summaryrefslogtreecommitdiff
path: root/tex/generic
diff options
context:
space:
mode:
authorContext Git Mirror Bot <phg42.2a@gmail.com>2015-09-11 12:15:06 +0200
committerContext Git Mirror Bot <phg42.2a@gmail.com>2015-09-11 12:15:06 +0200
commit31cd4d643836f69279b399acf864474c1283b8f5 (patch)
tree7e59492e32ef06e57bad0d4a4a953f7e7ba5b058 /tex/generic
parentf28043b96635a0845521fe0094a3863d7ff13b6d (diff)
downloadcontext-31cd4d643836f69279b399acf864474c1283b8f5.tar.gz
2015-09-11 11:05:00
Diffstat (limited to 'tex/generic')
-rw-r--r--tex/generic/context/luatex/luatex-fonts-inj.lua92
-rw-r--r--tex/generic/context/luatex/luatex-fonts-merged.lua1450
-rw-r--r--tex/generic/context/luatex/luatex-fonts-otn.lua1676
-rw-r--r--tex/generic/context/luatex/luatex-fonts.lua14
4 files changed, 1889 insertions, 1343 deletions
diff --git a/tex/generic/context/luatex/luatex-fonts-inj.lua b/tex/generic/context/luatex/luatex-fonts-inj.lua
index 10108a271..da1364d9d 100644
--- a/tex/generic/context/luatex/luatex-fonts-inj.lua
+++ b/tex/generic/context/luatex/luatex-fonts-inj.lua
@@ -204,7 +204,10 @@ function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmne
end
function injections.setpair(current,factor,rlmode,r2lflag,spec,injection) -- r2lflag & tfmchr not used
- local x, y, w, h = factor*spec[1], factor*spec[2], factor*spec[3], factor*spec[4]
+ local x = factor*spec[1]
+ local y = factor*spec[2]
+ local w = factor*spec[3]
+ local h = factor*spec[4]
if x ~= 0 or w ~= 0 or y ~= 0 or h ~= 0 then -- okay?
local yoffset = y - h
local leftkern = x -- both kerns are set in a pair kern compared
@@ -549,13 +552,13 @@ local function inject_marks(marks,marki,nofmarks)
else
-- kern(x) glyph(p) kern(w-x) mark(n)
-- ox = px - getfield(p,"width") + pn.markx - pp.leftkern
- --
+ --
-- According to Kai we don't need to handle leftkern here but I'm
- -- pretty sure I've run into a case where it was needed so maybe
+ -- pretty sure I've run into a case where it was needed so maybe
-- some day we need something more clever here.
- --
- if false then
- -- a mark with kerning
+ --
+ if false then
+ -- a mark with kerning
local leftkern = pp.leftkern
if leftkern then
ox = px - pn.markx - leftkern
@@ -724,7 +727,7 @@ local function inject_kerns(head,glist,ilist,length) -- not complete ! compare w
if leftkern and leftkern ~= 0 then
local t = find_tail(dp)
insert_node_after(dp,t,newkern(leftkern))
-setfield(p,"post",dp) -- currently we need to force a tail refresh
+ setfield(p,"post",dp) -- currently we need to force a tail refresh
end
end
end
@@ -735,7 +738,7 @@ setfield(p,"post",dp) -- currently we need to force a tail refresh
if leftkern and leftkern ~= 0 then
local t = find_tail(dr)
insert_node_after(dr,t,newkern(leftkern))
-setfield(p,"replace",dr) -- currently we need to force a tail refresh
+ setfield(p,"replace",dr) -- currently we need to force a tail refresh
end
end
else
@@ -798,7 +801,7 @@ local function inject_kerns_only(head,where)
trace(head,"kerns")
end
local n = head
- local p = nil
+ local p = nil -- disc node when non-nil
while n do
local id = getid(n)
if id == glyph_code then
@@ -814,7 +817,7 @@ local function inject_kerns_only(head,where)
if leftkern and leftkern ~= 0 then
local t = find_tail(d)
insert_node_after(d,t,newkern(leftkern))
-setfield(p,"post",d) -- currently we need to force a tail refresh
+ setfield(p,"post",d) -- currently we need to force a tail refresh
end
end
end
@@ -826,7 +829,7 @@ setfield(p,"post",d) -- currently we need to force a tail refresh
if leftkern and leftkern ~= 0 then
local t = find_tail(d)
insert_node_after(d,t,newkern(leftkern))
-setfield(p,"replace",d) -- currently we need to force a tail refresh
+ setfield(p,"replace",d) -- currently we need to force a tail refresh
end
end
else
@@ -839,6 +842,7 @@ setfield(p,"replace",d) -- currently we need to force a tail refresh
end
end
else
+ -- this is the most common case
local i = rawget(pn,"injections")
if i then
local leftkern = i.leftkern
@@ -848,8 +852,6 @@ setfield(p,"replace",d) -- currently we need to force a tail refresh
end
end
end
- else
- break
end
p = nil
elseif id == disc_code then
@@ -876,7 +878,6 @@ setfield(p,"replace",d) -- currently we need to force a tail refresh
setfield(n,"pre",h)
end
end
- -- weird
local d = getfield(n,"post")
if d then
local h = d
@@ -905,7 +906,7 @@ setfield(p,"replace",d) -- currently we need to force a tail refresh
local h = d
for n in traverse_id(glyph_code,d) do
if getsubtype(n) < 256 then
- local pn = rawget(properties,n) -- why can it be empty { }
+ local pn = rawget(properties,n)
if pn then
local i = rawget(pn,"replaceinjections")
if i then
@@ -943,7 +944,6 @@ local function inject_pairs_only(head,where)
if trace_injections then
trace(head,"pairs")
end
- --
local n = head
local p = nil -- disc node when non-nil
while n do
@@ -961,7 +961,7 @@ local function inject_pairs_only(head,where)
if leftkern and leftkern ~= 0 then
local t = find_tail(d)
insert_node_after(d,t,newkern(leftkern))
-setfield(p,"post",d) -- currently we need to force a tail refresh
+ setfield(p,"post",d) -- currently we need to force a tail refresh
end
-- local rightkern = i.rightkern
-- if rightkern and rightkern ~= 0 then
@@ -978,7 +978,7 @@ setfield(p,"post",d) -- currently we need to force a tail refresh
if leftkern and leftkern ~= 0 then
local t = find_tail(d)
insert_node_after(d,t,newkern(leftkern))
-setfield(p,"replace",d) -- currently we need to force a tail refresh
+ setfield(p,"replace",d) -- currently we need to force a tail refresh
end
-- local rightkern = i.rightkern
-- if rightkern and rightkern ~= 0 then
@@ -1004,24 +1004,22 @@ setfield(p,"replace",d) -- currently we need to force a tail refresh
-- this is the most common case
local i = rawget(pn,"injections")
if i then
- local yoffset = i.yoffset
- if yoffset and yoffset ~= 0 then
- setfield(n,"yoffset",yoffset)
- end
local leftkern = i.leftkern
if leftkern and leftkern ~= 0 then
- insert_node_before(head,n,newkern(leftkern))
+ head = insert_node_before(head,n,newkern(leftkern))
end
local rightkern = i.rightkern
if rightkern and rightkern ~= 0 then
insert_node_after(head,n,newkern(rightkern))
n = getnext(n) -- to be checked
end
+ local yoffset = i.yoffset
+ if yoffset and yoffset ~= 0 then
+ setfield(n,"yoffset",yoffset)
+ end
end
end
end
- else
- break
end
p = nil
elseif id == disc_code then
@@ -1030,16 +1028,12 @@ setfield(p,"replace",d) -- currently we need to force a tail refresh
local h = d
for n in traverse_id(glyph_code,d) do
if getsubtype(n) < 256 then
- local p = rawget(properties,n)
- if p then
- local i = rawget(p,"preinjections")
+ local pn = rawget(properties,n)
+ if pn then
+ local i = rawget(pn,"preinjections")
if i then
- local yoffset = i.yoffset
- if yoffset and yoffset ~= 0 then
- setfield(n,"yoffset",yoffset)
- end
local leftkern = i.leftkern
- if leftkern ~= 0 then
+ if leftkern and leftkern ~= 0 then
h = insert_node_before(h,n,newkern(leftkern))
end
local rightkern = i.rightkern
@@ -1047,6 +1041,10 @@ setfield(p,"replace",d) -- currently we need to force a tail refresh
insert_node_after(head,n,newkern(rightkern))
n = getnext(n) -- to be checked
end
+ local yoffset = i.yoffset
+ if yoffset and yoffset ~= 0 then
+ setfield(n,"yoffset",yoffset)
+ end
end
end
else
@@ -1062,14 +1060,10 @@ setfield(p,"replace",d) -- currently we need to force a tail refresh
local h = d
for n in traverse_id(glyph_code,d) do
if getsubtype(n) < 256 then
- local p = rawget(properties,n)
- if p then
- local i = rawget(p,"postinjections")
+ local pn = rawget(properties,n)
+ if pn then
+ local i = rawget(pn,"postinjections")
if i then
- local yoffset = i.yoffset
- if yoffset and yoffset ~= 0 then
- setfield(n,"yoffset",yoffset)
- end
local leftkern = i.leftkern
if leftkern and leftkern ~= 0 then
h = insert_node_before(h,n,newkern(leftkern))
@@ -1079,6 +1073,10 @@ setfield(p,"replace",d) -- currently we need to force a tail refresh
insert_node_after(head,n,newkern(rightkern))
n = getnext(n) -- to be checked
end
+ local yoffset = i.yoffset
+ if yoffset and yoffset ~= 0 then
+ setfield(n,"yoffset",yoffset)
+ end
end
end
else
@@ -1094,14 +1092,10 @@ setfield(p,"replace",d) -- currently we need to force a tail refresh
local h = d
for n in traverse_id(glyph_code,d) do
if getsubtype(n) < 256 then
- local p = rawget(properties,n)
- if p then
- local i = rawget(p,"replaceinjections")
+ local pn = rawget(properties,n)
+ if pn then
+ local i = rawget(pn,"replaceinjections")
if i then
- local yoffset = i.yoffset
- if yoffset and yoffset ~= 0 then
- setfield(n,"yoffset",yoffset)
- end
local leftkern = i.leftkern
if leftkern and leftkern ~= 0 then
h = insert_node_before(h,n,newkern(leftkern))
@@ -1111,6 +1105,10 @@ setfield(p,"replace",d) -- currently we need to force a tail refresh
insert_node_after(head,n,newkern(rightkern))
n = getnext(n) -- to be checked
end
+ local yoffset = i.yoffset
+ if yoffset and yoffset ~= 0 then
+ setfield(n,"yoffset",yoffset)
+ end
end
end
else
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index 75788d408..a255835cc 100644
--- a/tex/generic/context/luatex/luatex-fonts-merged.lua
+++ b/tex/generic/context/luatex/luatex-fonts-merged.lua
@@ -1,6 +1,6 @@
-- merged file : luatex-fonts-merged.lua
-- parent file : luatex-fonts.lua
--- merge date : 09/09/15 21:23:41
+-- merge date : 09/11/15 11:03:20
do -- begin closure to overcome local limits and interference
@@ -5832,6 +5832,7 @@ local readers=fonts.readers
local constructors=fonts.constructors
local encodings=fonts.encodings
local tfm=constructors.newhandler("tfm")
+tfm.version=1.000
local tfmfeatures=constructors.newfeatures("tfm")
local registertfmfeature=tfmfeatures.register
constructors.resolvevirtualtoo=false
@@ -10269,7 +10270,10 @@ function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmne
return dx,dy,nofregisteredcursives
end
function injections.setpair(current,factor,rlmode,r2lflag,spec,injection)
- local x,y,w,h=factor*spec[1],factor*spec[2],factor*spec[3],factor*spec[4]
+ local x=factor*spec[1]
+ local y=factor*spec[2]
+ local w=factor*spec[3]
+ local h=factor*spec[4]
if x~=0 or w~=0 or y~=0 or h~=0 then
local yoffset=y-h
local leftkern=x
@@ -10718,7 +10722,7 @@ local function inject_kerns(head,glist,ilist,length)
if leftkern and leftkern~=0 then
local t=find_tail(dp)
insert_node_after(dp,t,newkern(leftkern))
-setfield(p,"post",dp)
+ setfield(p,"post",dp)
end
end
end
@@ -10729,7 +10733,7 @@ setfield(p,"post",dp)
if leftkern and leftkern~=0 then
local t=find_tail(dr)
insert_node_after(dr,t,newkern(leftkern))
-setfield(p,"replace",dr)
+ setfield(p,"replace",dr)
end
end
else
@@ -10782,7 +10786,7 @@ local function inject_kerns_only(head,where)
trace(head,"kerns")
end
local n=head
- local p=nil
+ local p=nil
while n do
local id=getid(n)
if id==glyph_code then
@@ -10798,7 +10802,7 @@ local function inject_kerns_only(head,where)
if leftkern and leftkern~=0 then
local t=find_tail(d)
insert_node_after(d,t,newkern(leftkern))
-setfield(p,"post",d)
+ setfield(p,"post",d)
end
end
end
@@ -10810,7 +10814,7 @@ setfield(p,"post",d)
if leftkern and leftkern~=0 then
local t=find_tail(d)
insert_node_after(d,t,newkern(leftkern))
-setfield(p,"replace",d)
+ setfield(p,"replace",d)
end
end
else
@@ -10832,8 +10836,6 @@ setfield(p,"replace",d)
end
end
end
- else
- break
end
p=nil
elseif id==disc_code then
@@ -10888,7 +10890,7 @@ setfield(p,"replace",d)
local h=d
for n in traverse_id(glyph_code,d) do
if getsubtype(n)<256 then
- local pn=rawget(properties,n)
+ local pn=rawget(properties,n)
if pn then
local i=rawget(pn,"replaceinjections")
if i then
@@ -10941,7 +10943,7 @@ local function inject_pairs_only(head,where)
if leftkern and leftkern~=0 then
local t=find_tail(d)
insert_node_after(d,t,newkern(leftkern))
-setfield(p,"post",d)
+ setfield(p,"post",d)
end
end
end
@@ -10953,7 +10955,7 @@ setfield(p,"post",d)
if leftkern and leftkern~=0 then
local t=find_tail(d)
insert_node_after(d,t,newkern(leftkern))
-setfield(p,"replace",d)
+ setfield(p,"replace",d)
end
end
else
@@ -10968,24 +10970,22 @@ setfield(p,"replace",d)
else
local i=rawget(pn,"injections")
if i then
- local yoffset=i.yoffset
- if yoffset and yoffset~=0 then
- setfield(n,"yoffset",yoffset)
- end
local leftkern=i.leftkern
if leftkern and leftkern~=0 then
- insert_node_before(head,n,newkern(leftkern))
+ head=insert_node_before(head,n,newkern(leftkern))
end
local rightkern=i.rightkern
if rightkern and rightkern~=0 then
insert_node_after(head,n,newkern(rightkern))
n=getnext(n)
end
+ local yoffset=i.yoffset
+ if yoffset and yoffset~=0 then
+ setfield(n,"yoffset",yoffset)
+ end
end
end
end
- else
- break
end
p=nil
elseif id==disc_code then
@@ -10994,16 +10994,12 @@ setfield(p,"replace",d)
local h=d
for n in traverse_id(glyph_code,d) do
if getsubtype(n)<256 then
- local p=rawget(properties,n)
- if p then
- local i=rawget(p,"preinjections")
+ local pn=rawget(properties,n)
+ if pn then
+ local i=rawget(pn,"preinjections")
if i then
- local yoffset=i.yoffset
- if yoffset and yoffset~=0 then
- setfield(n,"yoffset",yoffset)
- end
local leftkern=i.leftkern
- if leftkern~=0 then
+ if leftkern and leftkern~=0 then
h=insert_node_before(h,n,newkern(leftkern))
end
local rightkern=i.rightkern
@@ -11011,6 +11007,10 @@ setfield(p,"replace",d)
insert_node_after(head,n,newkern(rightkern))
n=getnext(n)
end
+ local yoffset=i.yoffset
+ if yoffset and yoffset~=0 then
+ setfield(n,"yoffset",yoffset)
+ end
end
end
else
@@ -11026,14 +11026,10 @@ setfield(p,"replace",d)
local h=d
for n in traverse_id(glyph_code,d) do
if getsubtype(n)<256 then
- local p=rawget(properties,n)
- if p then
- local i=rawget(p,"postinjections")
+ local pn=rawget(properties,n)
+ if pn then
+ local i=rawget(pn,"postinjections")
if i then
- local yoffset=i.yoffset
- if yoffset and yoffset~=0 then
- setfield(n,"yoffset",yoffset)
- end
local leftkern=i.leftkern
if leftkern and leftkern~=0 then
h=insert_node_before(h,n,newkern(leftkern))
@@ -11043,6 +11039,10 @@ setfield(p,"replace",d)
insert_node_after(head,n,newkern(rightkern))
n=getnext(n)
end
+ local yoffset=i.yoffset
+ if yoffset and yoffset~=0 then
+ setfield(n,"yoffset",yoffset)
+ end
end
end
else
@@ -11058,14 +11058,10 @@ setfield(p,"replace",d)
local h=d
for n in traverse_id(glyph_code,d) do
if getsubtype(n)<256 then
- local p=rawget(properties,n)
- if p then
- local i=rawget(p,"replaceinjections")
+ local pn=rawget(properties,n)
+ if pn then
+ local i=rawget(pn,"replaceinjections")
if i then
- local yoffset=i.yoffset
- if yoffset and yoffset~=0 then
- setfield(n,"yoffset",yoffset)
- end
local leftkern=i.leftkern
if leftkern and leftkern~=0 then
h=insert_node_before(h,n,newkern(leftkern))
@@ -11075,6 +11071,10 @@ setfield(p,"replace",d)
insert_node_after(head,n,newkern(rightkern))
n=getnext(n)
end
+ local yoffset=i.yoffset
+ if yoffset and yoffset~=0 then
+ setfield(n,"yoffset",yoffset)
+ end
end
end
else
@@ -11527,7 +11527,6 @@ local trace_kernruns=false registertracker("otf.kernruns",function(v) trace_kern
local trace_discruns=false registertracker("otf.discruns",function(v) trace_discruns=v end)
local trace_compruns=false registertracker("otf.compruns",function(v) trace_compruns=v end)
local quit_on_no_replacement=true
-local check_discretionaries=true
local zwnjruns=true
registerdirective("otf.zwnjruns",function(v) zwnjruns=v end)
registerdirective("otf.chain.quitonnoreplacement",function(value) quit_on_no_replacement=value end)
@@ -11589,8 +11588,6 @@ local math_code=nodecodes.math
local dir_code=whatcodes.dir
local localpar_code=whatcodes.localpar
local discretionary_code=disccodes.discretionary
-local regular_code=disccodes.regular
-local automatic_code=disccodes.automatic
local ligature_code=glyphcodes.ligature
local privateattribute=attributes.private
local a_state=privateattribute('state')
@@ -11624,6 +11621,13 @@ local lookuptags=false
local handlers={}
local rlmode=0
local featurevalue=false
+local sweephead={}
+local sweepnode=nil
+local sweepprev=nil
+local sweepnext=nil
+local notmatchpre={}
+local notmatchpost={}
+local notmatchreplace={}
local checkstep=(nodes and nodes.tracers and nodes.tracers.steppers.check) or function() end
local registerstep=(nodes and nodes.tracers and nodes.tracers.steppers.register) or function() end
local registermessage=(nodes and nodes.tracers and nodes.tracers.steppers.message) or function() end
@@ -11693,46 +11697,63 @@ local function copy_glyph(g)
return n
end
end
-local function collapse_disc(start,next)
- local replace1=getfield(start,"replace")
- local replace2=getfield(next,"replace")
- if replace1 and replace2 then
- local pre2=getfield(next,"pre")
- local post2=getfield(next,"post")
- setfield(replace1,"prev",nil)
- if pre2 then
- local pre1=getfield(start,"pre")
- if pre1 then
- flush_node_list(pre1)
- end
- local pre1=copy_node_list(replace1)
- local tail1=find_node_tail(pre1)
- setfield(tail1,"next",pre2)
- setfield(pre2,"prev",tail1)
- setfield(start,"pre",pre1)
- setfield(next,"pre",nil)
+local function flattendisk(head,disc)
+ local replace=getfield(disc,"replace")
+ setfield(disc,"replace",nil)
+ free_node(disc)
+ if head==disc then
+ local next=getnext(disc)
+ if replace then
+ if next then
+ local tail=find_node_tail(replace)
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
+ end
+ return replace,replace
+ elseif next then
+ return next,next
else
- setfield(start,"pre",nil)
+ return
end
- if post2 then
- local post1=getfield(start,"post")
- if post1 then
- flush_node_list(post1)
+ else
+ local next=getnext(disc)
+ local prev=getprev(disc)
+ if replace then
+ local tail=find_node_tail(replace)
+ if next then
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
end
- setfield(start,"post",post2)
+ setfield(prev,"next",replace)
+ setfield(replace,"prev",prev)
+ return head,replace
else
- setfield(start,"post",nil)
+ if next then
+ setfield(next,"prev",prev)
+ end
+ setfield(prev,"next",next)
+ return head,next
end
- local tail1=find_node_tail(replace1)
- setfield(tail1,"next",replace2)
- setfield(replace2,"prev",tail1)
- setfield(start,"replace",replace1)
- setfield(next,"replace",nil)
- local nextnext=getnext(next)
- setfield(nextnext,"prev",start)
- setfield(start,"next",nextnext)
- free_node(next)
+ end
+end
+local function appenddisc(disc,list)
+ local post=getfield(disc,"post")
+ local replace=getfield(disc,"replace")
+ local phead=list
+ local rhead=copy_node_list(list)
+ local ptail=find_node_tail(post)
+ local rtail=find_node_tail(replace)
+ if post then
+ setfield(ptail,"next",phead)
+ setfield(phead,"prev",ptail)
+ else
+ setfield(disc,"post",phead)
+ end
+ if replace then
+ setfield(rtail,"next",rhead)
+ setfield(rhead,"prev",rtail)
else
+ setfield(disc,"replace",rhead)
end
end
local function markstoligature(kind,lookupname,head,start,stop,char)
@@ -11762,8 +11783,8 @@ local function markstoligature(kind,lookupname,head,start,stop,char)
return head,base
end
end
-local function getcomponentindex(start)
- if getid(start)~=glyph_code then
+local function getcomponentindex(start)
+ if getid(start)~=glyph_code then
return 0
elseif getsubtype(start)==ligature_code then
local i=0
@@ -11780,50 +11801,6 @@ local function getcomponentindex(start)
end
end
local a_noligature=attributes.private("noligature")
-local prehyphenchar=languages and languages.prehyphenchar
-local posthyphenchar=languages and languages.posthyphenchar
-if prehyphenchar then
-elseif context then
- report_warning("no language support") os.exit()
-else
- local newlang=lang.new
- local getpre=lang.prehyphenchar
- local getpost=lang.posthyphenchar
- prehyphenchar=function(l) local l=newlang(l) return l and getpre (l) or -1 end
- posthyphenchar=function(l) local l=newlang(l) return l and getpost (l) or -1 end
-end
-local function addhyphens(template,pre,post)
- local l=getfield(template,"lang")
- local p=prehyphenchar(l)
- if p and p>0 then
- local c=copy_node(template)
- setfield(c,"char",p)
- if pre then
- local t=find_node_tail(pre)
- setfield(t,"next",c)
- setfield(c,"prev",t)
- else
- pre=c
- end
- end
- local p=posthyphenchar(l)
- if p and p>0 then
- local c=copy_node(template)
- setfield(c,"char",p)
- if post then
- local prev=getprev(post)
- setfield(c,"next",post)
- setfield(post,"prev",c)
- if prev then
- setfield(prev,"next",c)
- setfield(c,"prev",prev)
- end
- else
- post=c
- end
- end
- return pre,post
-end
local function toligature(kind,lookupname,head,start,stop,char,markflag,discfound)
if getattr(start,a_noligature)==1 then
return head,start
@@ -11855,8 +11832,8 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
if next then
setfield(next,"prev",base)
end
- setfield(base,"next",next)
setfield(base,"prev",prev)
+ setfield(base,"next",next)
if not discfound then
local deletemarks=markflag~="mark"
local components=start
@@ -11899,51 +11876,31 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
local discprev=getfield(discfound,"prev")
local discnext=getfield(discfound,"next")
if discprev and discnext then
- local subtype=getsubtype(discfound)
- if subtype==discretionary_code then
- local pre=getfield(discfound,"pre")
- local post=getfield(discfound,"post")
- local replace=getfield(discfound,"replace")
- if not replace then
- local prev=getfield(base,"prev")
- local copied=copy_node_list(comp)
- setfield(discnext,"prev",nil)
- setfield(discprev,"next",nil)
- if pre then
- setfield(discprev,"next",pre)
- setfield(pre,"prev",discprev)
- end
- pre=comp
- if post then
- local tail=find_node_tail(post)
- setfield(tail,"next",discnext)
- setfield(discnext,"prev",tail)
- setfield(post,"prev",nil)
- else
- post=discnext
- end
- setfield(prev,"next",discfound)
- setfield(next,"prev",discfound)
- setfield(discfound,"next",next)
- setfield(discfound,"prev",prev)
- setfield(base,"next",nil)
- setfield(base,"prev",nil)
- setfield(base,"components",copied)
- setfield(discfound,"pre",pre)
- setfield(discfound,"post",post)
- setfield(discfound,"replace",base)
- setfield(discfound,"subtype",discretionary_code)
- base=prev
- end
- elseif subtype==regular_code then
+ local pre=getfield(discfound,"pre")
+ local post=getfield(discfound,"post")
+ local replace=getfield(discfound,"replace")
+ if not replace then
+ local prev=getfield(base,"prev")
local copied=copy_node_list(comp)
setfield(discnext,"prev",nil)
setfield(discprev,"next",nil)
- local pre,post=addhyphens(comp,comp,discnext,subtype)
+ if pre then
+ setfield(discprev,"next",pre)
+ setfield(pre,"prev",discprev)
+ end
+ pre=comp
+ if post then
+ local tail=find_node_tail(post)
+ setfield(tail,"next",discnext)
+ setfield(discnext,"prev",tail)
+ setfield(post,"prev",nil)
+ else
+ post=discnext
+ end
setfield(prev,"next",discfound)
- setfield(next,"prev",discfound)
- setfield(discfound,"next",next)
setfield(discfound,"prev",prev)
+ setfield(discfound,"next",next)
+ setfield(next,"prev",discfound)
setfield(base,"next",nil)
setfield(base,"prev",nil)
setfield(base,"components",copied)
@@ -11951,20 +11908,39 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
setfield(discfound,"post",post)
setfield(discfound,"replace",base)
setfield(discfound,"subtype",discretionary_code)
- base=next
- else
+ base=prev
end
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(getchar(start)),gref(replacement))
+local function multiple_glyphs(head,start,multiple,ignoremarks)
+ local nofmultiples=#multiple
+ if nofmultiples>0 then
+ resetinjection(start)
+ setfield(start,"char",multiple[1])
+ if nofmultiples>1 then
+ local sn=getnext(start)
+ for k=2,nofmultiples do
+ local n=copy_node(start)
+ resetinjection(n)
+ setfield(n,"char",multiple[k])
+ setfield(n,"prev",start)
+ setfield(n,"next",sn)
+ if sn then
+ setfield(sn,"prev",n)
+ end
+ setfield(start,"next",n)
+ start=n
+ end
+ end
+ return head,start,true
+ else
+ if trace_multiples then
+ logprocess("no multiple for %s",gref(getchar(start)))
+ end
+ return head,start,false
end
- resetinjection(start)
- setfield(start,"char",replacement)
- return head,start,true
end
local function get_alternative_glyph(start,alternatives,value,trace_alternatives)
local n=#alternatives
@@ -11997,33 +11973,13 @@ local function get_alternative_glyph(start,alternatives,value,trace_alternatives
end
end
end
-local function multiple_glyphs(head,start,multiple,ignoremarks)
- local nofmultiples=#multiple
- if nofmultiples>0 then
- resetinjection(start)
- setfield(start,"char",multiple[1])
- if nofmultiples>1 then
- local sn=getnext(start)
- for k=2,nofmultiples do
- local n=copy_node(start)
- resetinjection(n)
- setfield(n,"char",multiple[k])
- setfield(n,"next",sn)
- setfield(n,"prev",start)
- if sn then
- setfield(sn,"prev",n)
- end
- setfield(start,"next",n)
- start=n
- end
- end
- return head,start,true
- else
- if trace_multiples then
- logprocess("no multiple for %s",gref(getchar(start)))
- end
- return head,start,false
+function handlers.gsub_single(head,start,kind,lookupname,replacement)
+ if trace_singles then
+ logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(getchar(start)),gref(replacement))
end
+ resetinjection(start)
+ setfield(start,"char",replacement)
+ return head,start,true
end
function handlers.gsub_alternate(head,start,kind,lookupname,alternative,sequence)
local value=featurevalue==true and tfmdata.shared.features[kind] or featurevalue
@@ -12138,6 +12094,65 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
end
return head,start,false,discfound
end
+function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence,injection)
+ local startchar=getchar(start)
+ local dx,dy,w,h=setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,injection)
+ 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)
+ end
+ return head,start,false
+end
+function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence,lookuphash,i,injection)
+ local snext=getnext(start)
+ if not snext then
+ return head,start,false
+ else
+ local prev=start
+ local done=false
+ local factor=tfmdata.parameters.factor
+ local lookuptype=lookuptypes[lookupname]
+ 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=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 x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,injection)
+ if trace_kerns then
+ local startchar=getchar(start)
+ logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
+ end
+ end
+ if b and #b>0 then
+ local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,injection)
+ if trace_kerns then
+ local startchar=getchar(start)
+ 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)
+ end
+ end
+ else
+ report_process("%s: check this out (old kern stuff)",pref(kind,lookupname))
+ end
+ done=true
+ elseif krn~=0 then
+ local k=setkern(snext,factor,rlmode,krn,injection)
+ if trace_kerns then
+ logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar))
+ end
+ done=true
+ end
+ break
+ end
+ end
+ return head,start,done
+ end
+end
function handlers.gpos_mark2base(head,start,kind,lookupname,markanchors,sequence)
local markchar=getchar(start)
if marks[markchar] then
@@ -12368,65 +12383,6 @@ function handlers.gpos_cursive(head,start,kind,lookupname,exitanchors,sequence)
return head,start,false
end
end
-function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence,injection)
- local startchar=getchar(start)
- local dx,dy,w,h=setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,injection)
- 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)
- end
- return head,start,false
-end
-function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence,lookuphash,i,injection)
- 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 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=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=getchar(start)
- local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,injection)
- 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=getchar(start)
- local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,injection)
- 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)
- end
- end
- else
- report_process("%s: check this out (old kern stuff)",pref(kind,lookupname))
- end
- done=true
- elseif krn~=0 then
- local k=setkern(snext,factor,rlmode,krn,injection)
- if trace_kerns then
- logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar))
- end
- done=true
- end
- break
- end
- end
- return head,start,done
- end
-end
-local chainmores={}
local chainprocs={}
local function logprocess(...)
if trace_steps then
@@ -12446,10 +12402,6 @@ function chainprocs.chainsub(head,start,stop,kind,chainname,currentcontext,looku
logwarning("%s: a direct call to chainsub cannot happen",cref(kind,chainname,chainlookupname))
return head,start,false
end
-function chainmores.chainsub(head,start,stop,kind,chainname,currentcontext,lookuphash,lookuplist,chainlookupname,n)
- logprocess("%s: a direct call to chainsub cannot happen",cref(kind,chainname,chainlookupname))
- return head,start,false
-end
function chainprocs.reversesub(head,start,stop,kind,chainname,currentcontext,lookuphash,replacements)
local char=getchar(start)
local replacement=replacements[char]
@@ -12490,80 +12442,7 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo
logprocess("%s: replacing single %s by %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(currentchar),gref(replacement))
end
resetinjection(current)
- if check_discretionaries then
- local next=getnext(current)
- local prev=getprev(current)
- local done=false
- if next then
- if getid(next)==disc_code then
- local subtype=getsubtype(next)
- if subtype==discretionary_code then
- setfield(next,"prev",prev)
- setfield(prev,"next",next)
- setfield(current,"prev",nil)
- setfield(current,"next",nil)
- local replace=getfield(next,"replace")
- local pre=getfield(next,"pre")
- local new=copy_node(current)
- setfield(new,"char",replacement)
- if replace then
- setfield(new,"next",replace)
- setfield(replace,"prev",new)
- end
- if pre then
- setfield(current,"next",pre)
- setfield(pre,"prev",current)
- end
- setfield(next,"replace",new)
- setfield(next,"pre",current)
- end
- start=next
- done=true
- local next=getnext(start)
- if next and getid(next)==disc_code then
- collapse_disc(start,next)
- end
- end
- end
- if not done and prev then
- if getid(prev)==disc_code then
- local subtype=getsubtype(prev)
- if subtype==discretionary_code then
- setfield(next,"prev",prev)
- setfield(prev,"next",next)
- setfield(current,"prev",nil)
- setfield(current,"next",nil)
- local replace=getfield(prev,"replace")
- local post=getfield(prev,"post")
- local new=copy_node(current)
- setfield(new,"char",replacement)
- if replace then
- local tail=find_node_tail(replace)
- setfield(tail,"next",new)
- setfield(new,"prev",tail)
- else
- replace=new
- end
- if post then
- local tail=find_node_tail(post)
- setfield(tail,"next",current)
- setfield(current,"prev",tail)
- else
- post=current
- end
- setfield(prev,"replace",replace)
- setfield(prev,"post",post)
- start=prev
- done=true
- end
- end
- end
- if not done then
- setfield(current,"char",replacement)
- end
- else
- setfield(current,"char",replacement)
- end
+ setfield(current,"char",replacement)
end
end
return head,start,true
@@ -12575,7 +12454,6 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo
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=getchar(start)
local subtables=currentlookup.subtables
@@ -12600,7 +12478,6 @@ function chainprocs.gsub_multiple(head,start,stop,kind,chainname,currentcontext,
end
return head,start,false
end
-chainmores.gsub_multiple=chainprocs.gsub_multiple
function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
local current=start
local subtables=currentlookup.subtables
@@ -12642,7 +12519,6 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext
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=getchar(start)
local subtables=currentlookup.subtables
@@ -12677,7 +12553,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
end
else
local schar=getchar(s)
- if skipmark and marks[schar] then
+ if skipmark and marks[schar] then
s=getnext(s)
else
local lg=ligatures[schar]
@@ -12719,7 +12595,80 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
end
return head,start,false,0,false
end
-chainmores.gsub_ligature=chainprocs.gsub_ligature
+function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
+ local startchar=getchar(start)
+ local subtables=currentlookup.subtables
+ local lookupname=subtables[1]
+ local kerns=lookuphash[lookupname]
+ if kerns then
+ kerns=kerns[startchar]
+ if kerns then
+ local dx,dy,w,h=setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns)
+ if trace_kerns then
+ logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),dx,dy,w,h)
+ end
+ end
+ end
+ return head,start,false
+end
+function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
+ local snext=getnext(start)
+ if snext then
+ local startchar=getchar(start)
+ local subtables=currentlookup.subtables
+ local lookupname=subtables[1]
+ local kerns=lookuphash[lookupname]
+ if kerns then
+ kerns=kerns[startchar]
+ if kerns then
+ local lookuptype=lookuptypes[lookupname]
+ local prev,done=start,false
+ local factor=tfmdata.parameters.factor
+ 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=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=getchar(start)
+ local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a)
+ 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=getchar(start)
+ local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b)
+ 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)
+ end
+ end
+ else
+ report_process("%s: check this out (old kern stuff)",cref(kind,chainname,chainlookupname))
+ end
+ done=true
+ 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(getchar(prev)),gref(nextchar))
+ end
+ done=true
+ end
+ break
+ end
+ end
+ return head,start,done
+ end
+ end
+ end
+ return head,start,false
+end
function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
local markchar=getchar(start)
if marks[markchar] then
@@ -12970,99 +12919,286 @@ function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,l
end
return head,start,false
end
-function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
- local startchar=getchar(start)
- local subtables=currentlookup.subtables
- local lookupname=subtables[1]
- local kerns=lookuphash[lookupname]
- if kerns then
- kerns=kerns[startchar]
- if kerns then
- local dx,dy,w,h=setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns)
- if trace_kerns then
- logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),dx,dy,w,h)
+local function show_skip(kind,chainname,char,ck,class)
+ if ck[9] then
+ logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a, %a => %a",cref(kind,chainname),gref(char),class,ck[1],ck[2],ck[9],ck[10])
+ else
+ logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a",cref(kind,chainname),gref(char),class,ck[1],ck[2])
+ end
+end
+local function chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,chainindex,sequence,chainproc)
+ if not start then
+ return head,start,false
+ end
+ local startishead=start==head
+ local seq=ck[3]
+ local f=ck[4]
+ local l=ck[5]
+ local s=#seq
+ local done=false
+ local sweepnode=sweepnode
+ local sweeptype=sweeptype
+ local sweepoverflow=false
+ local checkdisc=getprev(head)
+ local keepdisc=not sweepnode
+ local lookaheaddisc=nil
+ local backtrackdisc=nil
+ local current=start
+ local last=start
+ local prev=getprev(start)
+ local i=f
+ while i<=l do
+ local id=getid(current)
+ if id==glyph_code then
+ i=i+1
+ last=current
+ current=getnext(current)
+ elseif id==disc_code then
+ if keepdisc then
+ keepdisc=false
+ if notmatchpre[current]~=notmatchreplace[current] then
+ lookaheaddisc=current
+ end
+ local replace=getfield(current,"replace")
+ while replace and i<=l do
+ if getid(replace)==glyph_code then
+ i=i+1
+ end
+ replace=getnext(replace)
+ end
+ last=current
+ current=getnext(c)
+ else
+ head,current=flattendisk(head,current)
+ end
+ else
+ last=current
+ current=getnext(current)
+ end
+ if current then
+ elseif sweepoverflow then
+ break
+ elseif sweeptype=="post" or sweeptype=="replace" then
+ current=getnext(sweepnode)
+ if current then
+ sweeptype=nil
+ sweepoverflow=true
+ else
+ break
end
end
end
- return head,start,false
-end
-chainmores.gpos_single=chainprocs.gpos_single
-function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
- local snext=getnext(start)
- if snext then
- local startchar=getchar(start)
- local subtables=currentlookup.subtables
- local lookupname=subtables[1]
- local kerns=lookuphash[lookupname]
- if kerns then
- kerns=kerns[startchar]
- if kerns then
- local lookuptype=lookuptypes[lookupname]
- local prev,done=start,false
- local factor=tfmdata.parameters.factor
- 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=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=getchar(start)
- local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a)
- 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=getchar(start)
- local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b)
- 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)
- end
- end
- else
- report_process("%s: check this out (old kern stuff)",cref(kind,chainname,chainlookupname))
- end
- done=true
- 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(getchar(prev)),gref(nextchar))
- end
- done=true
+ if sweepoverflow then
+ local prev=current and getprev(current)
+ if not current or prev~=sweepnode then
+ local head=getnext(sweepnode)
+ local tail=nil
+ if prev then
+ tail=prev
+ setfield(current,"prev",sweepnode)
+ else
+ tail=find_node_tail(head)
+ end
+ setfield(sweepnode,"next",current)
+ setfield(head,"prev",nil)
+ setfield(tail,"next",nil)
+ appenddisc(sweepnode,head)
+ end
+ end
+ if l<s then
+ local i=l
+ local t=sweeptype=="post" or sweeptype=="replace"
+ while current and i<s do
+ local id=getid(current)
+ if id==glyph_code then
+ i=i+1
+ current=getnext(current)
+ elseif id==disc_code then
+ if keepdisc then
+ keepdisc=false
+ if notmatchpre[current]~=notmatchreplace[current] then
+ lookaheaddisc=current
+ end
+ local replace=getfield(c,"replace")
+ while replace and i<s do
+ if getid(replace)==glyph_code then
+ i=i+1
end
- break
+ replace=getnext(replace)
+ end
+ current=getnext(current)
+ elseif notmatchpre[current]~=notmatchreplace[current] then
+ head,current=flattendisk(head,current)
+ else
+ current=getnext(current)
+ end
+ else
+ current=getnext(current)
+ end
+ if not current and t then
+ current=getnext(sweepnode)
+ if current then
+ sweeptype=nil
+ end
+ end
+ end
+ end
+ if f>1 then
+ local current=prev
+ local i=f
+ local t=sweeptype=="pre" or sweeptype=="replace"
+ if not current and t and current==checkdisk then
+ current=getprev(sweepnode)
+ end
+ while current and i>1 do
+ local id=getid(current)
+ if id==glyph_code then
+ i=i-1
+ elseif id==disc_code then
+ if keepdisc then
+ keepdisc=false
+ if notmatchpost[current]~=notmatchreplace[current] then
+ backtrackdisc=current
end
+ local replace=getfield(current,"replace")
+ while replace and i>1 do
+ if getid(replace)==glyph_code then
+ i=i-1
+ end
+ replace=getnext(replace)
+ end
+ elseif notmatchpost[current]~=notmatchreplace[current] then
+ head,current=flattendisk(head,current)
end
- return head,start,done
+ end
+ current=getprev(current)
+ if t and current==checkdisk then
+ current=getprev(sweepnode)
end
end
end
- return head,start,false
-end
-chainmores.gpos_pair=chainprocs.gpos_pair
-local function show_skip(kind,chainname,char,ck,class)
- if ck[9] then
- logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a, %a => %a",cref(kind,chainname),gref(char),class,ck[1],ck[2],ck[9],ck[10])
+ local ok=false
+ if lookaheaddisc then
+ local cf=start
+ local cl=getprev(lookaheaddisc)
+ local cprev=getprev(start)
+ local insertedmarks=0
+ while cprev and getid(cf)==glyph_code and getfont(cf)==currentfont and getsubtype(cf)<256 and marks[getchar(cf)] do
+ insertedmarks=insertedmarks+1
+ cf=cprev
+ startishead=cf==head
+ cprev=getprev(cprev)
+ end
+ setfield(lookaheaddisc,"prev",cprev)
+ if cprev then
+ setfield(cprev,"next",lookaheaddisc)
+ end
+ setfield(cf,"prev",nil)
+ setfield(cl,"next",nil)
+ if startishead then
+ head=lookaheaddisc
+ end
+ local replace=getfield(lookaheaddisc,"replace")
+ local pre=getfield(lookaheaddisc,"pre")
+ local new=copy_node_list(cf)
+ local cnew=new
+ for i=1,insertedmarks do
+ cnew=getnext(cnew)
+ end
+ local clast=cnew
+ for i=f,l do
+ clast=getnext(clast)
+ end
+ if not notmatchpre[lookaheaddisc] then
+ cf,start,ok=chainproc(cf,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
+ if not notmatchreplace[lookaheaddisc] then
+ new,cnew,ok=chainproc(new,cnew,clast,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
+ if pre then
+ setfield(cl,"next",pre)
+ setfield(pre,"prev",cl)
+ end
+ if replace then
+ local tail=find_node_tail(new)
+ setfield(tail,"next",replace)
+ setfield(replace,"prev",tail)
+ end
+ setfield(lookaheaddisc,"pre",cf)
+ setfield(lookaheaddisc,"replace",new)
+ start=getprev(lookaheaddisc)
+ sweephead[cf]=getnext(clast)
+ sweephead[new]=getnext(last)
+ elseif backtrackdisc then
+ local cf=getnext(backtrackdisc)
+ local cl=start
+ local cnext=getnext(start)
+ local insertedmarks=0
+ while cnext and getid(cnext)==glyph_code and getfont(cnext)==currentfont and getsubtype(cnext)<256 and marks[getchar(cnext)] do
+ insertedmarks=insertedmarks+1
+ cl=cnext
+ cnext=getnext(cnext)
+ end
+ if cnext then
+ setfield(cnext,"prev",backtrackdisc)
+ end
+ setfield(backtrackdisc,"next",cnext)
+ setfield(cf,"prev",nil)
+ setfield(cl,"next",nil)
+ local replace=getfield(backtrackdisc,"replace")
+ local post=getfield(backtrackdisc,"post")
+ local new=copy_node_list(cf)
+ local cnew=find_node_tail(new)
+ for i=1,insertedmarks do
+ cnew=getprev(cnew)
+ end
+ local clast=cnew
+ for i=f,l do
+ clast=getnext(clast)
+ end
+ if not notmatchpost[backtrackdisc] then
+ cf,start,ok=chainproc(cf,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
+ if not notmatchreplace[backtrackdisc] then
+ new,cnew,ok=chainproc(new,cnew,clast,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
+ if post then
+ local tail=find_node_tail(post)
+ setfield(tail,"next",cf)
+ setfield(cf,"prev",tail)
+ else
+ post=cf
+ end
+ if replace then
+ local tail=find_node_tail(replace)
+ setfield(tail,"next",new)
+ setfield(new,"prev",tail)
+ else
+ replace=new
+ end
+ setfield(backtrackdisc,"post",post)
+ setfield(backtrackdisc,"replace",replace)
+ start=getprev(backtrackdisc)
+ sweephead[post]=getnext(clast)
+ sweephead[replace]=getnext(last)
else
- logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a",cref(kind,chainname),gref(char),class,ck[1],ck[2])
+ head,start,ok=chainproc(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
end
+ return head,start,ok
end
local function normal_handle_contextchain(head,start,kind,chainname,contexts,sequence,lookuphash)
+ local sweepnode=sweepnode
+ local sweeptype=sweeptype
+ local diskseen=false
+ local checkdisc=getprev(head)
local flags=sequence.flags
local done=false
local skipmark=flags[1]
local skipligature=flags[2]
local skipbase=flags[3]
- local someskip=skipmark or skipligature or skipbase
- local markclass=sequence.markclass
+ local markclass=sequence.markclass
local skipped=false
- for k=1,#contexts do
+ for k=1,#contexts do
local match=true
local current=start
local last=start
@@ -13072,14 +13208,20 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
if s==1 then
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]
+ local f=ck[4]
+ local l=ck[5]
if f==1 and f==l then
else
if f==l then
else
+ local discfound=nil
local n=f+1
last=getnext(last)
while n<=l do
+ if not last and (sweeptype=="post" or sweeptype=="replace") then
+ last=getnext(sweepnode)
+ sweeptype=nil
+ end
if last then
local id=getid(last)
if id==glyph_code then
@@ -13087,7 +13229,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
local char=getchar(last)
local ccd=descriptions[char]
if ccd then
- local class=ccd.class
+ local class=ccd.class or "base"
if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then
skipped=true
if trace_skips then
@@ -13100,46 +13242,77 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
n=n+1
else
- match=false
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpre[discfound]
+ else
+ match=false
+ end
break
end
else
- match=false
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpre[discfound]
+ else
+ match=false
+ end
break
end
else
- match=false
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpre[discfound]
+ else
+ match=false
+ end
break
end
elseif id==disc_code then
- if check_discretionaries then
- local replace=getfield(last,"replace")
- if replace then
- while replace do
- if seq[n][getchar(replace)] then
- n=n+1
- replace=getnext(replace)
- if not replace then
- break
- elseif n>l then
- break
- end
- else
- match=false
+ diskseen=true
+ discfound=last
+ notmatchpre[last]=nil
+ notmatchpost[last]=true
+ notmatchreplace[last]=nil
+ local pre=getfield(last,"pre")
+ local replace=getfield(last,"replace")
+ if pre then
+ local n=n
+ while pre do
+ if seq[n][getchar(pre)] then
+ n=n+1
+ pre=getnext(pre)
+ if n>l then
break
end
- end
- if not match then
+ else
+ notmatchpre[last]=true
break
- elseif check_discretionaries=="trace" then
- report_chain("check disc action in current")
end
- else
- last=getnext(last)
+ end
+ if n<=l then
+ notmatchpre[last]=true
end
else
- last=getnext(last)
+ notmatchpre[last]=true
end
+ if replace then
+ while replace do
+ if seq[n][getchar(replace)] then
+ n=n+1
+ replace=getnext(replace)
+ if n>l then
+ break
+ end
+ else
+ notmatchreplace[last]=true
+ match=not notmatchpre[last]
+ break
+ end
+ end
+ match=not notmatchpre[last]
+ end
+ last=getnext(last)
else
match=false
break
@@ -13154,77 +13327,132 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
if match and f>1 then
local prev=getprev(start)
if prev then
- local n=f-1
- while n>=1 do
- if prev then
- local id=getid(prev)
- if id==glyph_code then
- if getfont(prev)==currentfont and getsubtype(prev)<256 then
- local char=getchar(prev)
- local ccd=descriptions[char]
- if ccd then
- local class=ccd.class
- if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then
- skipped=true
- if trace_skips then
- show_skip(kind,chainname,char,ck,class)
+ if prev==checkdisc and (sweeptype=="pre" or sweeptype=="replace") then
+ prev=getprev(sweepnode)
+ end
+ if prev then
+ local discfound=nil
+ local n=f-1
+ while n>=1 do
+ if prev then
+ local id=getid(prev)
+ if id==glyph_code then
+ if getfont(prev)==currentfont and getsubtype(prev)<256 then
+ local char=getchar(prev)
+ local ccd=descriptions[char]
+ if ccd then
+ local class=ccd.class
+ if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then
+ skipped=true
+ if trace_skips then
+ show_skip(kind,chainname,char,ck,class)
+ end
+ elseif seq[n][char] then
+ n=n -1
+ else
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpost[discfound]
+ else
+ match=false
+ end
+ break
end
- elseif seq[n][char] then
- n=n -1
else
- match=false
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpost[discfound]
+ else
+ match=false
+ end
break
end
else
- match=false
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpost[discfound]
+ else
+ match=false
+ end
break
end
- else
- match=false
- break
- end
- elseif id==disc_code then
- if check_discretionaries then
+ elseif id==disc_code then
+ diskseen=true
+ discfound=prev
+ notmatchpre[prev]=true
+ notmatchpost[prev]=nil
+ notmatchreplace[prev]=nil
+ local pre=getfield(prev,"pre")
+ local post=getfield(prev,"post")
local replace=getfield(prev,"replace")
- if replace then
- replace=find_node_tail(replace)
- local finish=getprev(replace)
- while replace do
- if seq[n][getchar(replace)] then
- n=n-1
- replace=getprev(replace)
- if not replace or replace==finish then
+ if pre~=start and post~=start and replace~=start then
+ if post then
+ local n=n
+ local posttail=find_node_tail(post)
+ while posttail do
+ if seq[n][getchar(posttail)] then
+ n=n-1
+ if posttail==post then
+ break
+ else
+ posttail=getprev(posttail)
+ if n<1 then
+ break
+ end
+ end
+ else
+ notmatchpost[prev]=true
break
- elseif n<1 then
+ end
+ end
+ if n>=1 then
+ notmatchpost[prev]=true
+ end
+ else
+ notmatchpost[prev]=true
+ end
+ if replace then
+ local replacetail=find_node_tail(replace)
+ while replacetail do
+ if seq[n][getchar(replacetail)] then
+ n=n-1
+ if replacetail==replace then
+ break
+ else
+ replacetail=getprev(replacetail)
+ if n<1 then
+ break
+ end
+ end
+ else
+ notmatchreplace[prev]=true
+ match=not notmatchpost[prev]
break
end
- else
- match=false
+ end
+ if not match then
break
end
- end
- if not match then
- break
- elseif check_discretionaries=="trace" then
- report_chain("check disc action in before")
+ else
end
else
end
+ elseif seq[n][32] then
+ n=n -1
else
+ match=false
+ break
end
- elseif seq[n][32] then
- n=n -1
+ prev=getprev(prev)
+ elseif seq[n][32] then
+ n=n-1
else
match=false
break
end
- prev=getprev(prev)
- elseif seq[n][32] then
- n=n-1
- else
- match=false
- break
end
+ else
+ match=false
end
else
match=false
@@ -13232,7 +13460,13 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
if match and s>l then
local current=last and getnext(last)
+ if not current then
+ if sweeptype=="post" or sweeptype=="replace" then
+ current=getnext(sweepnode)
+ end
+ end
if current then
+ local discfound=nil
local n=l+1
while n<=s do
if current then
@@ -13251,41 +13485,76 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
elseif seq[n][char] then
n=n+1
else
- match=false
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpre[discfound]
+ else
+ match=false
+ end
break
end
else
- match=false
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpre[discfound]
+ else
+ match=false
+ end
break
end
else
- match=false
+ if discfound then
+ notmatchreplace[discfound]=true
+ match=not notmatchpre[discfound]
+ else
+ match=false
+ end
break
end
elseif id==disc_code then
- if check_discretionaries then
- local replace=getfield(current,"replace")
- if replace then
- while replace do
- if seq[n][getchar(replace)] then
- n=n+1
- replace=getnext(replace)
- if not replace then
- break
- elseif n>s then
- break
- end
- else
- match=false
+ diskseen=true
+ discfound=current
+ notmatchpre[current]=nil
+ notmatchpost[current]=true
+ notmatchreplace[current]=nil
+ local pre=getfield(current,"pre")
+ local replace=getfield(current,"replace")
+ if pre then
+ local n=n
+ while pre do
+ if seq[n][getchar(pre)] then
+ n=n+1
+ pre=getnext(pre)
+ if n>s then
break
end
+ else
+ notmatchpre[current]=true
+ break
end
- if not match then
+ end
+ if n<=s then
+ notmatchpre[current]=true
+ end
+ else
+ notmatchpre[current]=true
+ end
+ if replace then
+ while replace do
+ if seq[n][getchar(replace)] then
+ n=n+1
+ replace=getnext(replace)
+ if n>s then
+ break
+ end
+ else
+ notmatchreplace[current]=true
+ match=notmatchpre[current]
break
- elseif check_discretionaries=="trace" then
- report_chain("check disc action in after")
end
- else
+ end
+ if not match then
+ break
end
else
end
@@ -13309,6 +13578,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
end
if match then
+ local diskchain=diskseen or sweepnode
if trace_contexts then
local rule,lookuptype,f,l=ck[1],ck[2],ck[4],ck[5]
local char=getchar(start)
@@ -13327,10 +13597,14 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
local chainlookupname=chainlookups[1]
local chainlookup=lookuptable[chainlookupname]
if chainlookup then
- local cp=chainprocs[chainlookup.type]
- if cp then
+ local chainproc=chainprocs[chainlookup.type]
+ if chainproc then
local ok
- head,start,ok=cp(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ if diskchain then
+ head,start,ok=chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence,chainproc)
+ else
+ head,start,ok=chainproc(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
if ok then
done=true
end
@@ -13348,7 +13622,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
local char=getchar(start)
local ccd=descriptions[char]
if ccd then
- local class=ccd.class
+ local class=ccd.class or "base"
if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then
start=getnext(start)
else
@@ -13364,13 +13638,17 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
if not chainlookup then
i=i+1
else
- local cp=chainmores[chainlookup.type]
- if not cp then
+ local chainproc=chainprocs[chainlookup.type]
+ if not chainproc then
logprocess("%s: %s is not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type)
i=i+1
else
local ok,n
- head,start,ok,n=cp(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,i,sequence)
+ if diskchain then
+ head,start,ok=chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence,chainproc)
+ else
+ head,start,ok,n=chainproc(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,i,sequence)
+ end
if ok then
done=true
if n and n>1 then
@@ -13401,8 +13679,16 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
end
end
+ if done then
+ break
+ end
end
end
+ if diskseen then
+ notmatchpre={}
+ notmatchpost={}
+ notmatchreplace={}
+ end
return head,start,done
end
local verbose_handle_contextchain=function(font,...)
@@ -13522,22 +13808,22 @@ local function kernrun(disc,run)
local pre=getfield(disc,"pre")
local post=getfield(disc,"post")
local replace=getfield(disc,"replace")
- if pre or replace then
- if not (prev and getid(prev)==glyph_code and getfont(prev)==currentfont and getsubtype(prev)<256) then
- prev=false
- end
+ local prevmarks=prev
+ while prevmarks and getid(prevmarks)==glyph_code and marks[getchar(prevmarks)] and getfont(prevmarks)==currentfont and getsubtype(prevmarks)<256 do
+ prevmarks=getprev(prevmarks)
end
- if post or replace then
- if not (next and getid(next)==glyph_code and getfont(next)==currentfont and getsubtype(next)<256) then
- next=false
- end
+ if prev and (pre or replace) and not (getid(prev)==glyph_code and getfont(prev)==currentfont and getsubtype(prev)<256) then
+ prev=false
+ end
+ if next and (post or replace) and not (getid(next)==glyph_code and getfont(next)==currentfont and getsubtype(next)<256) then
+ next=false
end
if not pre then
elseif prev then
local nest=getprev(pre)
setfield(pre,"prev",prev)
setfield(prev,"next",pre)
- run(prev,"preinjections")
+ run(prevmarks,"preinjections")
setfield(pre,"prev",nest)
setfield(prev,"next",disc)
else
@@ -13548,13 +13834,18 @@ local function kernrun(disc,run)
local tail=find_node_tail(post)
setfield(tail,"next",next)
setfield(next,"prev",tail)
- run(post,"postinjections",tail)
+ run(post,"postinjections",next)
setfield(tail,"next",nil)
setfield(next,"prev",disc)
else
run(post,"postinjections")
end
if not replace and prev and next then
+ setfield(prev,"next",next)
+ setfield(next,"prev",prev)
+ run(prevmarks,"injections",next)
+ setfield(prev,"next",disc)
+ setfield(next,"prev",disc)
elseif prev and next then
local tail=find_node_tail(replace)
local nest=getprev(replace)
@@ -13562,7 +13853,7 @@ local function kernrun(disc,run)
setfield(prev,"next",replace)
setfield(tail,"next",next)
setfield(next,"prev",tail)
- run(prev,"replaceinjections",tail)
+ run(prevmarks,"replaceinjections",next)
setfield(replace,"prev",nest)
setfield(prev,"next",disc)
setfield(tail,"next",nil)
@@ -13571,14 +13862,14 @@ local function kernrun(disc,run)
local nest=getprev(replace)
setfield(replace,"prev",prev)
setfield(prev,"next",replace)
- run(prev,"replaceinjections")
+ run(prevmarks,"replaceinjections")
setfield(replace,"prev",nest)
setfield(prev,"next",disc)
elseif next then
local tail=find_node_tail(replace)
setfield(tail,"next",next)
setfield(next,"prev",tail)
- run(replace,"replaceinjections",tail)
+ run(replace,"replaceinjections",next)
setfield(tail,"next",nil)
setfield(next,"prev",disc)
else
@@ -13591,6 +13882,8 @@ local function comprun(disc,run)
end
local pre=getfield(disc,"pre")
if pre then
+ sweepnode=disc
+ sweeptype="pre"
local new,done=run(pre)
if done then
setfield(disc,"pre",new)
@@ -13598,6 +13891,8 @@ local function comprun(disc,run)
end
local post=getfield(disc,"post")
if post then
+ sweepnode=disc
+ sweeptype="post"
local new,done=run(post)
if done then
setfield(disc,"post",new)
@@ -13605,13 +13900,17 @@ local function comprun(disc,run)
end
local replace=getfield(disc,"replace")
if replace then
+ sweepnode=disc
+ sweeptype="replace"
local new,done=run(replace)
if done then
setfield(disc,"replace",new)
end
end
+ sweepnode=nil
+ sweeptype=nil
end
-local function testrun(disc,trun,crun)
+local function testrun(disc,trun,crun)
local next=getnext(disc)
if next then
local replace=getfield(disc,"replace")
@@ -13689,6 +13988,7 @@ local function featuresprocessor(head,font,attr)
lookuptags=resources.lookuptags
currentfont=font
rlmode=0
+ sweephead={}
local sequences=resources.sequences
local done=false
local datasets=otf.dataset(tfmdata,font,attr)
@@ -13703,7 +14003,7 @@ local function featuresprocessor(head,font,attr)
local topstack=0
local success=false
local typ=sequence.type
- local gpossing=typ=="gpos_single" or typ=="gpos_pair"
+ local gpossing=typ=="gpos_single" or typ=="gpos_pair"
local subtables=sequence.subtables
local handler=handlers[typ]
if typ=="gsub_reversecontextchain" then
@@ -13724,7 +14024,7 @@ local function featuresprocessor(head,font,attr)
local lookupname=subtables[i]
local lookupcache=lookuphash[lookupname]
if lookupcache then
- local lookupmatch=lookupcache[start]
+ local lookupmatch=lookupcache[char]
if lookupmatch then
head,start,success=handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,i)
if success then
@@ -13756,9 +14056,14 @@ local function featuresprocessor(head,font,attr)
if not lookupcache then
report_missing_cache(typ,lookupname)
else
- local function c_run(start)
- local head=start
+ local function c_run(head)
local done=false
+ local start=sweephead[head]
+ if start then
+ sweephead[head]=nil
+ else
+ start=head
+ end
while start do
local id=getid(start)
if id~=glyph_code then
@@ -13904,39 +14209,30 @@ local function featuresprocessor(head,font,attr)
start=getnext(start)
end
elseif id==disc_code then
- local discretionary=getsubtype(start)==discretionary_code
if gpossing then
- if discretionary then
- kernrun(start,k_run)
- else
- discrun(start,d_run,k_run)
- end
+ kernrun(start,k_run)
start=getnext(start)
- elseif discretionary then
- if typ=="gsub_ligature" then
- start=testrun(start,t_run,c_run)
- else
- comprun(start,c_run)
- start=getnext(start)
- end
+ elseif typ=="gsub_ligature" then
+ start=testrun(start,t_run,c_run)
else
+ comprun(start,c_run)
start=getnext(start)
end
elseif id==whatsit_code then
local subtype=getsubtype(start)
if subtype==dir_code then
local dir=getfield(start,"dir")
- if dir=="+TRT" or dir=="+TLT" then
+ if dir=="+TLT" then
topstack=topstack+1
dirstack[topstack]=dir
- elseif dir=="-TRT" or dir=="-TLT" then
- topstack=topstack-1
- end
- local newdir=dirstack[topstack]
- if newdir=="+TRT" then
- rlmode=-1
- elseif newdir=="+TLT" then
rlmode=1
+ elseif dir=="+TRT" then
+ topstack=topstack+1
+ dirstack[topstack]=dir
+ rlmode=-1
+ elseif dir=="-TLT" or dir=="-TRT" then
+ topstack=topstack-1
+ rlmode=dirstack[topstack]=="+TLT" and 1 or -1
else
rlmode=rlparmode
end
@@ -13966,9 +14262,14 @@ local function featuresprocessor(head,font,attr)
end
end
else
- local function c_run(start)
- local head=start
+ local function c_run(head)
local done=false
+ local start=sweephead[head]
+ if start then
+ sweephead[head]=nil
+ else
+ start=head
+ end
while start do
local id=getid(start)
if id~=glyph_code then
@@ -14164,39 +14465,30 @@ local function featuresprocessor(head,font,attr)
start=getnext(start)
end
elseif id==disc_code then
- local discretionary=getsubtype(start)==discretionary_code
if gpossing then
- if discretionary then
- kernrun(start,k_run)
- else
- discrun(start,d_run,k_run)
- end
+ kernrun(start,k_run)
start=getnext(start)
- elseif discretionary then
- if typ=="gsub_ligature" then
- start=testrun(start,t_run,c_run)
- else
- comprun(start,c_run)
- start=getnext(start)
- end
+ elseif typ=="gsub_ligature" then
+ start=testrun(start,t_run,c_run)
else
+ comprun(start,c_run)
start=getnext(start)
end
elseif id==whatsit_code then
local subtype=getsubtype(start)
if subtype==dir_code then
local dir=getfield(start,"dir")
- if dir=="+TRT" or dir=="+TLT" then
+ if dir=="+TLT" then
topstack=topstack+1
dirstack[topstack]=dir
- elseif dir=="-TRT" or dir=="-TLT" then
- topstack=topstack-1
- end
- local newdir=dirstack[topstack]
- if newdir=="+TRT" then
- rlmode=-1
- elseif newdir=="+TLT" then
rlmode=1
+ elseif dir=="+TRT" then
+ topstack=topstack+1
+ dirstack[topstack]=dir
+ rlmode=-1
+ elseif dir=="-TLT" or dir=="-TRT" then
+ topstack=topstack-1
+ rlmode=dirstack[topstack]=="+TLT" and 1 or -1
else
rlmode=rlparmode
end
diff --git a/tex/generic/context/luatex/luatex-fonts-otn.lua b/tex/generic/context/luatex/luatex-fonts-otn.lua
index be2c48a09..8066b0f08 100644
--- a/tex/generic/context/luatex/luatex-fonts-otn.lua
+++ b/tex/generic/context/luatex/luatex-fonts-otn.lua
@@ -6,9 +6,6 @@ if not modules then modules = { } end modules ['font-otn'] = {
license = "see context related readme files",
}
--- todo: looks like we have a leak somewhere (probably in ligatures)
--- todo: copy attributes to disc
-
-- this is a context version which can contain experimental code, but when we
-- have serious patches we also need to change the other two font-otn files
@@ -83,9 +80,12 @@ is currently acceptable. Not all functions are implemented yet, often because I
lack the fonts for testing. Many scripts are not yet supported either, but I will
look into them as soon as <l n='context'/> users ask for it.</p>
-<p>Because there are different interpretations possible, I will extend the code
-with more (configureable) variants. I can also add hooks for users so that they can
-write their own extensions.</p>
+<p>The specification leaves room for interpretation. In case of doubt the microsoft
+implementation is the reference as it is the most complete one. As they deal with
+lots of scripts and fonts, Kai and Ivo did a lot of testing of the generic code and
+their suggestions help improve the code. I'm aware that not all border cases can be
+taken care of, unless we accept excessive runtime, and even then the interference
+with other mechanisms (like hyphenation) are not trivial.</p>
<p>Glyphs are indexed not by unicode but in their own way. This is because there is no
relationship with unicode at all, apart from the fact that a font might cover certain
@@ -112,12 +112,12 @@ when there's a fix in the <l n='fontforge'/> library or <l n='lua'/> code that
results in different tables.</p>
--ldx]]--
--- action handler chainproc chainmore comment
+-- action handler chainproc
--
--- gsub_single ok ok ok
--- gsub_multiple ok ok not implemented yet
--- gsub_alternate ok ok not implemented yet
--- gsub_ligature ok ok ok
+-- gsub_single ok ok
+-- gsub_multiple ok ok
+-- gsub_alternate ok ok
+-- gsub_ligature ok ok
-- gsub_context ok --
-- gsub_contextchain ok --
-- gsub_reversecontextchain ok --
@@ -182,13 +182,11 @@ local trace_discruns = false registertracker("otf.discruns", function(v
local trace_compruns = false registertracker("otf.compruns", function(v) trace_compruns = v end)
local quit_on_no_replacement = true -- maybe per font
-local check_discretionaries = true -- "trace"
local zwnjruns = true
registerdirective("otf.zwnjruns", function(v) zwnjruns = v end)
registerdirective("otf.chain.quitonnoreplacement",function(value) quit_on_no_replacement = value end)
-
local report_direct = logs.reporter("fonts","otf direct")
local report_subchain = logs.reporter("fonts","otf subchain")
local report_chain = logs.reporter("fonts","otf chain")
@@ -257,11 +255,7 @@ local math_code = nodecodes.math
local dir_code = whatcodes.dir
local localpar_code = whatcodes.localpar
-
local discretionary_code = disccodes.discretionary
-local regular_code = disccodes.regular
-local automatic_code = disccodes.automatic
-
local ligature_code = glyphcodes.ligature
local privateattribute = attributes.private
@@ -313,6 +307,15 @@ local handlers = { }
local rlmode = 0
local featurevalue = false
+local sweephead = { }
+local sweepnode = nil
+local sweepprev = nil
+local sweepnext = nil
+
+local notmatchpre = { }
+local notmatchpost = { }
+local notmatchreplace = { }
+
-- head is always a whatsit so we can safely assume that head is not changed
-- we use this for special testing and documentation
@@ -403,50 +406,64 @@ local function copy_glyph(g) -- next and prev are untouched !
end
end
--- temp here (context)
-
-local function collapse_disc(start,next)
- local replace1 = getfield(start,"replace")
- local replace2 = getfield(next,"replace")
- if replace1 and replace2 then
- local pre2 = getfield(next,"pre")
- local post2 = getfield(next,"post")
- setfield(replace1,"prev",nil)
- if pre2 then
- local pre1 = getfield(start,"pre")
- if pre1 then
- flush_node_list(pre1)
+local function flattendisk(head,disc)
+ local replace = getfield(disc,"replace")
+ setfield(disc,"replace",nil)
+ free_node(disc)
+ if head == disc then
+ local next = getnext(disc)
+ if replace then
+ if next then
+ local tail = find_node_tail(replace)
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
end
- local pre1 = copy_node_list(replace1)
- local tail1 = find_node_tail(pre1)
- setfield(tail1,"next",pre2)
- setfield(pre2,"prev",tail1)
- setfield(start,"pre",pre1)
- setfield(next,"pre",nil)
+ return replace, replace
+ elseif next then
+ return next, next
else
- setfield(start,"pre",nil)
+ return -- maybe warning
end
- if post2 then
- local post1 = getfield(start,"post")
- if post1 then
- flush_node_list(post1)
+ else
+ local next = getnext(disc)
+ local prev = getprev(disc)
+ if replace then
+ local tail = find_node_tail(replace)
+ if next then
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
end
- setfield(start,"post",post2)
+ setfield(prev,"next",replace)
+ setfield(replace,"prev",prev)
+ return head, replace
else
- setfield(start,"post",nil)
- end
- local tail1 = find_node_tail(replace1)
- setfield(tail1,"next",replace2)
- setfield(replace2,"prev",tail1)
- setfield(start,"replace",replace1)
- setfield(next,"replace",nil)
- --
- local nextnext = getnext(next)
- setfield(nextnext,"prev",start)
- setfield(start,"next",nextnext)
- free_node(next)
+ if next then
+ setfield(next,"prev",prev)
+ end
+ setfield(prev,"next",next)
+ return head, next
+ end
+ end
+end
+
+local function appenddisc(disc,list)
+ local post = getfield(disc,"post")
+ local replace = getfield(disc,"replace")
+ local phead = list
+ local rhead = copy_node_list(list)
+ local ptail = find_node_tail(post)
+ local rtail = find_node_tail(replace)
+ if post then
+ setfield(ptail,"next",phead)
+ setfield(phead,"prev",ptail)
else
- -- maybe remove it
+ setfield(disc,"post",phead)
+ end
+ if replace then
+ setfield(rtail,"next",rhead)
+ setfield(rhead,"prev",rtail)
+ else
+ setfield(disc,"replace",rhead)
end
end
@@ -487,8 +504,8 @@ end
-- iteration this becomes a KAF-LAM-ALEF with a SHADDA on the second and a FATHA on the
-- third component.
-local function getcomponentindex(start)
- if getid(start) ~= glyph_code then
+local function getcomponentindex(start) -- we could store this offset in the glyph (nofcomponents)
+ if getid(start) ~= glyph_code then -- and then get rid of all components
return 0
elseif getsubtype(start) == ligature_code then
local i = 0
@@ -505,69 +522,7 @@ local function getcomponentindex(start)
end
end
-local a_noligature = attributes.private("noligature")
-local prehyphenchar = languages and languages.prehyphenchar
-local posthyphenchar = languages and languages.posthyphenchar
------ preexhyphenchar = languages and languages.preexhyphenchar
------ postexhyphenchar = languages and languages.postexhyphenchar
-
-if prehyphenchar then
-
- -- okay
-
-elseif context then
-
- report_warning("no language support") os.exit()
-
-else
-
- local newlang = lang.new
- local getpre = lang.prehyphenchar
- local getpost = lang.posthyphenchar
- -- local getpreex = lang.preexhyphenchar
- -- local getpostex = lang.postexhyphenchar
-
- prehyphenchar = function(l) local l = newlang(l) return l and getpre (l) or -1 end
- posthyphenchar = function(l) local l = newlang(l) return l and getpost (l) or -1 end
- -- preexhyphenchar = function(l) local l = newlang(l) return l and getpreex (l) or -1 end
- -- postexhyphenchar = function(l) local l = newlang(l) return l and getpostex(l) or -1 end
-
-end
-
-local function addhyphens(template,pre,post)
- -- inserted by hyphenation algorithm
- local l = getfield(template,"lang")
- local p = prehyphenchar(l)
- if p and p > 0 then
- local c = copy_node(template)
- setfield(c,"char",p)
- if pre then
- local t = find_node_tail(pre)
- setfield(t,"next",c)
- setfield(c,"prev",t)
- else
- pre = c
- end
- end
- local p = posthyphenchar(l)
- if p and p > 0 then
- local c = copy_node(template)
- setfield(c,"char",p)
- if post then
- -- post has a prev nesting node .. alternatively we could
- local prev = getprev(post)
- setfield(c,"next",post)
- setfield(post,"prev",c)
- if prev then
- setfield(prev,"next",c)
- setfield(c,"prev",prev)
- end
- else
- post = c
- end
- end
- return pre, post
-end
+local a_noligature = attributes.private("noligature")
local function toligature(kind,lookupname,head,start,stop,char,markflag,discfound) -- brr head
if getattr(start,a_noligature) == 1 then
@@ -582,8 +537,8 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
-- needs testing (side effects):
local components = getfield(start,"components")
if components then
--- we get a double free .. needs checking
--- flush_node_list(components)
+ -- we get a double free .. needs checking
+ -- flush_node_list(components)
end
--
local prev = getprev(start)
@@ -605,8 +560,8 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
if next then
setfield(next,"prev",base)
end
- setfield(base,"next",next)
setfield(base,"prev",prev)
+ setfield(base,"next",next)
if not discfound then
local deletemarks = markflag ~= "mark"
local components = start
@@ -653,53 +608,34 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
local discprev = getfield(discfound,"prev")
local discnext = getfield(discfound,"next")
if discprev and discnext then
- local subtype = getsubtype(discfound)
- if subtype == discretionary_code then
- local pre = getfield(discfound,"pre")
- local post = getfield(discfound,"post")
- local replace = getfield(discfound,"replace")
- if not replace then -- todo: signal simple hyphen
- local prev = getfield(base,"prev")
- local copied = copy_node_list(comp)
- setfield(discnext,"prev",nil) -- also blocks funny assignments
- setfield(discprev,"next",nil) -- also blocks funny assignments
- if pre then
- setfield(discprev,"next",pre)
- setfield(pre,"prev",discprev)
- end
- pre = comp
- if post then
- local tail = find_node_tail(post)
- setfield(tail,"next",discnext)
- setfield(discnext,"prev",tail)
- setfield(post,"prev",nil)
- else
- post = discnext
- end
- setfield(prev,"next",discfound)
- setfield(next,"prev",discfound)
- setfield(discfound,"next",next)
- setfield(discfound,"prev",prev)
- setfield(base,"next",nil)
- setfield(base,"prev",nil)
- setfield(base,"components",copied)
- setfield(discfound,"pre",pre)
- setfield(discfound,"post",post)
- setfield(discfound,"replace",base)
- setfield(discfound,"subtype",discretionary_code)
- base = prev -- restart
- end
- elseif subtype == regular_code then
- -- local prev = getfield(base,"prev")
- -- local next = getfield(base,"next")
+ -- we assume normalization in context, and don't care about generic ... especially
+ -- \- can give problems as there we can have a negative char but that won't match
+ -- anyway
+ local pre = getfield(discfound,"pre")
+ local post = getfield(discfound,"post")
+ local replace = getfield(discfound,"replace")
+ if not replace then -- todo: signal simple hyphen
+ local prev = getfield(base,"prev")
local copied = copy_node_list(comp)
setfield(discnext,"prev",nil) -- also blocks funny assignments
setfield(discprev,"next",nil) -- also blocks funny assignments
- local pre, post = addhyphens(comp,comp,discnext,subtype) -- takes from components
+ if pre then
+ setfield(discprev,"next",pre)
+ setfield(pre,"prev",discprev)
+ end
+ pre = comp
+ if post then
+ local tail = find_node_tail(post)
+ setfield(tail,"next",discnext)
+ setfield(discnext,"prev",tail)
+ setfield(post,"prev",nil)
+ else
+ post = discnext
+ end
setfield(prev,"next",discfound)
- setfield(next,"prev",discfound)
- setfield(discfound,"next",next)
setfield(discfound,"prev",prev)
+ setfield(discfound,"next",next)
+ setfield(next,"prev",discfound)
setfield(base,"next",nil)
setfield(base,"prev",nil)
setfield(base,"components",copied)
@@ -707,22 +643,45 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
setfield(discfound,"post",post)
setfield(discfound,"replace",base)
setfield(discfound,"subtype",discretionary_code)
- base = next -- or restart
- else
- -- forget about it in generic usage
+ base = prev -- restart
end
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(getchar(start)),gref(replacement))
+local function multiple_glyphs(head,start,multiple,ignoremarks)
+ local nofmultiples = #multiple
+ if nofmultiples > 0 then
+ resetinjection(start)
+ setfield(start,"char",multiple[1])
+ if nofmultiples > 1 then
+ local sn = getnext(start)
+ for k=2,nofmultiples do -- todo: use insert_node
+-- untested:
+--
+-- while ignoremarks and marks[getchar(sn)] then
+-- local sn = getnext(sn)
+-- end
+ local n = copy_node(start) -- ignore components
+ resetinjection(n)
+ setfield(n,"char",multiple[k])
+ setfield(n,"prev",start)
+ setfield(n,"next",sn)
+ if sn then
+ setfield(sn,"prev",n)
+ end
+ setfield(start,"next",n)
+ start = n
+ end
+ end
+ return head, start, true
+ else
+ if trace_multiples then
+ logprocess("no multiple for %s",gref(getchar(start)))
+ end
+ return head, start, false
end
- resetinjection(start)
- setfield(start,"char",replacement)
- return head, start, true
end
local function get_alternative_glyph(start,alternatives,value,trace_alternatives)
@@ -757,38 +716,15 @@ local function get_alternative_glyph(start,alternatives,value,trace_alternatives
end
end
-local function multiple_glyphs(head,start,multiple,ignoremarks)
- local nofmultiples = #multiple
- if nofmultiples > 0 then
- resetinjection(start)
- setfield(start,"char",multiple[1])
- if nofmultiples > 1 then
- local sn = getnext(start)
- for k=2,nofmultiples do -- todo: use insert_node
--- untested:
---
--- while ignoremarks and marks[getchar(sn)] then
--- local sn = getnext(sn)
--- end
- local n = copy_node(start) -- ignore components
- resetinjection(n)
- setfield(n,"char",multiple[k])
- setfield(n,"next",sn)
- setfield(n,"prev",start)
- if sn then
- setfield(sn,"prev",n)
- end
- setfield(start,"next",n)
- start = n
- end
- end
- return head, start, true
- else
- if trace_multiples then
- logprocess("no multiple for %s",gref(getchar(start)))
- end
- return head, start, false
+-- handlers
+
+function handlers.gsub_single(head,start,kind,lookupname,replacement)
+ if trace_singles then
+ logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(getchar(start)),gref(replacement))
end
+ resetinjection(start)
+ setfield(start,"char",replacement)
+ return head, start, true
end
function handlers.gsub_alternate(head,start,kind,lookupname,alternative,sequence)
@@ -910,19 +846,79 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
return head, start, false, discfound
end
--- function is_gsub_ligature(start,ligature) -- limited case: in disc nodes, only latin, always glyphs
--- local s = getnext(start)
--- while s do
--- local lg = ligature[getchar(s)]
--- if lg then
--- ligature = lg
--- s = getnext(s)
--- else
--- return
--- end
--- end
--- return ligature and ligature.ligature
--- end
+function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence,injection)
+ local startchar = getchar(start)
+ local dx, dy, w, h = setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,injection) -- ,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)
+ end
+ return head, start, false
+end
+
+function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence,lookuphash,i,injection)
+ -- todo: kerns in disc nodes: pre, post, replace -> loop over disc too
+ -- todo: kerns in components of ligatures
+ local snext = getnext(start)
+ if not snext then
+ return head, start, false
+ else
+ local prev = start
+ local done = false
+ local factor = tfmdata.parameters.factor
+ local lookuptype = lookuptypes[lookupname]
+ 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 = getnext(snext)
+ else
+ if not krn then
+ -- skip
+ elseif type(krn) == "table" then
+ if lookuptype == "pair" then -- probably not needed
+ local a, b = krn[2], krn[3]
+ if a and #a > 0 then
+ local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,injection) -- characters[startchar])
+ if trace_kerns then
+ local startchar = getchar(start)
+ 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 x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,injection) -- characters[nextchar])
+ if trace_kerns then
+ local startchar = getchar(start)
+ 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)
+ end
+ end
+ else -- wrong ... position has different entries
+ report_process("%s: check this out (old kern stuff)",pref(kind,lookupname))
+ -- local a, b = krn[2], krn[6]
+ -- 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",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar))
+ -- end
+ -- end
+ -- if b and b ~= 0 then
+ -- logwarning("%s: ignoring second kern xoff %s",pref(kind,lookupname),b*factor)
+ -- end
+ end
+ done = true
+ elseif krn ~= 0 then
+ local k = setkern(snext,factor,rlmode,krn,injection)
+ if trace_kerns then
+ logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar)) -- prev?
+ end
+ done = true
+ end
+ break
+ end
+ end
+ return head, start, done
+ end
+end
--[[ldx--
<p>We get hits on a mark, but we're not sure if the it has to be applied so
@@ -1169,85 +1165,11 @@ function handlers.gpos_cursive(head,start,kind,lookupname,exitanchors,sequence)
end
end
-function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence,injection)
- local startchar = getchar(start)
- local dx, dy, w, h = setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,injection) -- ,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)
- end
- return head, start, false
-end
-
-function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence,lookuphash,i,injection)
- -- todo: kerns in disc nodes: pre, post, replace -> loop over disc too
- -- todo: kerns in components of ligatures
- 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 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 = getnext(snext)
- else
- if not krn then
- -- skip
- elseif type(krn) == "table" then
- if lookuptype == "pair" then -- probably not needed
- local a, b = krn[2], krn[3]
- if a and #a > 0 then
- local startchar = getchar(start)
- local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,injection) -- 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 = getchar(start)
- local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,injection) -- 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)
- end
- end
- else -- wrong ... position has different entries
- report_process("%s: check this out (old kern stuff)",pref(kind,lookupname))
- -- local a, b = krn[2], krn[6]
- -- 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",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar))
- -- end
- -- end
- -- if b and b ~= 0 then
- -- logwarning("%s: ignoring second kern xoff %s",pref(kind,lookupname),b*factor)
- -- end
- end
- done = true
- elseif krn ~= 0 then
- local k = setkern(snext,factor,rlmode,krn,injection)
- if trace_kerns then
- logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar))
- end
- done = true
- end
- break
- end
- end
- return head, start, done
- end
-end
-
--[[ldx--
<p>I will implement multiple chain replacements once I run into a font that uses
it. It's not that complex to handle.</p>
--ldx]]--
-local chainmores = { }
local chainprocs = { }
local function logprocess(...)
@@ -1276,11 +1198,6 @@ function chainprocs.chainsub(head,start,stop,kind,chainname,currentcontext,looku
return head, start, false
end
-function chainmores.chainsub(head,start,stop,kind,chainname,currentcontext,lookuphash,lookuplist,chainlookupname,n)
- logprocess("%s: a direct call to chainsub cannot happen",cref(kind,chainname,chainlookupname))
- return head, start, false
-end
-
-- The reversesub is a special case, which is why we need to store the replacements
-- in a bit weird way. There is no lookup and the replacement comes from the lookup
-- itself. It is meant mostly for dealing with Urdu.
@@ -1377,83 +1294,7 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo
logprocess("%s: replacing single %s by %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(currentchar),gref(replacement))
end
resetinjection(current)
- if check_discretionaries then
- -- some fonts use a chain lookup to replace e.g. an f in a fi ligature
- -- and there can be a disc node in between ... the next code tries to catch
- -- this
- local next = getnext(current)
- local prev = getprev(current) -- todo: just remember it above
- local done = false
- if next then
- if getid(next) == disc_code then
- local subtype = getsubtype(next)
- if subtype == discretionary_code then
- setfield(next,"prev",prev)
- setfield(prev,"next",next)
- setfield(current,"prev",nil)
- setfield(current,"next",nil)
- local replace = getfield(next,"replace")
- local pre = getfield(next,"pre")
- local new = copy_node(current)
- setfield(new,"char",replacement)
- if replace then
- setfield(new,"next",replace)
- setfield(replace,"prev",new)
- end
- if pre then
- setfield(current,"next",pre)
- setfield(pre,"prev",current)
- end
- setfield(next,"replace",new) -- also updates tail
- setfield(next,"pre",current) -- also updates tail
- end
- start = next
- done = true
- local next = getnext(start)
- if next and getid(next) == disc_code then
- collapse_disc(start,next)
- end
- end
- end
- if not done and prev then
- if getid(prev) == disc_code then
- local subtype = getsubtype(prev)
- if subtype == discretionary_code then
- setfield(next,"prev",prev)
- setfield(prev,"next",next)
- setfield(current,"prev",nil)
- setfield(current,"next",nil)
- local replace = getfield(prev,"replace")
- local post = getfield(prev,"post")
- local new = copy_node(current)
- setfield(new,"char",replacement)
- if replace then
- local tail = find_node_tail(replace)
- setfield(tail,"next",new)
- setfield(new,"prev",tail)
- else
- replace = new
- end
- if post then
- local tail = find_node_tail(post)
- setfield(tail,"next",current)
- setfield(current,"prev",tail)
- else
- post = current
- end
- setfield(prev,"replace",replace) -- also updates tail
- setfield(prev,"post",post) -- also updates tail
- start = prev
- done = true
- end
- end
- end
- if not done then
- setfield(current,"char",replacement)
- end
- else
- setfield(current,"char",replacement)
- end
+ setfield(current,"char",replacement)
end
end
return head, start, true
@@ -1466,8 +1307,6 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo
return head, start, false
end
-chainmores.gsub_single = chainprocs.gsub_single
-
--[[ldx--
<p>Here we replace start by a sequence of new glyphs.</p>
--ldx]]--
@@ -1498,8 +1337,6 @@ function chainprocs.gsub_multiple(head,start,stop,kind,chainname,currentcontext,
return head, start, false
end
-chainmores.gsub_multiple = chainprocs.gsub_multiple
-
--[[ldx--
<p>Here we replace start by new glyph. First we delete the rest of the match.</p>
--ldx]]--
@@ -1554,8 +1391,6 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext
return head, start, false
end
-chainmores.gsub_alternate = chainprocs.gsub_alternate
-
--[[ldx--
<p>When we replace ligatures we use a helper that handles the marks. I might change
this function (move code inline and handle the marks by a separate function). We
@@ -1597,11 +1432,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
else
local schar = getchar(s)
if skipmark and marks[schar] then -- marks
--- if s == stop then -- maybe add this
--- break
--- else
s = getnext(s)
--- end
else
local lg = ligatures[schar]
if lg then
@@ -1643,7 +1474,93 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
return head, start, false, 0, false
end
-chainmores.gsub_ligature = chainprocs.gsub_ligature
+function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
+ -- untested .. needs checking for the new model
+ local startchar = getchar(start)
+ local subtables = currentlookup.subtables
+ local lookupname = subtables[1]
+ local kerns = lookuphash[lookupname]
+ if kerns then
+ kerns = kerns[startchar] -- needed ?
+ if kerns then
+ 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)",cref(kind,chainname,chainlookupname),gref(startchar),dx,dy,w,h)
+ end
+ end
+ end
+ return head, start, false
+end
+
+function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
+ local snext = getnext(start)
+ if snext then
+ local startchar = getchar(start)
+ local subtables = currentlookup.subtables
+ local lookupname = subtables[1]
+ local kerns = lookuphash[lookupname]
+ if kerns then
+ kerns = kerns[startchar]
+ if kerns then
+ local lookuptype = lookuptypes[lookupname]
+ local prev, done = start, false
+ local factor = tfmdata.parameters.factor
+ 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 = getnext(snext)
+ else
+ if not krn then
+ -- skip
+ elseif type(krn) == "table" then
+ if lookuptype == "pair" then
+ local a, b = krn[2], krn[3]
+ if a and #a > 0 then
+ 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 = 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)
+ end
+ end
+ else
+ report_process("%s: check this out (old kern stuff)",cref(kind,chainname,chainlookupname))
+ -- local a, b = krn[2], krn[6]
+ -- 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(getchar(prev)),gref(nextchar))
+ -- end
+ -- end
+ -- if b and b ~= 0 then
+ -- logwarning("%s: ignoring second kern xoff %s",cref(kind,chainname,chainlookupname),b*factor)
+ -- end
+ end
+ done = true
+ 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(getchar(prev)),gref(nextchar))
+ end
+ done = true
+ end
+ break
+ end
+ end
+ return head, start, done
+ end
+ end
+ end
+ return head, start, false
+end
function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
local markchar = getchar(start)
@@ -1903,129 +1820,346 @@ 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)
- -- untested .. needs checking for the new model
- local startchar = getchar(start)
- local subtables = currentlookup.subtables
- local lookupname = subtables[1]
- local kerns = lookuphash[lookupname]
- if kerns then
- kerns = kerns[startchar] -- needed ?
- if kerns then
- 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)",cref(kind,chainname,chainlookupname),gref(startchar),dx,dy,w,h)
+-- what pointer to return, spec says stop
+-- to be discussed ... is bidi changer a space?
+-- elseif char == zwnj and sequence[n][32] then -- brrr
+
+-- somehow l or f is global
+-- we don't need to pass the currentcontext, saves a bit
+-- make a slow variant then can be activated but with more tracing
+
+local function show_skip(kind,chainname,char,ck,class)
+ if ck[9] then
+ logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a, %a => %a",cref(kind,chainname),gref(char),class,ck[1],ck[2],ck[9],ck[10])
+ else
+ logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a",cref(kind,chainname),gref(char),class,ck[1],ck[2])
+ end
+end
+
+-- A previous version had disc collapsing code in the (single sub) handler plus some
+-- checking in the main loop, but that left the pre/post sequences undone. The best
+-- solution is to add some checking there and backtrack when a replace/post matches
+-- but it takes a bit of work to figure out an efficient way (this is what the sweep*
+-- names refer to). I might look into that variant one day again as it can replace
+-- some other code too. In that approach we can have a special version for gub and pos
+-- which gains some speed. This method does the test and passes info to the handlers
+-- (sweepnode, sweepmode, sweepprev, sweepnext, etc). Here collapsing is handled in the
+-- main loop which also makes code elsewhere simpler (i.e. no need for the other special
+-- runners and disc code in ligature building). I also experimented with pushing preceding
+-- glyphs sequences in the replace/pre fields beforehand which saves checking afterwards
+-- but at the cost of duplicate glyphs (memory) but it's too much overhead (runtime).
+--
+-- In the meantime Kai had moved the code from the single chain into a more general handler
+-- and this one (renamed to chaindisk) is used now. I optimized the code a bit and brought
+-- it in sycn with the other code. Hopefully I didn't introduce errors. Note: this somewhat
+-- complex approach is meant for fonts that implement (for instance) ligatures by character
+-- replacement which to some extend is not that suitable for hyphenation. I also use some
+-- helpers. This method passes some states but reparses the list. There is room for a bit of
+-- speed up but that will be done in the context version. (In fact a partial rewrite of all
+-- code can bring some more efficientry.)
+--
+-- I didn't test it with extremes but successive disc nodes still can give issues but in
+-- order to handle that we need more complex code which also slows down even more. The main
+-- loop variant could deal with that: test, collapse, backtrack.
+
+local function chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,chainindex,sequence,chainproc)
+
+ if not start then
+ return head, start, false
+ end
+
+ local startishead = start == head
+ local seq = ck[3]
+ local f = ck[4]
+ local l = ck[5]
+ local s = #seq
+ local done = false
+ local sweepnode = sweepnode
+ local sweeptype = sweeptype
+ local sweepoverflow = false
+ local checkdisc = getprev(head) -- hm bad name head
+ local keepdisc = not sweepnode
+ local lookaheaddisc = nil
+ local backtrackdisc = nil
+ local current = start
+ local last = start
+ local prev = getprev(start)
+
+ -- fishy: so we can overflow and then go on in the sweep?
+
+ local i = f
+ while i <= l do
+ local id = getid(current)
+ if id == glyph_code then
+ i = i + 1
+ last = current
+ current = getnext(current)
+ elseif id == disc_code then
+ if keepdisc then
+ keepdisc = false
+ if notmatchpre[current] ~= notmatchreplace[current] then
+ lookaheaddisc = current
+ end
+ local replace = getfield(current,"replace")
+ while replace and i <= l do
+ if getid(replace) == glyph_code then
+ i = i + 1
+ end
+ replace = getnext(replace)
+ end
+ last = current
+ current = getnext(c)
+ else
+ head, current = flattendisk(head,current)
+ end
+ else
+ last = current
+ current = getnext(current)
+ end
+ if current then
+ -- go on
+ elseif sweepoverflow then
+ -- we already are folling up on sweepnode
+ break
+ elseif sweeptype == "post" or sweeptype == "replace" then
+ current = getnext(sweepnode)
+ if current then
+ sweeptype = nil
+ sweepoverflow = true
+ else
+ break
end
end
end
- return head, start, false
-end
-chainmores.gpos_single = chainprocs.gpos_single -- okay?
+ if sweepoverflow then
+ local prev = current and getprev(current)
+ if not current or prev ~= sweepnode then
+ local head = getnext(sweepnode)
+ local tail = nil
+ if prev then
+ tail = prev
+ setfield(current,"prev",sweepnode)
+ else
+ tail = find_node_tail(head)
+ end
+ setfield(sweepnode,"next",current)
+ setfield(head,"prev",nil)
+ setfield(tail,"next",nil)
+ appenddisc(sweepnode,head)
+ end
+ end
--- when machines become faster i will make a shared function
+ if l < s then
+ local i = l
+ local t = sweeptype == "post" or sweeptype == "replace"
+ while current and i < s do
+ local id = getid(current)
+ if id == glyph_code then
+ i = i + 1
+ current = getnext(current)
+ elseif id == disc_code then
+ if keepdisc then
+ keepdisc = false
+ if notmatchpre[current] ~= notmatchreplace[current] then
+ lookaheaddisc = current
+ end
+ local replace = getfield(c,"replace")
+ while replace and i < s do
+ if getid(replace) == glyph_code then
+ i = i + 1
+ end
+ replace = getnext(replace)
+ end
+ current = getnext(current)
+ elseif notmatchpre[current] ~= notmatchreplace[current] then
+ head, current = flattendisk(head,current)
+ else
+ current = getnext(current) -- HH
+ end
+ else
+ current = getnext(current)
+ end
+ if not current and t then
+ current = getnext(sweepnode)
+ if current then
+ sweeptype = nil
+ end
+ end
+ end
+ end
-function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
- local snext = getnext(start)
- if snext then
- local startchar = getchar(start)
- local subtables = currentlookup.subtables
- local lookupname = subtables[1]
- local kerns = lookuphash[lookupname]
- if kerns then
- kerns = kerns[startchar]
- if kerns then
- local lookuptype = lookuptypes[lookupname]
- local prev, done = start, false
- local factor = tfmdata.parameters.factor
- 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 = getnext(snext)
- else
- if not krn then
- -- skip
- elseif type(krn) == "table" then
- if lookuptype == "pair" then
- local a, b = krn[2], krn[3]
- if a and #a > 0 then
- 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 = 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)
- end
- end
- else
- report_process("%s: check this out (old kern stuff)",cref(kind,chainname,chainlookupname))
- -- local a, b = krn[2], krn[6]
- -- 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(getchar(prev)),gref(nextchar))
- -- end
- -- end
- -- if b and b ~= 0 then
- -- logwarning("%s: ignoring second kern xoff %s",cref(kind,chainname,chainlookupname),b*factor)
- -- end
- end
- done = true
- 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(getchar(prev)),gref(nextchar))
- end
- done = true
+ if f > 1 then
+ local current = prev
+ local i = f
+ local t = sweeptype == "pre" or sweeptype == "replace"
+ if not current and t and current == checkdisk then
+ current = getprev(sweepnode)
+ end
+ while current and i > 1 do -- missing getprev added / moved outside
+ local id = getid(current)
+ if id == glyph_code then
+ i = i - 1
+ elseif id == disc_code then
+ if keepdisc then
+ keepdisc = false
+ if notmatchpost[current] ~= notmatchreplace[current] then
+ backtrackdisc = current
+ end
+ local replace = getfield(current,"replace")
+ while replace and i > 1 do
+ if getid(replace) == glyph_code then
+ i = i - 1
end
- break
+ replace = getnext(replace)
end
+ elseif notmatchpost[current] ~= notmatchreplace[current] then
+ head, current = flattendisk(head,current)
end
- return head, start, done
+ end
+ current = getprev(current)
+ if t and current == checkdisk then
+ current = getprev(sweepnode)
end
end
end
- return head, start, false
-end
-chainmores.gpos_pair = chainprocs.gpos_pair -- okay?
+ local ok = false
+ if lookaheaddisc then
--- what pointer to return, spec says stop
--- to be discussed ... is bidi changer a space?
--- elseif char == zwnj and sequence[n][32] then -- brrr
+ local cf = start
+ local cl = getprev(lookaheaddisc)
+ local cprev = getprev(start)
+ local insertedmarks = 0
--- somehow l or f is global
--- we don't need to pass the currentcontext, saves a bit
--- make a slow variant then can be activated but with more tracing
+ while cprev and getid(cf) == glyph_code and getfont(cf) == currentfont and getsubtype(cf) < 256 and marks[getchar(cf)] do
+ insertedmarks = insertedmarks + 1
+ cf = cprev
+ startishead = cf == head
+ cprev = getprev(cprev)
+ end
+
+ setfield(lookaheaddisc,"prev",cprev)
+ if cprev then
+ setfield(cprev,"next",lookaheaddisc)
+ end
+ setfield(cf,"prev",nil)
+ setfield(cl,"next",nil)
+ if startishead then
+ head = lookaheaddisc
+ end
+
+ local replace = getfield(lookaheaddisc,"replace")
+ local pre = getfield(lookaheaddisc,"pre")
+ local new = copy_node_list(cf)
+ local cnew = new
+ for i=1,insertedmarks do
+ cnew = getnext(cnew)
+ end
+ local clast = cnew
+ for i=f,l do
+ clast = getnext(clast)
+ end
+ if not notmatchpre[lookaheaddisc] then
+ cf, start, ok = chainproc(cf,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
+ if not notmatchreplace[lookaheaddisc] then
+ new, cnew, ok = chainproc(new,cnew,clast,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
+ if pre then
+ setfield(cl,"next",pre)
+ setfield(pre,"prev",cl)
+ end
+ if replace then
+ local tail = find_node_tail(new)
+ setfield(tail,"next",replace)
+ setfield(replace,"prev",tail)
+ end
+ setfield(lookaheaddisc,"pre",cf) -- also updates tail
+ setfield(lookaheaddisc,"replace",new) -- also updates tail
+
+ start = getprev(lookaheaddisc)
+ sweephead[cf] = getnext(clast)
+ sweephead[new] = getnext(last)
+
+ elseif backtrackdisc then
+
+ local cf = getnext(backtrackdisc)
+ local cl = start
+ local cnext = getnext(start)
+ local insertedmarks = 0
+
+ while cnext and getid(cnext) == glyph_code and getfont(cnext) == currentfont and getsubtype(cnext) < 256 and marks[getchar(cnext)] do
+ insertedmarks = insertedmarks + 1
+ cl = cnext
+ cnext = getnext(cnext)
+ end
+ if cnext then
+ setfield(cnext,"prev",backtrackdisc)
+ end
+ setfield(backtrackdisc,"next",cnext)
+ setfield(cf,"prev",nil)
+ setfield(cl,"next",nil)
+ local replace = getfield(backtrackdisc,"replace")
+ local post = getfield(backtrackdisc,"post")
+ local new = copy_node_list(cf)
+ local cnew = find_node_tail(new)
+ for i=1,insertedmarks do
+ cnew = getprev(cnew)
+ end
+ local clast = cnew
+ for i=f,l do
+ clast = getnext(clast)
+ end
+ if not notmatchpost[backtrackdisc] then
+ cf, start, ok = chainproc(cf,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
+ if not notmatchreplace[backtrackdisc] then
+ new, cnew, ok = chainproc(new,cnew,clast,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
+ if post then
+ local tail = find_node_tail(post)
+ setfield(tail,"next",cf)
+ setfield(cf,"prev",tail)
+ else
+ post = cf
+ end
+ if replace then
+ local tail = find_node_tail(replace)
+ setfield(tail,"next",new)
+ setfield(new,"prev",tail)
+ else
+ replace = new
+ end
+ setfield(backtrackdisc,"post",post) -- also updates tail
+ setfield(backtrackdisc,"replace",replace) -- also updates tail
+ start = getprev(backtrackdisc)
+ sweephead[post] = getnext(clast)
+ sweephead[replace] = getnext(last)
-local function show_skip(kind,chainname,char,ck,class)
- if ck[9] then
- logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a, %a => %a",cref(kind,chainname),gref(char),class,ck[1],ck[2],ck[9],ck[10])
else
- logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a",cref(kind,chainname),gref(char),class,ck[1],ck[2])
+
+ head, start, ok = chainproc(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+
end
-end
---hm, do i need to deal with disc here ?
+ return head, start, ok
+end
local function normal_handle_contextchain(head,start,kind,chainname,contexts,sequence,lookuphash)
- -- local rule, lookuptype, sequence, f, l, lookups = ck[1], ck[2] ,ck[3], ck[4], ck[5], ck[6]
+ local sweepnode = sweepnode
+ local sweeptype = sweeptype
+ local diskseen = false
+ local checkdisc = getprev(head)
local flags = sequence.flags
local done = false
local skipmark = flags[1]
local skipligature = flags[2]
local skipbase = flags[3]
- local someskip = skipmark or skipligature or skipbase -- could be stored in flags for a fast test (hm, flags could be false !)
- local markclass = sequence.markclass -- todo, first we need a proper test
+ local markclass = sequence.markclass
local skipped = false
- for k=1,#contexts do
+
+ for k=1,#contexts do -- i've only seen ccmp having > 1 (e.g. dejavu)
local match = true
local current = start
local last = start
@@ -2039,7 +2173,8 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
else
-- maybe we need a better space check (maybe check for glue or category or combination)
-- we cannot optimize for n=2 because there can be disc nodes
- local f, l = ck[4], ck[5]
+ local f = ck[4]
+ local l = ck[5]
-- current match
if f == 1 and f == l then -- current only
-- already a hit
@@ -2049,9 +2184,14 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
if f == l then -- new, else last out of sync (f is > 1)
-- match = true
else
+ local discfound = nil
local n = f + 1
last = getnext(last)
while n <= l do
+ if not last and (sweeptype == "post" or sweeptype == "replace") then
+ last = getnext(sweepnode)
+ sweeptype = nil
+ end
if last then
local id = getid(last)
if id == glyph_code then
@@ -2059,7 +2199,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
local char = getchar(last)
local ccd = descriptions[char]
if ccd then
- local class = ccd.class
+ local class = ccd.class or "base"
if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
skipped = true
if trace_skips then
@@ -2072,48 +2212,78 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
n = n + 1
else
- match = false
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpre[discfound]
+ else
+ match = false
+ end
break
end
else
- match = false
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpre[discfound]
+ else
+ match = false
+ end
break
end
else
- match = false
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpre[discfound]
+ else
+ match = false
+ end
break
end
elseif id == disc_code then
- if check_discretionaries then
- local replace = getfield(last,"replace")
- if replace then
- -- so far we never entered this branch
- while replace do
- if seq[n][getchar(replace)] then
- n = n + 1
- replace = getnext(replace)
- if not replace then
- break
- elseif n > l then
- -- match = false
- break
- end
- else
- match = false
+ diskseen = true
+ discfound = last
+ notmatchpre[last] = nil
+ notmatchpost[last] = true
+ notmatchreplace[last] = nil
+ local pre = getfield(last,"pre")
+ local replace = getfield(last,"replace")
+ if pre then
+ local n = n
+ while pre do
+ if seq[n][getchar(pre)] then
+ n = n + 1
+ pre = getnext(pre)
+ if n > l then
break
end
- end
- if not match then
+ else
+ notmatchpre[last] = true
break
- elseif check_discretionaries == "trace" then
- report_chain("check disc action in current")
end
- else
- last = getnext(last) -- no skipping here
+ end
+ if n <= l then
+ notmatchpre[last] = true
end
else
- last = getnext(last) -- no skipping here
+ notmatchpre[last] = true
end
+ if replace then
+ -- so far we never entered this branch
+ while replace do
+ if seq[n][getchar(replace)] then
+ n = n + 1
+ replace = getnext(replace)
+ if n > l then
+ break
+ end
+ else
+ notmatchreplace[last] = true
+ match = not notmatchpre[last]
+ break
+ end
+ end
+ match = not notmatchpre[last]
+ end
+ last = getnext(last)
else
match = false
break
@@ -2129,82 +2299,137 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
if match and f > 1 then
local prev = getprev(start)
if prev then
- local n = f-1
- while n >= 1 do
- if prev then
- local id = getid(prev)
- if id == glyph_code then
- if getfont(prev) == currentfont and getsubtype(prev)<256 then -- normal char
- local char = getchar(prev)
- local ccd = descriptions[char]
- if ccd then
- local class = ccd.class
- if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
- skipped = true
- if trace_skips then
- show_skip(kind,chainname,char,ck,class)
+ if prev == checkdisc and (sweeptype == "pre" or sweeptype == "replace") then
+ prev = getprev(sweepnode)
+ -- sweeptype = nil
+ end
+ if prev then
+ local discfound = nil
+ local n = f - 1
+ while n >= 1 do
+ if prev then
+ local id = getid(prev)
+ if id == glyph_code then
+ if getfont(prev) == currentfont and getsubtype(prev)<256 then -- normal char
+ local char = getchar(prev)
+ local ccd = descriptions[char]
+ if ccd then
+ local class = ccd.class
+ if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
+ skipped = true
+ if trace_skips then
+ show_skip(kind,chainname,char,ck,class)
+ end
+ elseif seq[n][char] then
+ n = n -1
+ else
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpost[discfound]
+ else
+ match = false
+ end
+ break
end
- elseif seq[n][char] then
- n = n -1
else
- match = false
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpost[discfound]
+ else
+ match = false
+ end
break
end
else
- match = false
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpost[discfound]
+ else
+ match = false
+ end
break
end
- else
- match = false
- break
- end
- elseif id == disc_code then
- -- the special case: f i where i becomes dottless i ..
- if check_discretionaries then
+ elseif id == disc_code then
+ -- the special case: f i where i becomes dottless i ..
+ diskseen = true
+ discfound = prev
+ notmatchpre[prev] = true
+ notmatchpost[prev] = nil
+ notmatchreplace[prev] = nil
+ local pre = getfield(prev,"pre")
+ local post = getfield(prev,"post")
local replace = getfield(prev,"replace")
- if replace then
- -- we seldom enter this branch (e.g. on brill efficient)
- replace = find_node_tail(replace)
- local finish = getprev(replace)
- while replace do
- if seq[n][getchar(replace)] then
- n = n - 1
- replace = getprev(replace)
- if not replace or replace == finish then
+ if pre ~= start and post ~= start and replace ~= start then
+ if post then
+ local n = n
+ local posttail = find_node_tail(post)
+ while posttail do
+ if seq[n][getchar(posttail)] then
+ n = n - 1
+ if posttail == post then
+ break
+ else
+ posttail = getprev(posttail)
+ if n < 1 then
+ break
+ end
+ end
+ else
+ notmatchpost[prev] = true
break
- elseif n < 1 then
- -- match = false
+ end
+ end
+ if n >= 1 then
+ notmatchpost[prev] = true
+ end
+ else
+ notmatchpost[prev] = true
+ end
+ if replace then
+ -- we seldom enter this branch (e.g. on brill efficient)
+ local replacetail = find_node_tail(replace)
+ while replacetail do
+ if seq[n][getchar(replacetail)] then
+ n = n - 1
+ if replacetail == replace then
+ break
+ else
+ replacetail = getprev(replacetail)
+ if n < 1 then
+ break
+ end
+ end
+ else
+ notmatchreplace[prev] = true
+ match = not notmatchpost[prev]
break
end
- else
- match = false
+ end
+ if not match then
break
end
- end
- if not match then
- break
- elseif check_discretionaries == "trace" then
- report_chain("check disc action in before")
+ else
+ -- skip 'm
end
else
-- skip 'm
end
+ elseif seq[n][32] then
+ n = n -1
else
- -- skip 'm
+ match = false
+ break
end
- elseif seq[n][32] then
- n = n -1
+ prev = getprev(prev)
+ elseif seq[n][32] then -- somewhat special, as zapfino can have many preceding spaces
+ n = n - 1
else
match = false
break
end
- prev = getprev(prev)
- elseif seq[n][32] then -- somewhat special, as zapfino can have many preceding spaces
- n = n - 1
- else
- match = false
- break
end
+ else
+ match = false
end
else
match = false
@@ -2213,7 +2438,14 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
-- after
if match and s > l then
local current = last and getnext(last)
+ if not current then
+ if sweeptype == "post" or sweeptype == "replace" then
+ current = getnext(sweepnode)
+ -- sweeptype = nil
+ end
+ end
if current then
+ local discfound = nil
-- removed optimization for s-l == 1, we have to deal with marks anyway
local n = l + 1
while n <= s do
@@ -2233,43 +2465,77 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
elseif seq[n][char] then
n = n + 1
else
- match = false
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpre[discfound]
+ else
+ match = false
+ end
break
end
else
- match = false
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpre[discfound]
+ else
+ match = false
+ end
break
end
else
- match = false
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpre[discfound]
+ else
+ match = false
+ end
break
end
elseif id == disc_code then
- if check_discretionaries then
- local replace = getfield(current,"replace")
- if replace then
- -- so far we never entered this branch
- while replace do
- if seq[n][getchar(replace)] then
- n = n + 1
- replace = getnext(replace)
- if not replace then
- break
- elseif n > s then
- break
- end
- else
- match = false
+ diskseen = true
+ discfound = current
+ notmatchpre[current] = nil
+ notmatchpost[current] = true
+ notmatchreplace[current] = nil
+ local pre = getfield(current,"pre")
+ local replace = getfield(current,"replace")
+ if pre then
+ local n = n
+ while pre do
+ if seq[n][getchar(pre)] then
+ n = n + 1
+ pre = getnext(pre)
+ if n > s then
break
end
+ else
+ notmatchpre[current] = true
+ break
end
- if not match then
+ end
+ if n <= s then
+ notmatchpre[current] = true
+ end
+ else
+ notmatchpre[current] = true
+ end
+ if replace then
+ -- so far we never entered this branch
+ while replace do
+ if seq[n][getchar(replace)] then
+ n = n + 1
+ replace = getnext(replace)
+ if n > s then
+ break
+ end
+ else
+ notmatchreplace[current] = true
+ match = notmatchpre[current]
break
- elseif check_discretionaries == "trace" then
- report_chain("check disc action in after")
end
- else
- -- skip 'm
+ end
+ if not match then
+ break
end
else
-- skip 'm
@@ -2294,7 +2560,8 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
end
if match then
- -- ck == currentcontext
+ -- can lookups be of a different type ?
+ local diskchain = diskseen or sweepnode
if trace_contexts then
local rule, lookuptype, f, l = ck[1], ck[2], ck[4], ck[5]
local char = getchar(start)
@@ -2314,10 +2581,14 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
local chainlookupname = chainlookups[1]
local chainlookup = lookuptable[chainlookupname]
if chainlookup then
- local cp = chainprocs[chainlookup.type]
- if cp then
+ local chainproc = chainprocs[chainlookup.type]
+ if chainproc then
local ok
- head, start, ok = cp(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ if diskchain then
+ head, start, ok = chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence,chainproc)
+ else
+ head, start, ok = chainproc(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ end
if ok then
done = true
end
@@ -2335,7 +2606,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
local char = getchar(start)
local ccd = descriptions[char]
if ccd then
- local class = ccd.class
+ local class = ccd.class or "base"
if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
start = getnext(start)
else
@@ -2353,14 +2624,18 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
-- we just advance
i = i + 1
else
- local cp = chainmores[chainlookup.type]
- if not cp then
+ local chainproc = chainprocs[chainlookup.type]
+ if not chainproc then
-- actually an error
logprocess("%s: %s is not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type)
i = i + 1
else
local ok, n
- head, start, ok, n = cp(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,i,sequence)
+ if diskchain then
+ head, start, ok = chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence,chainproc)
+ else
+ head, start, ok, n = chainproc(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,i,sequence)
+ end
-- messy since last can be changed !
if ok then
done = true
@@ -2401,8 +2676,16 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
end
end
+ if done then
+ break -- out of contexts (new, needs checking)
+ end
end
end
+ if diskseen then -- maybe move up so that we can turn checking on/off
+ notmatchpre = { }
+ notmatchpost = { }
+ notmatchreplace = { }
+ end
return head, start, done
end
@@ -2487,7 +2770,7 @@ local function initialize(sequence,script,language,enabled)
local order = sequence.order
if order then
for i=1,#order do --
- local kind = order[i] --
+ local kind = order[i] --
local valid = enabled[kind]
if valid then
local scripts = features[kind] --
@@ -2537,38 +2820,11 @@ function otf.dataset(tfmdata,font) -- generic variant, overloaded in context
return rl
end
--- elseif id == glue_code then
--- if p[5] then -- chain
--- local pc = pp[32]
--- if pc then
--- start, ok = start, false -- p[1](start,kind,p[2],pc,p[3],p[4])
--- if ok then
--- done = true
--- end
--- if start then start = getnext(start) end
--- else
--- start = getnext(start)
--- end
--- else
--- start = getnext(start)
--- end
-
--- there will be a new direction parser (pre-parsed etc)
-
--- less bytecode: 290 -> 254
---
--- attr = attr or false
---
--- local a = getattr(start,0)
--- if (a == attr and (not attribute or getprop(start,a_state) == attribute)) or (not attribute or getprop(start,a_state) == attribute) then
--- -- the action
--- end
-
-- assumptions:
--
-- * languages that use complex disc nodes
-local function kernrun(disc,run) -- we can assume that prev and next are glyphs
+local function kernrun(disc,run)
--
-- we catch <font 1><disc font 2>
--
@@ -2576,22 +2832,27 @@ local function kernrun(disc,run) -- we can assume that prev and next are glyphs
report_run("kern") -- will be more detailed
end
--
- local prev = getprev(disc) -- todo, keep these in the main loop
- local next = getnext(disc) -- todo, keep these in the main loop
+ local prev = getprev(disc) -- todo, keep these in the main loop
+ local next = getnext(disc) -- todo, keep these in the main loop
--
- local pre = getfield(disc,"pre")
- local post = getfield(disc,"post")
- local replace = getfield(disc,"replace")
+ local pre = getfield(disc,"pre")
+ local post = getfield(disc,"post")
+ local replace = getfield(disc,"replace")
--
- if pre or replace then
- if not (prev and getid(prev) == glyph_code and getfont(prev) == currentfont and getsubtype(prev)<256) then
- prev = false
- end
+ local prevmarks = prev
+ --
+ -- can be optional, because why on earth do we get a disc after a mark (okay, maybe when a ccmp
+ -- has happened but then it should be in the disc so basically this test indicates an error)
+ --
+ while prevmarks and getid(prevmarks) == glyph_code and marks[getchar(prevmarks)] and getfont(prevmarks) == currentfont and getsubtype(prevmarks) < 256 do
+ prevmarks = getprev(prevmarks)
end
- if post or replace then
- if not (next and getid(next) == glyph_code and getfont(next) == currentfont and getsubtype(next)<256) then
- next = false
- end
+ --
+ if prev and (pre or replace) and not (getid(prev) == glyph_code and getfont(prev) == currentfont and getsubtype(prev)<256) then
+ prev = false
+ end
+ if next and (post or replace) and not (getid(next) == glyph_code and getfont(next) == currentfont and getsubtype(next)<256) then
+ next = false
end
--
if not pre then
@@ -2600,7 +2861,7 @@ local function kernrun(disc,run) -- we can assume that prev and next are glyphs
local nest = getprev(pre)
setfield(pre,"prev",prev)
setfield(prev,"next",pre)
- run(prev,"preinjections")
+ run(prevmarks,"preinjections")
setfield(pre,"prev",nest)
setfield(prev,"next",disc)
else
@@ -2613,7 +2874,7 @@ local function kernrun(disc,run) -- we can assume that prev and next are glyphs
local tail = find_node_tail(post)
setfield(tail,"next",next)
setfield(next,"prev",tail)
- run(post,"postinjections",tail)
+ run(post,"postinjections",next)
setfield(tail,"next",nil)
setfield(next,"prev",disc)
else
@@ -2622,6 +2883,11 @@ local function kernrun(disc,run) -- we can assume that prev and next are glyphs
--
if not replace and prev and next then
-- this should be already done by discfound
+ setfield(prev,"next",next)
+ setfield(next,"prev",prev)
+ run(prevmarks,"injections",next)
+ setfield(prev,"next",disc)
+ setfield(next,"prev",disc)
elseif prev and next then
local tail = find_node_tail(replace)
local nest = getprev(replace)
@@ -2629,7 +2895,7 @@ local function kernrun(disc,run) -- we can assume that prev and next are glyphs
setfield(prev,"next",replace)
setfield(tail,"next",next)
setfield(next,"prev",tail)
- run(prev,"replaceinjections",tail)
+ run(prevmarks,"replaceinjections",next)
setfield(replace,"prev",nest)
setfield(prev,"next",disc)
setfield(tail,"next",nil)
@@ -2638,14 +2904,14 @@ local function kernrun(disc,run) -- we can assume that prev and next are glyphs
local nest = getprev(replace)
setfield(replace,"prev",prev)
setfield(prev,"next",replace)
- run(prev,"replaceinjections")
+ run(prevmarks,"replaceinjections")
setfield(replace,"prev",nest)
setfield(prev,"next",disc)
elseif next then
local tail = find_node_tail(replace)
setfield(tail,"next",next)
setfield(next,"prev",tail)
- run(replace,"replaceinjections",tail)
+ run(replace,"replaceinjections",next)
setfield(tail,"next",nil)
setfield(next,"prev",disc)
else
@@ -2663,6 +2929,8 @@ local function comprun(disc,run)
--
local pre = getfield(disc,"pre")
if pre then
+ sweepnode = disc
+ sweeptype = "pre" -- in alternative code preinjections is used (also used then for proeprties, saves a variable)
local new, done = run(pre)
if done then
setfield(disc,"pre",new)
@@ -2671,6 +2939,8 @@ local function comprun(disc,run)
--
local post = getfield(disc,"post")
if post then
+ sweepnode = disc
+ sweeptype = "post"
local new, done = run(post)
if done then
setfield(disc,"post",new)
@@ -2679,14 +2949,18 @@ local function comprun(disc,run)
--
local replace = getfield(disc,"replace")
if replace then
+ sweepnode = disc
+ sweeptype = "replace"
local new, done = run(replace)
if done then
setfield(disc,"replace",new)
end
end
+ sweepnode = nil
+ sweeptype = nil
end
-local function testrun(disc,trun,crun)
+local function testrun(disc,trun,crun) -- use helper
local next = getnext(disc)
if next then
local replace = getfield(disc,"replace")
@@ -2784,6 +3058,7 @@ local function featuresprocessor(head,font,attr)
currentfont = font
rlmode = 0
+ sweephead = { }
local sequences = resources.sequences
local done = false
@@ -2799,10 +3074,8 @@ local function featuresprocessor(head,font,attr)
-- Keeping track of the headnode is needed for devanagari (I generalized it a bit
-- so that multiple cases are also covered.)
- -- todo: retain prev
-
-- We don't goto the next node of a disc node is created so that we can then treat
- -- the pre, post and replace. It's a bit of a hack but works out ok for most cases.
+ -- the pre, post and replace. It's abit of a hack but works out ok for most cases.
-- there can be less subtype and attr checking in the comprun etc helpers
@@ -2817,10 +3090,9 @@ local function featuresprocessor(head,font,attr)
local topstack = 0
local success = false
local typ = sequence.type
- local gpossing = typ == "gpos_single" or typ == "gpos_pair"
+ local gpossing = typ == "gpos_single" or typ == "gpos_pair" -- maybe all of them
local subtables = sequence.subtables
local handler = handlers[typ]
-
if typ == "gsub_reversecontextchain" then -- chain < 0
-- this is a limited case, no special treatments like 'init' etc
-- we need to get rid of this slide! probably no longer needed in latest luatex
@@ -2841,8 +3113,7 @@ local function featuresprocessor(head,font,attr)
local lookupname = subtables[i]
local lookupcache = lookuphash[lookupname]
if lookupcache then
- -- local lookupmatch = lookupcache[getchar(start)]
- local lookupmatch = lookupcache[start]
+ local lookupmatch = lookupcache[char]
if lookupmatch then
-- todo: disc?
head, start, success = handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,i)
@@ -2870,15 +3141,20 @@ local function featuresprocessor(head,font,attr)
local start = head -- local ?
rlmode = 0 -- to be checked ?
if ns == 1 then -- happens often
- local lookupname = subtables[1]
+ local lookupname = subtables[1]
local lookupcache = lookuphash[lookupname]
if not lookupcache then -- also check for empty cache
report_missing_cache(typ,lookupname)
else
- local function c_run(start) -- no need to check for 256 and attr probably also the same
- local head = start
- local done = false
+ local function c_run(head) -- no need to check for 256 and attr probably also the same
+ local done = false
+ local start = sweephead[head]
+ if start then
+ sweephead[head] = nil
+ else
+ start = head
+ end
while start do
local id = getid(start)
if id ~= glyph_code then
@@ -2965,7 +3241,7 @@ local function featuresprocessor(head,font,attr)
-- sequence kan weg
local h, d, ok = handler(head,prev,kind,lookupname,lookupmatch,sequence,lookuphash,1)
if ok then
- done = true
+ done = true
success = true
end
end
@@ -2991,7 +3267,7 @@ local function featuresprocessor(head,font,attr)
if lookupmatch then
local h, d, ok = handler(sub,n,kind,lookupname,lookupmatch,sequence,lookuphash,1,injection)
if ok then
- done = true
+ done = true
success = true
end
end
@@ -3035,39 +3311,30 @@ local function featuresprocessor(head,font,attr)
start = getnext(start)
end
elseif id == disc_code then
- local discretionary = getsubtype(start) == discretionary_code
- if gpossing then
- if discretionary then
- kernrun(start,k_run)
- else
- discrun(start,d_run,k_run)
- end
- start = getnext(start)
- elseif discretionary then
- if typ == "gsub_ligature" then
- start = testrun(start,t_run,c_run)
- else
- comprun(start,c_run)
- start = getnext(start)
- end
- else
+ if gpossing then
+ kernrun(start,k_run)
+ start = getnext(start)
+ elseif typ == "gsub_ligature" then
+ start = testrun(start,t_run,c_run)
+ else
+ comprun(start,c_run)
start = getnext(start)
- end
+ end
elseif id == whatsit_code then -- will be function
local subtype = getsubtype(start)
if subtype == dir_code then
local dir = getfield(start,"dir")
- if dir == "+TRT" or dir == "+TLT" then
+ if dir == "+TLT" then
topstack = topstack + 1
dirstack[topstack] = dir
- elseif dir == "-TRT" or dir == "-TLT" then
- topstack = topstack - 1
- end
- local newdir = dirstack[topstack]
- if newdir == "+TRT" then
- rlmode = -1
- elseif newdir == "+TLT" then
rlmode = 1
+ elseif dir == "+TRT" then
+ topstack = topstack + 1
+ dirstack[topstack] = dir
+ rlmode = -1
+ elseif dir == "-TLT" or dir == "-TRT" then
+ topstack = topstack - 1
+ rlmode = dirstack[topstack] == "+TLT" and 1 or -1
else
rlmode = rlparmode
end
@@ -3100,9 +3367,14 @@ local function featuresprocessor(head,font,attr)
else
- local function c_run(start)
- local head = start
- local done = false
+ local function c_run(head)
+ local done = false
+ local start = sweephead[head]
+ if start then
+ sweephead[head] = nil
+ else
+ start = head
+ end
while start do
local id = getid(start)
if id ~= glyph_code then
@@ -3121,7 +3393,6 @@ local function featuresprocessor(head,font,attr)
local lookupname = subtables[i]
local lookupcache = lookuphash[lookupname]
if lookupcache then
- -- local lookupmatch = lookupcache[getchar(start)]
local lookupmatch = lookupcache[char]
if lookupmatch then
-- we could move all code inline but that makes things even more unreadable
@@ -3164,7 +3435,7 @@ local function featuresprocessor(head,font,attr)
-- brr prev can be disc
local char = getchar(prev)
for i=1,ns do
- local lookupname = subtables[i]
+ local lookupname = subtables[i]
local lookupcache = lookuphash[lookupname]
if lookupcache then
local lookupmatch = lookupcache[char]
@@ -3199,7 +3470,7 @@ local function featuresprocessor(head,font,attr)
if id == glyph_code then
local char = getchar(n)
for i=1,ns do
- local lookupname = subtables[i]
+ local lookupname = subtables[i]
local lookupcache = lookuphash[lookupname]
if lookupcache then
local lookupmatch = lookupcache[char]
@@ -3234,7 +3505,7 @@ local function featuresprocessor(head,font,attr)
if a then
local char = getchar(start)
for i=1,ns do
- local lookupname = subtables[i]
+ local lookupname = subtables[i]
local lookupcache = lookuphash[lookupname]
if lookupcache then
local lookupmatch = lookupcache[char]
@@ -3279,7 +3550,7 @@ local function featuresprocessor(head,font,attr)
end
if a then
for i=1,ns do
- local lookupname = subtables[i]
+ local lookupname = subtables[i]
local lookupcache = lookuphash[lookupname]
if lookupcache then
local char = getchar(start)
@@ -3312,39 +3583,30 @@ local function featuresprocessor(head,font,attr)
start = getnext(start)
end
elseif id == disc_code then
- local discretionary = getsubtype(start) == discretionary_code
if gpossing then
- if discretionary then
- kernrun(start,k_run)
- else
- discrun(start,d_run,k_run)
- end
+ kernrun(start,k_run)
start = getnext(start)
- elseif discretionary then
- if typ == "gsub_ligature" then
- start = testrun(start,t_run,c_run)
- else
- comprun(start,c_run)
- start = getnext(start)
- end
+ elseif typ == "gsub_ligature" then
+ start = testrun(start,t_run,c_run)
else
+ comprun(start,c_run)
start = getnext(start)
end
elseif id == whatsit_code then
local subtype = getsubtype(start)
if subtype == dir_code then
local dir = getfield(start,"dir")
- if dir == "+TRT" or dir == "+TLT" then
+ if dir == "+TLT" then
topstack = topstack + 1
dirstack[topstack] = dir
- elseif dir == "-TRT" or dir == "-TLT" then
- topstack = topstack - 1
- end
- local newdir = dirstack[topstack]
- if newdir == "+TRT" then
- rlmode = -1
- elseif newdir == "+TLT" then
rlmode = 1
+ elseif dir == "+TRT" then
+ topstack = topstack + 1
+ dirstack[topstack] = dir
+ rlmode = -1
+ elseif dir == "-TLT" or dir == "-TRT" then
+ topstack = topstack - 1
+ rlmode = dirstack[topstack] == "+TLT" and 1 or -1
else
rlmode = rlparmode
end
diff --git a/tex/generic/context/luatex/luatex-fonts.lua b/tex/generic/context/luatex/luatex-fonts.lua
index 738118945..dab3025e0 100644
--- a/tex/generic/context/luatex/luatex-fonts.lua
+++ b/tex/generic/context/luatex/luatex-fonts.lua
@@ -27,16 +27,10 @@ if not modules then modules = { } end modules ['luatex-fonts'] = {
-- also add more helper code here, but that depends to what extend metatex (sidetrack of context)
-- evolves into a low level layer (depends on time, as usual).
--- texio.write_nl("")
--- texio.write_nl("--------------------------------------------------------------------------------")
--- texio.write_nl("The font code has been brought in sync with the context version of 2015.08.31 so")
--- texio.write_nl("if things don't work out as expected the interfacing needs to be checked. When")
--- texio.write_nl("this works as expected a second upgrade will happen that gives a more complete")
--- texio.write_nl("support and another sync with the context code (that new code is currently being")
--- texio.write_nl("tested. The base pass is now integrated in the main pass. The results can differ")
--- texio.write_nl("from those in context because there we integrate some mechanisms differently.")
--- texio.write_nl("--------------------------------------------------------------------------------")
--- texio.write_nl("")
+-- The code here is the same as in context version 2015.09.11 but the rendering in context can be
+-- different from generic. This can be a side effect of additional callbacks, additional features
+-- and interferences between mechanisms between macro packages. We use the rendering in context
+-- and luatex-plain as reference for issues.
utf = utf or unicode.utf8