diff options
author | Karl Berry <karl@freefriends.org> | 2018-09-26 20:50:34 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2018-09-26 20:50:34 +0000 |
commit | 78334b0d4607b242273f9d0cde94f6a6fba51832 (patch) | |
tree | 5b604ee30bb611eeeae95ed4218b4e7fd6eb00b8 /Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otj.lua | |
parent | 3a0140d05a7e481750ec23a30ed5cf3cdef61eb7 (diff) |
luaotfload (26sep18)
git-svn-id: svn://tug.org/texlive/trunk@48771 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otj.lua')
-rw-r--r-- | Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otj.lua | 1181 |
1 files changed, 666 insertions, 515 deletions
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otj.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otj.lua index 68cf608ec94..8d1b540be0f 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otj.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otj.lua @@ -7,7 +7,7 @@ if not modules then modules = { } end modules ['font-otj'] = { } -- This property based variant is not faster but looks nicer than the attribute one. We --- need to use rawget (which is apbout 4 times slower than a direct access but we cannot +-- need to use rawget (which is about 4 times slower than a direct access but we cannot -- get/set that one for our purpose! This version does a bit more with discretionaries -- (and Kai has tested it with his collection of weird fonts.) @@ -16,31 +16,37 @@ if not modules then modules = { } end modules ['font-otj'] = { -- cleaner to have an identification pass here. Also, I need to keep tracing in mind so -- being too clever here is dangerous. --- The subtype test is not needed as there will be no (new) properties set, given that we --- reset the properties. - -- As we have a rawget on properties we don't need one on injections. --- The use_advance code is just a test and is meant for testing and manuals. There is no +-- The use_advance code was just a test and is meant for testing and manuals. There is no -- performance (or whatever) gain and using kerns is somewhat cleaner (at least for now). --- Maybe: subtype fontkern when pure kerns. +-- An alternative is to have a list per base of all marks and then do a run over the node +-- list that resolves the accumulated l/r/x/y and then do an inject pass. + +-- if needed we can flag a kern node as immutable + +-- The thing with these positioning options is that it is not clear what Uniscribe does with +-- the 2rl flag and we keep oscillating a between experiments. if not nodes.properties then return end -local next, rawget = next, rawget +local next, rawget, tonumber = next, rawget, tonumber local fastcopy = table.fastcopy -local registertracker = trackers.register +local registertracker = trackers.register +local registerdirective = directives.register local trace_injections = false registertracker("fonts.injections", function(v) trace_injections = v end) local trace_marks = false registertracker("fonts.injections.marks", function(v) trace_marks = v end) local trace_cursive = false registertracker("fonts.injections.cursive", function(v) trace_cursive = v end) local trace_spaces = false registertracker("fonts.injections.spaces", function(v) trace_spaces = v end) --- use_advance is just an experiment: it makes copying glyphs (instead of new_glyph) dangerous - -local use_advance = false directives.register("fonts.injections.advance", function(v) use_advance = v end) +-- local fix_cursive_marks = false +-- +-- registerdirective("fonts.injections.fixcursivemarks", function(v) +-- fix_cursive_marks = v +-- end) local report_injections = logs.reporter("fonts","injections") local report_spaces = logs.reporter("fonts","spaces") @@ -50,6 +56,7 @@ local attributes, nodes, node = attributes, nodes, node fonts = fonts local hashes = fonts.hashes local fontdata = hashes.identifiers +local fontmarks = hashes.marks ----- parameters = fonts.hashes.parameters -- not in generic ----- resources = fonts.hashes.resources -- not in generic @@ -69,92 +76,105 @@ local glue_code = nodecodes.glue local nuts = nodes.nuts local nodepool = nuts.pool -local newkern = nodepool.kern - local tonode = nuts.tonode local tonut = nuts.tonut -local getfield = nuts.getfield local setfield = nuts.setfield local getnext = nuts.getnext local getprev = nuts.getprev local getid = nuts.getid local getfont = nuts.getfont -local getsubtype = nuts.getsubtype local getchar = nuts.getchar +local getoffsets = nuts.getoffsets local getboth = nuts.getboth - -local ischar = nuts.is_char - local getdisc = nuts.getdisc local setdisc = nuts.setdisc +local setoffsets = nuts.setoffsets +local ischar = nuts.is_char +local getkern = nuts.getkern +local setkern = nuts.setkern +local setlink = nuts.setlink +local setwidth = nuts.setwidth +local getwidth = nuts.getwidth + +----- traverse_id = nuts.traverse_id +----- traverse_char = nuts.traverse_char +local nextchar = nuts.traversers.char +local nextglue = nuts.traversers.glue -local traverse_id = nuts.traverse_id -local traverse_char = nuts.traverse_char local insert_node_before = nuts.insert_before local insert_node_after = nuts.insert_after local properties = nodes.properties.data -function injections.installnewkern(nk) - newkern = nk or newkern -end +local fontkern = nuts.pool and nuts.pool.fontkern -- context +local italickern = nuts.pool and nuts.pool.italickern -- context -local nofregisteredkerns = 0 -local nofregisteredpairs = 0 -local nofregisteredmarks = 0 -local nofregisteredcursives = 0 -local keepregisteredcounts = false +local useitalickerns = false + +directives.register("fonts.injections.useitalics", function(v) + if v then + report_injections("using italics for space kerns (tracing only)") + end + useitalickerns = v +end) + +do if not fontkern then -- generic + + local thekern = nuts.new("kern",0) -- fontkern + local setkern = nuts.setkern + local copy_node = nuts.copy_node + + fontkern = function(k) + local n = copy_node(thekern) + setkern(n,k) + return n + end + +end end + +do if not italickern then -- generic + + local thekern = nuts.new("kern",3) -- italiccorrection + local setkern = nuts.setkern + local copy_node = nuts.copy_node + + italickern = function(k) + local n = copy_node(thekern) + setkern(n,k) + return n + end + +end end + +function injections.installnewkern() end -- obsolete + +local nofregisteredkerns = 0 +local nofregisteredpositions = 0 +local nofregisteredmarks = 0 +local nofregisteredcursives = 0 +local keepregisteredcounts = false function injections.keepcounts() keepregisteredcounts = true end function injections.resetcounts() - nofregisteredkerns = 0 - nofregisteredpairs = 0 - nofregisteredmarks = 0 - nofregisteredcursives = 0 - keepregisteredcounts = false + nofregisteredkerns = 0 + nofregisteredpositions = 0 + nofregisteredmarks = 0 + nofregisteredcursives = 0 + keepregisteredcounts = false end -- We need to make sure that a possible metatable will not kick in unexpectedly. --- function injections.reset(n) --- local p = rawget(properties,n) --- if p and rawget(p,"injections") then --- p.injections = nil --- end --- end - --- function injections.copy(target,source) --- local sp = rawget(properties,source) --- if sp then --- local tp = rawget(properties,target) --- local si = rawget(sp,"injections") --- if si then --- si = fastcopy(si) --- if tp then --- tp.injections = si --- else --- propertydata[target] = { --- injections = si, --- } --- end --- else --- if tp then --- tp.injections = nil --- end --- end --- end --- end - function injections.reset(n) local p = rawget(properties,n) if p then - p.injections = false -- { } + p.injections = false -- { } -- nil should work too as we use rawget else - properties[n] = false -- { injections = { } } + properties[n] = false -- { injections = { } } -- nil should work too as we use rawget end end @@ -162,14 +182,13 @@ function injections.copy(target,source) local sp = rawget(properties,source) if sp then local tp = rawget(properties,target) - -- local si = rawget(sp,"injections") local si = sp.injections if si then si = fastcopy(si) if tp then tp.injections = si else - propertydata[target] = { + properties[target] = { injections = si, } end @@ -188,10 +207,9 @@ function injections.copy(target,source) end end -function injections.setligaindex(n,index) +function injections.setligaindex(n,index) -- todo: don't set when 0 local p = rawget(properties,n) if p then - -- local i = rawget(p,"injections") local i = p.injections if i then i.ligaindex = index @@ -212,7 +230,6 @@ end function injections.getligaindex(n,default) local p = rawget(properties,n) if p then - -- local i = rawget(p,"injections") local i = p.injections if i then return i.ligaindex or default @@ -221,7 +238,15 @@ function injections.getligaindex(n,default) return default end -function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmnext) -- hm: nuts or nodes +function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmnext,r2lflag) + + -- The standard says something about the r2lflag related to the first in a series: + -- + -- When this bit is set, the last glyph in a given sequence to which the cursive + -- attachment lookup is applied, will be positioned on the baseline. + -- + -- But it looks like we don't need to consider it. + local dx = factor*(exit[1]-entry[1]) local dy = -factor*(exit[2]-entry[2]) local ws = tfmstart.width @@ -239,7 +264,6 @@ function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmne -- local p = rawget(properties,start) if p then - -- local i = rawget(p,"injections") local i = p.injections if i then i.cursiveanchor = true @@ -257,7 +281,6 @@ function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmne end local p = rawget(properties,nxt) if p then - -- local i = rawget(p,"injections") local i = p.injections if i then i.cursivex = dx @@ -279,17 +302,19 @@ 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) -- r2lflag & tfmchr not used - local x = factor*spec[1] - local y = factor*spec[2] - local w = factor*spec[3] - local h = factor*spec[4] +-- kind: 0=single 1=first of pair, 2=second of pair + +function injections.setposition(kind,current,factor,rlmode,spec,injection) + local x = factor * (spec[1] or 0) + local y = factor * (spec[2] or 0) + local w = factor * (spec[3] or 0) + local h = factor * (spec[4] or 0) 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 local rightkern = w - x -- to normal kerns where we set only leftkern if leftkern ~= 0 or rightkern ~= 0 or yoffset ~= 0 then - nofregisteredpairs = nofregisteredpairs + 1 + nofregisteredpositions = nofregisteredpositions + 1 if rlmode and rlmode < 0 then leftkern, rightkern = rightkern, leftkern end @@ -298,8 +323,7 @@ function injections.setpair(current,factor,rlmode,r2lflag,spec,injection) -- r2l end local p = rawget(properties,current) if p then - -- local i = p[injection] - local i = rawget(p,injection) + local i = p[injection] if i then if leftkern ~= 0 then i.leftkern = (i.leftkern or 0) + leftkern @@ -336,15 +360,15 @@ function injections.setpair(current,factor,rlmode,r2lflag,spec,injection) -- r2l }, } end - return x, y, w, h, nofregisteredpairs + return x, y, w, h, nofregisteredpositions end end return x, y, w, h -- no bound end --- This needs checking for rl < 0 but it is unlikely that a r2l script uses kernclasses between --- glyphs so we're probably safe (KE has a problematic font where marks interfere with rl < 0 in --- the previous case) +-- The next one is used for simple kerns coming from a truetype kern table. The r2l +-- variant variant needs checking but it is unlikely that a r2l script uses thsi +-- feature. function injections.setkern(current,factor,rlmode,x,injection) local dx = factor * x @@ -355,8 +379,7 @@ function injections.setkern(current,factor,rlmode,x,injection) injection = "injections" end if p then - -- local i = rawget(p,injection) - local i = rawget(p,injection) + local i = p[injection] if i then i.leftkern = dx + (i.leftkern or 0) else @@ -377,8 +400,62 @@ function injections.setkern(current,factor,rlmode,x,injection) end end -function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk,checkmark) -- ba=baseanchor, ma=markanchor +-- This one is an optimization of pairs where we have only a "w" entry. This one is +-- potentially different from the previous one wrt r2l. It needs checking. The +-- optimization relates to smaller tma files. + +function injections.setmove(current,factor,rlmode,x,injection) + local dx = factor * x + if dx ~= 0 then + nofregisteredkerns = nofregisteredkerns + 1 + local p = rawget(properties,current) + if not injection then + injection = "injections" + end + if rlmode and rlmode < 0 then + -- we need to swap with a single so then we also need to to it here + -- as move is just a simple single + if p then + local i = p[injection] + if i then + i.rightkern = dx + (i.rightkern or 0) + else + p[injection] = { + rightkern = dx, + } + end + else + properties[current] = { + [injection] = { + rightkern = dx, + }, + } + end + else + if p then + local i = p[injection] + if i then + i.leftkern = dx + (i.leftkern or 0) + else + p[injection] = { + leftkern = dx, + } + end + else + properties[current] = { + [injection] = { + leftkern = dx, + }, + } + end + end + return dx, nofregisteredkerns + else + return 0, 0 + end +end +function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk,checkmark) -- ba=baseanchor, ma=markanchor local dx, dy = factor*(ba[1]-ma[1]), factor*(ba[2]-ma[2]) nofregisteredmarks = nofregisteredmarks + 1 if rlmode >= 0 then @@ -387,15 +464,20 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk,checkmar local p = rawget(properties,start) -- hm, dejavu serif does a sloppy mark2mark before mark2base if p then - -- local i = rawget(p,"injections") local i = p.injections if i then if i.markmark then -- out of order mkmk: yes or no or option else - i.markx = dx - i.marky = dy - i.markdir = rlmode or 0 + if dx ~= 0 then + i.markx = dx + end + if y ~= 0 then + i.marky = dy + end + if rlmode then + i.markdir = rlmode + end i.markbase = nofregisteredmarks i.markbasenode = base i.markmark = mkmk @@ -441,7 +523,7 @@ local function show(n,what,nested,symbol) if n then local p = rawget(properties,n) if p then - local i = rawget(p,what) + local i = p[what] if i then local leftkern = i.leftkern or 0 local rightkern = i.rightkern or 0 @@ -483,7 +565,7 @@ end local function showsub(n,what,where) report_injections("begin subrun: %s",where) - for n in traverse_id(glyph_code,n) do + for n in nextchar, n do showchar(n,where) show(n,what,where," ") end @@ -491,8 +573,9 @@ local function showsub(n,what,where) end local function trace(head,where) - report_injections("begin run %s: %s kerns, %s pairs, %s marks and %s cursives registered", - where or "",nofregisteredkerns,nofregisteredpairs,nofregisteredmarks,nofregisteredcursives) + report_injections() + report_injections("begin run %s: %s kerns, %s positions, %s marks and %s cursives registered", + where or "",nofregisteredkerns,nofregisteredpositions,nofregisteredmarks,nofregisteredcursives) local n = head while n do local id = getid(n) @@ -527,11 +610,12 @@ local function show_result(head) while current do local id = getid(current) if id == glyph_code then - report_injections("char: %C, width %p, xoffset %p, yoffset %p", - getchar(current),getfield(current,"width"),getfield(current,"xoffset"),getfield(current,"yoffset")) + local w = getwidth(current) + local x, y = getoffsets(current) + report_injections("char: %C, width %p, xoffset %p, yoffset %p",getchar(current),w,x,y) skipping = false elseif id == kern_code then - report_injections("kern: %p",getfield(current,"kern")) + report_injections("kern: %p",getkern(current)) skipping = false elseif not skipping then report_injections() @@ -539,6 +623,7 @@ local function show_result(head) end current = getnext(current) end + report_injections() end -- G +D-pre G @@ -550,7 +635,6 @@ end -- +D-replace +D-replace local function inject_kerns_only(head,where) - head = tonut(head) if trace_injections then trace(head,"kerns") end @@ -558,7 +642,7 @@ local function inject_kerns_only(head,where) local prev = nil local next = nil local prevdisc = nil - local prevglyph = nil + -- local prevglyph = nil local pre = nil -- saves a lookup local post = nil -- saves a lookup local replace = nil -- saves a lookup @@ -566,96 +650,75 @@ local function inject_kerns_only(head,where) local posttail = nil -- saves a lookup local replacetail = nil -- saves a lookup while current do - local id = getid(current) local next = getnext(current) - if id == glyph_code then - if getsubtype(current) < 256 then - local p = rawget(properties,current) - if p then - -- local i = rawget(p,"injections") - local i = p.injections - if i then - -- left|glyph|right - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - if use_advance then - setfield(current,"xoffset",leftkern) - setfield(current,"xadvance",leftkern) - else - insert_node_before(head,current,newkern(leftkern)) + local char, id = ischar(current) + if char then + local p = rawget(properties,current) + if p then + local i = p.injections + if i then + -- left|glyph|right + local leftkern = i.leftkern + if leftkern and leftkern ~= 0 then + head = insert_node_before(head,current,fontkern(leftkern)) + end + end + if prevdisc then + local done = false + if post then + local i = p.postinjections + if i then + local leftkern = i.leftkern + if leftkern and leftkern ~= 0 then + setlink(posttail,fontkern(leftkern)) + done = true end end end - if prevdisc then - local done = false - if post then - -- local i = rawget(p,"postinjections") - local i = p.postinjections - if i then - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - if use_advance then - setfield(post,"xadvance",leftkern) - else - insert_node_after(post,posttail,newkern(leftkern)) - done = true - end - end + if replace then + local i = p.replaceinjections + if i then + local leftkern = i.leftkern + if leftkern and leftkern ~= 0 then + setlink(replacetail,fontkern(leftkern)) + done = true end end - if replace then - -- local i = rawget(p,"replaceinjections") - local i = p.replaceinjections - if i then - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - if use_advance then - setfield(replace,"xadvance",leftkern) - else - insert_node_after(replace,replacetail,newkern(leftkern)) - done = true - end - end - end - else - -- local i = rawget(p,"emptyinjections") - local i = p.emptyinjections - if i then - -- glyph|disc|glyph (special case) - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - setfield(prev,"replace",newkern(leftkern)) -- maybe also leftkern - end + else + local i = p.emptyinjections + if i then + -- glyph|disc|glyph (special case) + local leftkern = i.leftkern + if leftkern and leftkern ~= 0 then + setfield(prev,"replace",fontkern(leftkern)) -- maybe also leftkern end end - if done then - setdisc(prevdisc,pre,post,replace) - end + end + if done then + setdisc(prevdisc,pre,post,replace) end end end prevdisc = nil - prevglyph = current + -- prevglyph = current + elseif char == false then + -- other font + prevdisc = nil + -- prevglyph = current elseif id == disc_code then pre, post, replace, pretail, posttail, replacetail = getdisc(current,true) local done = false if pre then -- left|pre glyphs|right - for n in traverse_char(pre) do + for n in nextchar, pre do local p = rawget(properties,n) if p then - -- local i = rawget(p,"injections") or rawget(p,"preinjections") local i = p.injections or p.preinjections if i then local leftkern = i.leftkern if leftkern and leftkern ~= 0 then - if use_advance then - setfield(pre,"xoffset",leftkern) - setfield(pre,"xadvance",leftkern) - else - pre = insert_node_before(pre,n,newkern(leftkern)) - done = true - end + pre = insert_node_before(pre,n,fontkern(leftkern)) + done = true end end end @@ -663,21 +726,15 @@ local function inject_kerns_only(head,where) end if post then -- left|post glyphs|right - for n in traverse_char(post) do + for n in nextchar, post do local p = rawget(properties,n) if p then - -- local i = rawget(p,"injections") or rawget(p,"postinjections") local i = p.injections or p.postinjections if i then local leftkern = i.leftkern if leftkern and leftkern ~= 0 then - if use_advance then - setfield(post,"xoffset",leftkern) - setfield(post,"xadvance",leftkern) - else - post = insert_node_before(post,n,newkern(leftkern)) - done = true - end + post = insert_node_before(post,n,fontkern(leftkern)) + done = true end end end @@ -685,21 +742,15 @@ local function inject_kerns_only(head,where) end if replace then -- left|replace glyphs|right - for n in traverse_char(replace) do + for n in nextchar, replace do local p = rawget(properties,n) if p then - -- local i = rawget(p,"injections") or rawget(p,"replaceinjections") local i = p.injections or p.replaceinjections if i then local leftkern = i.leftkern if leftkern and leftkern ~= 0 then - if use_advance then - setfield(replace,"xoffset",leftkern) - setfield(replace,"xadvance",leftkern) - else - replace = insert_node_before(replace,n,newkern(leftkern)) - done = true - end + replace = insert_node_before(replace,n,fontkern(leftkern)) + done = true end end end @@ -708,10 +759,10 @@ local function inject_kerns_only(head,where) if done then setdisc(current,pre,post,replace) end - prevglyph = nil + -- prevglyph = nil prevdisc = current else - prevglyph = nil + -- prevglyph = nil prevdisc = nil end prev = current @@ -723,13 +774,15 @@ local function inject_kerns_only(head,where) else nofregisteredkerns = 0 end - return tonode(head), true + if trace_injections then + show_result(head) + end + return head end -local function inject_pairs_only(head,where) - head = tonut(head) +local function inject_positions_only(head,where) if trace_injections then - trace(head,"pairs") + trace(head,"positions") end local current = head local prev = nil @@ -743,110 +796,110 @@ local function inject_pairs_only(head,where) local posttail = nil -- saves a lookup local replacetail = nil -- saves a lookup while current do - local id = getid(current) local next = getnext(current) - if id == glyph_code then - if getsubtype(current) < 256 then - local p = rawget(properties,current) - if p then - -- local i = rawget(p,"injections") - local i = p.injections - if i then - -- left|glyph|right - local yoffset = i.yoffset - if yoffset and yoffset ~= 0 then - setfield(current,"yoffset",yoffset) - end - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - head = insert_node_before(head,current,newkern(leftkern)) + local char, id = ischar(current) + if char then + local p = rawget(properties,current) + if p then + local i = p.injections + if i then + -- left|glyph|right + local yoffset = i.yoffset + if yoffset and yoffset ~= 0 then + setoffsets(current,false,yoffset) + end + local leftkern = i.leftkern + local rightkern = i.rightkern + if leftkern and leftkern ~= 0 then + if rightkern and leftkern == -rightkern then + setoffsets(current,leftkern,false) + rightkern = 0 + else + head = insert_node_before(head,current,fontkern(leftkern)) end + end + if rightkern and rightkern ~= 0 then + insert_node_after(head,current,fontkern(rightkern)) + end + else + local i = p.emptyinjections + if i then + -- glyph|disc|glyph (special case) local rightkern = i.rightkern if rightkern and rightkern ~= 0 then - insert_node_after(head,current,newkern(rightkern)) - end - else - -- local i = rawget(p,"emptyinjections") - local i = p.emptyinjections - if i then - -- glyph|disc|glyph (special case) --- is this okay? - local rightkern = i.rightkern - if rightkern and rightkern ~= 0 then - if next and getid(next) == disc_code then - if replace then - -- error, we expect an empty one - else - setfield(next,"replace",newkern(rightkern)) -- maybe also leftkern - end + if next and getid(next) == disc_code then + if replace then + -- error, we expect an empty one + else + setfield(next,"replace",fontkern(rightkern)) -- maybe also leftkern end end end end - if prevdisc then - local done = false - if post then - -- local i = rawget(p,"postinjections") - local i = p.postinjections - if i then - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - insert_node_after(post,posttail,newkern(leftkern)) - done = true - end + end + if prevdisc then + local done = false + if post then + local i = p.postinjections + if i then + local leftkern = i.leftkern + if leftkern and leftkern ~= 0 then + setlink(posttail,fontkern(leftkern)) + done = true end end - if replace then - -- local i = rawget(p,"replaceinjections") - local i = p.replaceinjections - if i then - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - insert_node_after(replace,replacetail,newkern(leftkern)) - done = true - end - end - else - local i = p.emptyinjections - if i then --- new .. okay? - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - setfield(prev,"replace",newkern(leftkern)) -- maybe also leftkern - end + end + if replace then + local i = p.replaceinjections + if i then + local leftkern = i.leftkern + if leftkern and leftkern ~= 0 then + setlink(replacetail,fontkern(leftkern)) + done = true end end - if done then - setdisc(prevdisc,pre,post,replace) + else + local i = p.emptyinjections + if i then + -- new .. okay? + local leftkern = i.leftkern + if leftkern and leftkern ~= 0 then + setfield(prev,"replace",fontkern(leftkern)) -- maybe also leftkern + end end end + if done then + setdisc(prevdisc,pre,post,replace) + end end end prevdisc = nil prevglyph = current + elseif char == false then + prevdisc = nil + prevglyph = current elseif id == disc_code then pre, post, replace, pretail, posttail, replacetail = getdisc(current,true) local done = false if pre then -- left|pre glyphs|right - for n in traverse_char(pre) do + for n in nextchar, pre do local p = rawget(properties,n) if p then - -- local i = rawget(p,"injections") or rawget(p,"preinjections") local i = p.injections or p.preinjections if i then local yoffset = i.yoffset if yoffset and yoffset ~= 0 then - setfield(n,"yoffset",yoffset) + setoffsets(n,false,yoffset) end local leftkern = i.leftkern if leftkern and leftkern ~= 0 then - pre = insert_node_before(pre,n,newkern(leftkern)) + pre = insert_node_before(pre,n,fontkern(leftkern)) done = true end local rightkern = i.rightkern if rightkern and rightkern ~= 0 then - insert_node_after(pre,n,newkern(rightkern)) + insert_node_after(pre,n,fontkern(rightkern)) done = true end end @@ -855,24 +908,23 @@ local function inject_pairs_only(head,where) end if post then -- left|post glyphs|right - for n in traverse_char(post) do + for n in nextchar, post do local p = rawget(properties,n) if p then - -- local i = rawget(p,"injections") or rawget(p,"postinjections") local i = p.injections or p.postinjections if i then local yoffset = i.yoffset if yoffset and yoffset ~= 0 then - setfield(n,"yoffset",yoffset) + setoffsets(n,false,yoffset) end local leftkern = i.leftkern if leftkern and leftkern ~= 0 then - post = insert_node_before(post,n,newkern(leftkern)) + post = insert_node_before(post,n,fontkern(leftkern)) done = true end local rightkern = i.rightkern if rightkern and rightkern ~= 0 then - insert_node_after(post,n,newkern(rightkern)) + insert_node_after(post,n,fontkern(rightkern)) done = true end end @@ -881,24 +933,23 @@ local function inject_pairs_only(head,where) end if replace then -- left|replace glyphs|right - for n in traverse_char(replace) do + for n in nextchar, replace do local p = rawget(properties,n) if p then - -- local i = rawget(p,"injections") or rawget(p,"replaceinjections") local i = p.injections or p.replaceinjections if i then local yoffset = i.yoffset if yoffset and yoffset ~= 0 then - setfield(n,"yoffset",yoffset) + setoffsets(n,false,yoffset) end local leftkern = i.leftkern if leftkern and leftkern ~= 0 then - replace = insert_node_before(replace,n,newkern(leftkern)) + replace = insert_node_before(replace,n,fontkern(leftkern)) done = true end local rightkern = i.rightkern if rightkern and rightkern ~= 0 then - insert_node_after(replace,n,newkern(rightkern)) + insert_node_after(replace,n,fontkern(rightkern)) done = true end end @@ -909,13 +960,12 @@ local function inject_pairs_only(head,where) if pre then local p = rawget(properties,prevglyph) if p then - -- local i = rawget(p,"preinjections") local i = p.preinjections if i then -- glyph|pre glyphs local rightkern = i.rightkern if rightkern and rightkern ~= 0 then - pre = insert_node_before(pre,pre,newkern(rightkern)) + pre = insert_node_before(pre,pre,fontkern(rightkern)) done = true end end @@ -924,13 +974,12 @@ local function inject_pairs_only(head,where) if replace then local p = rawget(properties,prevglyph) if p then - -- local i = rawget(p,"replaceinjections") local i = p.replaceinjections if i then -- glyph|replace glyphs local rightkern = i.rightkern if rightkern and rightkern ~= 0 then - replace = insert_node_before(replace,replace,newkern(rightkern)) + replace = insert_node_before(replace,replace,fontkern(rightkern)) done = true end end @@ -953,43 +1002,22 @@ local function inject_pairs_only(head,where) if keepregisteredcounts then keepregisteredcounts = false else - nofregisteredkerns = 0 + nofregisteredpositions = 0 + end + if trace_injections then + show_result(head) end - return tonode(head), true + return head end --- local function showoffset(n,flag) --- local ox = getfield(n,"xoffset") --- local oy = getfield(n,"yoffset") --- if flag then --- if ox == 0 then --- setcolor(n,oy == 0 and "darkgray" or "darkgreen") --- else --- setcolor(n,oy == 0 and "darkblue" or "darkred") --- end --- else --- if ox == 0 then --- setcolor(n,oy == 0 and "gray" or "green") --- else --- setcolor(n,oy == 0 and "blue" or "red") --- end --- end --- end - local function showoffset(n,flag) - local o = getfield(n,"xoffset") - if o == 0 then - o = getfield(n,"yoffset") - end - if o ~= 0 then - setcolor(n,flag and "darkred" or "darkgreen") - else - resetcolor(n) + local x, y = getoffsets(n) + if x ~= 0 or y ~= 0 then + setcolor(n,"darkgray") end end local function inject_everything(head,where) - head = tonut(head) if trace_injections then trace(head,"everything") end @@ -998,8 +1026,6 @@ local function inject_everything(head,where) -- local current = head local last = nil - local font = font - local markdata = nil local prev = nil local next = nil local prevdisc = nil @@ -1018,262 +1044,333 @@ local function inject_everything(head,where) local marks = { } local nofmarks = 0 -- + -- local applyfix = hascursives and fix_cursive_marks + -- -- move out -- local function processmark(p,n,pn) -- p = basenode - local px = getfield(p,"xoffset") + local px, py = getoffsets(p) + local nx, ny = getoffsets(n) local ox = 0 local rightkern = nil local pp = rawget(properties,p) if pp then - -- pp = rawget(pp,"injections") pp = pp.injections if pp then rightkern = pp.rightkern end end + local markdir = pn.markdir if rightkern then -- x and w ~= 0 - if pn.markdir < 0 then + ox = px - (pn.markx or 0) - rightkern + if markdir and markdir < 0 then -- kern(w-x) glyph(p) kern(x) mark(n) - ox = px - pn.markx - rightkern - -- report_injections("r2l case 1: %p",ox) + if not pn.markmark then + ox = ox + (pn.leftkern or 0) + end 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 -- some day we need something more clever here. -- + -- maybe we need to apply both then + -- if false then - -- a mark with kerning + -- a mark with kerning (maybe husayni needs it ) local leftkern = pp.leftkern if leftkern then - ox = px - pn.markx - leftkern - else - ox = px - pn.markx + ox = ox - leftkern end - else - ox = px - pn.markx end end else - -- if pn.markdir < 0 then - -- ox = px - pn.markx - -- -- report_injections("r2l case 3: %p",ox) - -- else - -- -- ox = px - getfield(p,"width") + pn.markx - ox = px - pn.markx - -- report_injections("l2r case 3: %p",ox) - -- end + ox = px - (pn.markx or 0) + if markdir and markdir < 0 then + if not pn.markmark then + local leftkern = pn.leftkern + if leftkern then + ox = ox + leftkern -- husayni needs it + end + end + end if pn.checkmark then - local wn = getfield(n,"width") -- in arial marks have widths - if wn ~= 0 then + local wn = getwidth(n) -- in arial marks have widths + if wn and wn ~= 0 then wn = wn/2 if trace_injections then report_injections("correcting non zero width mark %C",getchar(n)) end -- -- bad: we should center + -- -- pn.leftkern = -wn -- pn.rightkern = -wn - -- -- we're too late anyway as kerns are already injected so - -- -- we do it the ugly way (no checking if the previous is - -- -- already a kern) .. maybe we should fix the font instead - insert_node_before(n,n,newkern(-wn)) - insert_node_after(n,n,newkern(-wn)) + -- + -- -- we're too late anyway as kerns are already injected so we do it the + -- -- ugly way (no checking if the previous is already a kern) .. maybe we + -- -- should fix the font instead + -- + -- todo: head and check for prev / next kern + -- + insert_node_before(n,n,fontkern(-wn)) + insert_node_after(n,n,fontkern(-wn)) end end end - local oy = getfield(n,"yoffset") + getfield(p,"yoffset") + pn.marky - setfield(n,"xoffset",ox) - setfield(n,"yoffset",oy) + local oy = ny + py + (pn.marky or 0) + if not pn.markmark then + local yoffset = pn.yoffset + if yoffset then + oy = oy + yoffset -- husayni needs it + end + end + setoffsets(n,ox,oy) if trace_marks then showoffset(n,true) end end - -- todo: marks in disc + -- begin of temp fix -- + -- local base = nil -- bah, some arabic fonts have no mark anchoring + -- end of temp fix -- while current do - local id = getid(current) local next = getnext(current) - if id == glyph_code then - if getsubtype(current) < 256 then - local p = rawget(properties,current) - if p then - -- local i = rawget(p,"injections") - local i = p.injections - if i then - local pm = i.markbasenode - if pm then - nofmarks = nofmarks + 1 - marks[nofmarks] = current - else - local yoffset = i.yoffset - if yoffset and yoffset ~= 0 then - setfield(current,"yoffset",yoffset) - end - if hascursives then - local cursivex = i.cursivex - if cursivex then - if cursiveanchor then - if cursivex ~= 0 then - i.leftkern = (i.leftkern or 0) + cursivex - end - if maxc == 0 then - minc = 1 - maxc = 1 - glyphs[1] = cursiveanchor - else - maxc = maxc + 1 - glyphs[maxc] = cursiveanchor - end - properties[cursiveanchor].cursivedy = i.cursivey -- cursiveprops - last = current + local char, id = ischar(current) + if char then + local p = rawget(properties,current) + -- begin of temp fix -- + -- if applyfix then + -- if not p then + -- local m = fontmarks[getfont(current)] + -- if m and m[char] then + -- if base then + -- p = { injections = { markbasenode = base } } + -- nofmarks = nofmarks + 1 + -- marks[nofmarks] = current + -- properties[current] = p + -- hasmarks = true + -- end + -- else + -- base = current + -- end + -- end + -- end + -- end of temp fix + if p then + local i = p.injections + -- begin of temp fix -- + -- if applyfix then + -- if not i then + -- local m = fontmarks[getfont(current)] + -- if m and m[char] then + -- if base then + -- i = { markbasenode = base } + -- nofmarks = nofmarks + 1 + -- marks[nofmarks] = current + -- p.injections = i + -- hasmarks = true + -- end + -- else + -- base = current + -- end + -- end + -- end + -- end of temp fix -- + if i then + local pm = i.markbasenode + -- begin of temp fix -- + -- if applyfix then + -- if not pm then + -- local m = fontmarks[getfont(current)] + -- if m and m[char] then + -- if base then + -- pm = base + -- i.markbasenode = pm + -- hasmarks = true + -- end + -- else + -- base = current + -- end + -- else + -- base = current + -- end + -- end + -- end of temp fix -- + if pm then + nofmarks = nofmarks + 1 + marks[nofmarks] = current + else + local yoffset = i.yoffset + if yoffset and yoffset ~= 0 then + setoffsets(current,false,yoffset) + end + if hascursives then + local cursivex = i.cursivex + if cursivex then + if cursiveanchor then + if cursivex ~= 0 then + i.leftkern = (i.leftkern or 0) + cursivex + end + if maxc == 0 then + minc = 1 + maxc = 1 + glyphs[1] = cursiveanchor else - maxc = 0 + maxc = maxc + 1 + glyphs[maxc] = cursiveanchor end - elseif maxc > 0 then - local ny = getfield(current,"yoffset") + properties[cursiveanchor].cursivedy = i.cursivey -- cursiveprops + last = current + else + maxc = 0 + end + elseif maxc > 0 then + local nx, ny = getoffsets(current) + for i=maxc,minc,-1 do + local ti = glyphs[i] + ny = ny + properties[ti].cursivedy + setoffsets(ti,false,ny) -- why not add ? + if trace_cursive then + showoffset(ti) + end + end + maxc = 0 + cursiveanchor = nil + end + if i.cursiveanchor then + cursiveanchor = current -- no need for both now + else + if maxc > 0 then + local nx, ny = getoffsets(current) for i=maxc,minc,-1 do local ti = glyphs[i] ny = ny + properties[ti].cursivedy - setfield(ti,"yoffset",ny) -- why not add ? + setoffsets(ti,false,ny) -- why not add ? if trace_cursive then showoffset(ti) end end maxc = 0 - cursiveanchor = nil - end - if i.cursiveanchor then - cursiveanchor = current -- no need for both now - else - if maxc > 0 then - local ny = getfield(current,"yoffset") - for i=maxc,minc,-1 do - local ti = glyphs[i] - ny = ny + properties[ti].cursivedy - setfield(ti,"yoffset",ny) -- why not add ? - if trace_cursive then - showoffset(ti) - end - end - maxc = 0 - end - cursiveanchor = nil end + cursiveanchor = nil end - -- left|glyph|right - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - insert_node_before(head,current,newkern(leftkern)) - end - local rightkern = i.rightkern - if rightkern and rightkern ~= 0 then - insert_node_after(head,current,newkern(rightkern)) + end + -- left|glyph|right + local leftkern = i.leftkern + local rightkern = i.rightkern + if leftkern and leftkern ~= 0 then + if rightkern and leftkern == -rightkern then + setoffsets(current,leftkern,false) + rightkern = 0 + else + head = insert_node_before(head,current,fontkern(leftkern)) end end - else - -- local i = rawget(p,"emptyinjections") - local i = p.emptyinjections - if i then - -- glyph|disc|glyph (special case) - -- okay? - local rightkern = i.rightkern - if rightkern and rightkern ~= 0 then - if next and getid(next) == disc_code then - if replace then - -- error, we expect an empty one - else - setfield(next,"replace",newkern(rightkern)) -- maybe also leftkern - end + if rightkern and rightkern ~= 0 then + insert_node_after(head,current,fontkern(rightkern)) + end + end + else + local i = p.emptyinjections + if i then + -- glyph|disc|glyph (special case) + local rightkern = i.rightkern + if rightkern and rightkern ~= 0 then + if next and getid(next) == disc_code then + if replace then + -- error, we expect an empty one + else + setfield(next,"replace",fontkern(rightkern)) -- maybe also leftkern end end end end - if prevdisc then - if p then - local done = false - if post then - -- local i = rawget(p,"postinjections") - local i = p.postinjections - if i then - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - insert_node_after(post,posttail,newkern(leftkern)) - done = true - end + end + if prevdisc then + if p then + local done = false + if post then + local i = p.postinjections + if i then + local leftkern = i.leftkern + if leftkern and leftkern ~= 0 then + setlink(posttail,fontkern(leftkern)) + done = true end end - if replace then - -- local i = rawget(p,"replaceinjections") - local i = p.replaceinjections - if i then - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - insert_node_after(replace,replacetail,newkern(leftkern)) - done = true - end - end - else - -- local i = rawget(p,"emptyinjections") - local i = p.emptyinjections - if i then - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - setfield(prev,"replace",newkern(leftkern)) -- maybe also leftkern - end + end + if replace then + local i = p.replaceinjections + if i then + local leftkern = i.leftkern + if leftkern and leftkern ~= 0 then + setlink(replacetail,fontkern(leftkern)) + done = true end end - if done then - setdisc(prevdisc,pre,post,replace) + else + local i = p.emptyinjections + if i then + local leftkern = i.leftkern + if leftkern and leftkern ~= 0 then + setfield(prev,"replace",fontkern(leftkern)) -- maybe also leftkern + end end end - end - else - -- cursive - if hascursives and maxc > 0 then - local ny = getfield(current,"yoffset") - for i=maxc,minc,-1 do - local ti = glyphs[i] - ny = ny + properties[ti].cursivedy - setfield(ti,"yoffset",getfield(ti,"yoffset") + ny) -- can be mark + if done then + setdisc(prevdisc,pre,post,replace) end - maxc = 0 - cursiveanchor = nil end end + else + -- cursive + if hascursives and maxc > 0 then + local nx, ny = getoffsets(current) + for i=maxc,minc,-1 do + local ti = glyphs[i] + ny = ny + properties[ti].cursivedy + local xi, yi = getoffsets(ti) + setoffsets(ti,xi,yi + ny) -- can be mark, we could use properties + end + maxc = 0 + cursiveanchor = nil + end end prevdisc = nil prevglyph = current + elseif char == false then + -- base = nil + prevdisc = nil + prevglyph = current elseif id == disc_code then + -- base = nil pre, post, replace, pretail, posttail, replacetail = getdisc(current,true) local done = false if pre then -- left|pre glyphs|right - for n in traverse_char(pre) do + for n in nextchar, pre do local p = rawget(properties,n) if p then - -- local i = rawget(p,"injections") or rawget(p,"preinjections") local i = p.injections or p.preinjections if i then local yoffset = i.yoffset if yoffset and yoffset ~= 0 then - setfield(n,"yoffset",yoffset) + setoffsets(n,false,yoffset) end local leftkern = i.leftkern if leftkern and leftkern ~= 0 then - pre = insert_node_before(pre,n,newkern(leftkern)) + pre = insert_node_before(pre,n,fontkern(leftkern)) done = true end local rightkern = i.rightkern if rightkern and rightkern ~= 0 then - insert_node_after(pre,n,newkern(rightkern)) + insert_node_after(pre,n,fontkern(rightkern)) done = true end if hasmarks then local pm = i.markbasenode if pm then - processmark(pm,current,i) + processmark(pm,n,i) end end end @@ -1282,30 +1379,29 @@ local function inject_everything(head,where) end if post then -- left|post glyphs|right - for n in traverse_char(post) do + for n in nextchar, post do local p = rawget(properties,n) if p then - -- local i = rawget(p,"injections") or rawget(p,"postinjections") local i = p.injections or p.postinjections if i then local yoffset = i.yoffset if yoffset and yoffset ~= 0 then - setfield(n,"yoffset",yoffset) + setoffsets(n,false,yoffset) end local leftkern = i.leftkern if leftkern and leftkern ~= 0 then - post = insert_node_before(post,n,newkern(leftkern)) + post = insert_node_before(post,n,fontkern(leftkern)) done = true end local rightkern = i.rightkern if rightkern and rightkern ~= 0 then - insert_node_after(post,n,newkern(rightkern)) + insert_node_after(post,n,fontkern(rightkern)) done = true end if hasmarks then local pm = i.markbasenode if pm then - processmark(pm,current,i) + processmark(pm,n,i) end end end @@ -1314,30 +1410,29 @@ local function inject_everything(head,where) end if replace then -- left|replace glyphs|right - for n in traverse_char(replace) do + for n in nextchar, replace do local p = rawget(properties,n) if p then - -- local i = rawget(p,"injections") or rawget(p,"replaceinjections") local i = p.injections or p.replaceinjections if i then local yoffset = i.yoffset if yoffset and yoffset ~= 0 then - setfield(n,"yoffset",yoffset) + setoffsets(n,false,yoffset) end local leftkern = i.leftkern if leftkern and leftkern ~= 0 then - replace = insert_node_before(replace,n,newkern(leftkern)) + replace = insert_node_before(replace,n,fontkern(leftkern)) done = true end local rightkern = i.rightkern if rightkern and rightkern ~= 0 then - insert_node_after(replace,n,newkern(rightkern)) + insert_node_after(replace,n,fontkern(rightkern)) done = true end if hasmarks then local pm = i.markbasenode if pm then - processmark(pm,current,i) + processmark(pm,n,i) end end end @@ -1348,13 +1443,12 @@ local function inject_everything(head,where) if pre then local p = rawget(properties,prevglyph) if p then - -- local i = rawget(p,"preinjections") local i = p.preinjections if i then -- glyph|pre glyphs local rightkern = i.rightkern if rightkern and rightkern ~= 0 then - pre = insert_node_before(pre,pre,newkern(rightkern)) + pre = insert_node_before(pre,pre,fontkern(rightkern)) done = true end end @@ -1363,13 +1457,12 @@ local function inject_everything(head,where) if replace then local p = rawget(properties,prevglyph) if p then - -- local i = rawget(p,"replaceinjections") local i = p.replaceinjections if i then -- glyph|replace glyphs local rightkern = i.rightkern if rightkern and rightkern ~= 0 then - replace = insert_node_before(replace,replace,newkern(rightkern)) + replace = insert_node_before(replace,replace,fontkern(rightkern)) done = true end end @@ -1382,6 +1475,7 @@ local function inject_everything(head,where) prevglyph = nil prevdisc = current else + -- base = nil prevglyph = nil prevdisc = nil end @@ -1390,11 +1484,11 @@ local function inject_everything(head,where) end -- cursive if hascursives and maxc > 0 then - local ny = getfield(last,"yoffset") + local nx, ny = getoffsets(last) for i=maxc,minc,-1 do local ti = glyphs[i] ny = ny + properties[ti].cursivedy - setfield(ti,"yoffset",ny) -- why not add ? + setoffsets(ti,false,ny) -- why not add ? if trace_cursive then showoffset(ti) end @@ -1405,7 +1499,6 @@ local function inject_everything(head,where) for i=1,nofmarks do local m = marks[i] local p = rawget(properties,m) - -- local i = rawget(p,"injections") local i = p.injections local b = i.markbasenode processmark(b,m,i) @@ -1417,12 +1510,15 @@ local function inject_everything(head,where) if keepregisteredcounts then keepregisteredcounts = false else - nofregisteredkerns = 0 - nofregisteredpairs = 0 - nofregisteredmarks = 0 - nofregisteredcursives = 0 + nofregisteredkerns = 0 + nofregisteredpositions = 0 + nofregisteredmarks = 0 + nofregisteredcursives = 0 end - return tonode(head), true + if trace_injections then + show_result(head) + end + return head end -- space triggers @@ -1470,21 +1566,49 @@ end injections.getthreshold = getthreshold -function injections.isspace(n,threshold) - if getid(n) == glue_code then - local w = getfield(n,"width") +function injections.isspace(n,threshold,id) + if (id or getid(n)) == glue_code then + local w = getwidth(n) if threshold and w > threshold then -- was >= return 32 end end end +-- We have a plugin so that Kai can use the next in plain. Such a plugin is rather application +-- specific. +-- +-- local getboth = nodes.direct.getboth +-- local getid = nodes.direct.getid +-- local getprev = nodes.direct.getprev +-- local getnext = nodes.direct.getnext +-- +-- local whatsit_code = nodes.nodecodes.whatsit +-- local glyph_code = nodes.nodecodes.glyph +-- +-- local function getspaceboth(n) -- fragile: what it prev/next has no width field +-- local prev, next = getboth(n) +-- while prev and (getid(prev) == whatsit_code or (getwidth(prev) == 0 and getid(prev) ~= glyph_code)) do +-- prev = getprev(prev) +-- end +-- while next and (getid(next) == whatsit_code or (getwidth(next) == 0 and getid(next) ~= glyph_code)) do +-- next = getnext(next) +-- end +-- end +-- +-- injections.installgetspaceboth(getspaceboth) + +local getspaceboth = getboth + +function injections.installgetspaceboth(gb) + getspaceboth = gb or getboth +end + local function injectspaces(head) if not triggers then - return head, false + return head end - local lastfont = nil local spacekerns = nil local leftkerns = nil @@ -1502,10 +1626,10 @@ local function injectspaces(head) factor = getthreshold(font) end - for n in traverse_id(glue_code,tonut(head)) do - local prev, next = getboth(n) - local prevchar = ischar(prev) - local nextchar = ischar(next) + for n in nextglue, head do + local prev, next = getspaceboth(n) + local prevchar = prev and ischar(prev) + local nextchar = next and ischar(next) if nextchar then local font = getfont(next) local trig = triggers[font] @@ -1531,39 +1655,66 @@ local function injectspaces(head) end end if leftkern then - local old = getfield(n,"width") + local old = getwidth(n) if old > threshold then if rightkern then - local new = old + (leftkern + rightkern) * factor - if trace_spaces then - report_spaces("%C [%p -> %p] %C",prevchar,old,new,nextchar) + if useitalickerns then + local lnew = leftkern * factor + local rnew = rightkern * factor + if trace_spaces then + report_spaces("%C [%p + %p + %p] %C",prevchar,lnew,old,rnew,nextchar) + end + head = insert_node_before(head,n,italickern(lnew)) + insert_node_after(head,n,italickern(rnew)) + else + local new = old + (leftkern + rightkern) * factor + if trace_spaces then + report_spaces("%C [%p -> %p] %C",prevchar,old,new,nextchar) + end + setwidth(n,new) end - setfield(n,"width",new) - leftkern = false + rightkern = false else - local new = old + leftkern * factor - if trace_spaces then - report_spaces("%C [%p -> %p]",prevchar,old,new) + if useitalickerns then + local new = leftkern * factor + if trace_spaces then + report_spaces("%C [%p + %p]",prevchar,old,new) + end + insert_node_after(head,n,italickern(new)) -- tricky with traverse but ok + else + local new = old + leftkern * factor + if trace_spaces then + report_spaces("%C [%p -> %p]",prevchar,old,new) + end + setwidth(n,new) end - setfield(n,"width",new) end end leftkern = false elseif rightkern then - local old = getfield(n,"width") + local old = getwidth(n) if old > threshold then - local new = old + rightkern * factor - if trace_spaces then - report_spaces("[%p -> %p] %C",nextchar,old,new) + if useitalickerns then + local new = rightkern * factor + if trace_spaces then + report_spaces("%C [%p + %p]",nextchar,old,new) + end + insert_node_after(head,n,italickern(new)) + else + local new = old + rightkern * factor + if trace_spaces then + report_spaces("[%p -> %p] %C",nextchar,old,new) + end + setwidth(n,new) end - setfield(n,"width",new) end rightkern = false end end triggers = false - return head, true + + return head end -- @@ -1578,17 +1729,17 @@ function injections.handler(head,where) report_injections("injection variant %a","everything") end return inject_everything(head,where) - elseif nofregisteredpairs > 0 then + elseif nofregisteredpositions > 0 then if trace_injections then - report_injections("injection variant %a","pairs") + report_injections("injection variant %a","positions") end - return inject_pairs_only(head,where) + return inject_positions_only(head,where) elseif nofregisteredkerns > 0 then if trace_injections then report_injections("injection variant %a","kerns") end return inject_kerns_only(head,where) else - return head, false + return head end end |