summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/font-otj.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkiv/font-otj.lua')
-rw-r--r--tex/context/base/mkiv/font-otj.lua711
1 files changed, 363 insertions, 348 deletions
diff --git a/tex/context/base/mkiv/font-otj.lua b/tex/context/base/mkiv/font-otj.lua
index b65a9db66..634f8a83c 100644
--- a/tex/context/base/mkiv/font-otj.lua
+++ b/tex/context/base/mkiv/font-otj.lua
@@ -16,18 +16,16 @@ 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.
+
if not nodes.properties then return end
-local next, rawget = next, rawget
-local utfchar = utf.char
+local next, rawget, tonumber = next, rawget, tonumber
local fastcopy = table.fastcopy
local registertracker = trackers.register
@@ -35,11 +33,7 @@ local registertracker = trackers.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("otf.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 trace_spaces = false registertracker("fonts.injections.spaces", function(v) trace_spaces = v end)
local report_injections = logs.reporter("fonts","injections")
local report_spaces = logs.reporter("fonts","spaces")
@@ -79,20 +73,23 @@ 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
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 find_tail = nuts.tail
local properties = nodes.properties.data
@@ -137,7 +134,7 @@ end
-- if tp then
-- tp.injections = si
-- else
--- propertydata[target] = {
+-- properties[target] = {
-- injections = si,
-- }
-- end
@@ -169,7 +166,7 @@ function injections.copy(target,source)
if tp then
tp.injections = si
else
- propertydata[target] = {
+ properties[target] = {
injections = si,
}
end
@@ -377,7 +374,8 @@ function injections.setkern(current,factor,rlmode,x,injection)
end
end
-function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk) -- ba=baseanchor, ma=markanchor
+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
@@ -398,6 +396,7 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk) -- ba=b
i.markbase = nofregisteredmarks
i.markbasenode = base
i.markmark = mkmk
+ i.checkmark = checkmark
end
else
p.injections = {
@@ -407,6 +406,7 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk) -- ba=b
markbase = nofregisteredmarks,
markbasenode = base,
markmark = mkmk,
+ checkmark = checkmark,
}
end
else
@@ -418,6 +418,7 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk) -- ba=b
markbase = nofregisteredmarks,
markbasenode = base,
markmark = mkmk,
+ checkmark = checkmark,
},
}
end
@@ -523,11 +524,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()
@@ -562,76 +564,65 @@ 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 = rawget(p,"injections")
+ 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,newkern(leftkern))
+ 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
+ setlink(posttail,newkern(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 = rawget(p,"replaceinjections")
+ local i = p.replaceinjections
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ setlink(replacetail,newkern(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 = 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
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
+ 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
@@ -645,13 +636,8 @@ local function inject_kerns_only(head,where)
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,newkern(leftkern))
+ done = true
end
end
end
@@ -667,13 +653,8 @@ local function inject_kerns_only(head,where)
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,newkern(leftkern))
+ done = true
end
end
end
@@ -689,13 +670,8 @@ local function inject_kerns_only(head,where)
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,newkern(leftkern))
+ done = true
end
end
end
@@ -739,87 +715,88 @@ 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
+ local char, id = ischar(current)
+ if char 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
+ setoffsets(current,false,yoffset)
+ end
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ head = 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
+ else
+ -- local i = rawget(p,"emptyinjections")
+ local i = p.emptyinjections
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
- insert_node_before(head,current,newkern(leftkern))
- end
+ -- glyph|disc|glyph (special case)
+-- is this okay?
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",newkern(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 = rawget(p,"postinjections")
+ local i = p.postinjections
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ setlink(posttail,newkern(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 = rawget(p,"replaceinjections")
+ local i = p.replaceinjections
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ setlink(replacetail,newkern(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",newkern(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
@@ -833,7 +810,7 @@ local function inject_pairs_only(head,where)
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
@@ -859,7 +836,7 @@ local function inject_pairs_only(head,where)
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
@@ -885,7 +862,7 @@ local function inject_pairs_only(head,where)
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
@@ -954,30 +931,9 @@ local function inject_pairs_only(head,where)
return tonode(head), true
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
+ local x, y = getoffsets(n)
+ if x ~= 0 or y ~= 0 then
setcolor(n,flag and "darkred" or "darkgreen")
else
resetcolor(n)
@@ -1017,7 +973,8 @@ local function inject_everything(head,where)
-- 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)
@@ -1035,7 +992,7 @@ local function inject_everything(head,where)
-- report_injections("r2l case 1: %p",ox)
else
-- kern(x) glyph(p) kern(w-x) mark(n)
- -- ox = px - getfield(p,"width") + pn.markx - pp.leftkern
+ -- ox = px - getwidth(p) + 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
@@ -1050,7 +1007,7 @@ local function inject_everything(head,where)
ox = px - pn.markx
end
else
- ox = px - pn.markx
+ ox = px - pn.markx - rightkern -- seguiemj needs the rightkern
end
end
else
@@ -1058,178 +1015,191 @@ local function inject_everything(head,where)
-- ox = px - pn.markx
-- -- report_injections("r2l case 3: %p",ox)
-- else
- -- -- ox = px - getfield(p,"width") + pn.markx
+ -- -- ox = px - getwidth(p) + pn.markx
ox = px - pn.markx
-- report_injections("l2r case 3: %p",ox)
-- end
- local wn = getfield(n,"width") -- in arial marks have widths
- if wn ~= 0 then
- -- bad: we should center
- pn.leftkern = -wn/2
- pn.rightkern = -wn/2
+ if pn.checkmark 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
+ -- hm, no head ?
+ insert_node_before(n,n,newkern(-wn))
+ insert_node_after(n,n,newkern(-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
+ setoffsets(n,ox,oy)
if trace_marks then
showoffset(n,true)
end
end
-- todo: marks in disc
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
- 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)
+ 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
+ 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
- end
- -- 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
- 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))
+ cursiveanchor = nil
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
+ -- left|glyph|right
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ head = 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
+ 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
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 = rawget(p,"postinjections")
+ local i = p.postinjections
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ setlink(posttail,newkern(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 = rawget(p,"replaceinjections")
+ local i = p.replaceinjections
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ setlink(replacetail,newkern(leftkern))
+ done = true
end
end
- if done then
- setdisc(prevdisc,pre,post,replace)
+ 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
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
+ prevdisc = nil
+ prevglyph = current
elseif id == disc_code then
pre, post, replace, pretail, posttail, replacetail = getdisc(current,true)
local done = false
@@ -1243,7 +1213,7 @@ local function inject_everything(head,where)
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
@@ -1258,7 +1228,7 @@ local function inject_everything(head,where)
if hasmarks then
local pm = i.markbasenode
if pm then
- processmark(pm,current,i)
+ processmark(pm,n,i)
end
end
end
@@ -1275,7 +1245,7 @@ local function inject_everything(head,where)
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
@@ -1290,7 +1260,7 @@ local function inject_everything(head,where)
if hasmarks then
local pm = i.markbasenode
if pm then
- processmark(pm,current,i)
+ processmark(pm,n,i)
end
end
end
@@ -1307,7 +1277,7 @@ local function inject_everything(head,where)
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
@@ -1322,7 +1292,7 @@ local function inject_everything(head,where)
if hasmarks then
local pm = i.markbasenode
if pm then
- processmark(pm,current,i)
+ processmark(pm,n,i)
end
end
end
@@ -1375,11 +1345,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
@@ -1422,6 +1392,48 @@ function nodes.injections.setspacekerns(font,sequence)
end
end
+local getthreshold
+
+if context then
+
+ local threshold = 1 -- todo: add a few methods for context
+ local parameters = fonts.hashes.parameters
+
+ directives.register("otf.threshold", function(v) threshold = tonumber(v) or 1 end)
+
+ getthreshold = function(font)
+ local p = parameters[font]
+ local f = p.factor
+ local s = p.spacing
+ local t = threshold * (s and s.width or p.space or 0) - 2
+ return t > 0 and t or 0, f
+ end
+
+else
+
+ injections.threshold = 0
+
+ getthreshold = function(font)
+ local p = fontdata[font].parameters
+ local f = p.factor
+ local s = p.spacing
+ local t = injections.threshold * (s and s.width or p.space or 0) - 2
+ return t > 0 and t or 0, f
+ end
+
+end
+
+injections.getthreshold = getthreshold
+
+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
+
local function injectspaces(head)
if not triggers then
@@ -1438,18 +1450,11 @@ local function injectspaces(head)
local rightkern = false
local function updatefont(font,trig)
- -- local resources = resources[font]
- -- local spacekerns = resources.spacekerns
- -- if spacekerns then
- -- leftkerns = spacekerns.left
- -- rightkerns = spacekerns.right
- -- end
leftkerns = trig.left
rightkerns = trig.right
- local par = fontdata[font].parameters -- fallback for generic
- factor = par.factor
- threshold = par.spacing.width - 1 -- get rid of rounding errors
lastfont = font
+ threshold,
+ factor = getthreshold(font)
end
for n in traverse_id(glue_code,tonut(head)) do
@@ -1469,7 +1474,7 @@ local function injectspaces(head)
end
end
if prevchar then
- local font = getfont(next)
+ local font = getfont(prev)
local trig = triggers[font]
if trig then
if lastfont ~= font then
@@ -1481,32 +1486,32 @@ local function injectspaces(head)
end
end
if leftkern then
- local old = getfield(n,"width")
- if old >= threshold then
+ 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)
end
- setfield(n,"width",new)
+ setwidth(n,new)
leftkern = false
else
local new = old + leftkern * factor
if trace_spaces then
report_spaces("%C [%p -> %p]",prevchar,old,new)
end
- setfield(n,"width",new)
+ setwidth(n,new)
end
end
leftkern = false
elseif rightkern then
- local old = getfield(n,"width")
- if old >= threshold then
+ 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)
end
- setfield(n,"width",new)
+ setwidth(n,new)
end
rightkern = false
end
@@ -1522,11 +1527,21 @@ function injections.handler(head,where)
if triggers then
head = injectspaces(head)
end
+ -- todo: marks only run too
if nofregisteredmarks > 0 or nofregisteredcursives > 0 then
+ if trace_injections then
+ report_injections("injection variant %a","everything")
+ end
return inject_everything(head,where)
elseif nofregisteredpairs > 0 then
+ if trace_injections then
+ report_injections("injection variant %a","pairs")
+ end
return inject_pairs_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