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.lua566
1 files changed, 361 insertions, 205 deletions
diff --git a/tex/context/base/mkiv/font-otj.lua b/tex/context/base/mkiv/font-otj.lua
index 2c79500e7..1f9fd1ac1 100644
--- a/tex/context/base/mkiv/font-otj.lua
+++ b/tex/context/base/mkiv/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.)
@@ -21,7 +21,13 @@ if not modules then modules = { } end modules ['font-otj'] = {
-- 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
@@ -43,6 +49,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
@@ -62,12 +69,9 @@ 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
@@ -93,65 +97,70 @@ 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 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
-local nofregisteredkerns = 0
-local nofregisteredpairs = 0
-local nofregisteredmarks = 0
-local nofregisteredcursives = 0
-local keepregisteredcounts = false
+ fontkern = function(k)
+ local n = copy_node(thekern)
+ setkern(n,k)
+ return n
+ end
+
+ 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
--- properties[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
@@ -159,7 +168,6 @@ 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)
@@ -185,10 +193,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
@@ -209,7 +216,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
@@ -218,7 +224,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
@@ -236,7 +250,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
@@ -254,7 +267,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
@@ -276,7 +288,9 @@ 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
+-- 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]
local y = factor*spec[2]
local w = factor*spec[3]
@@ -286,7 +300,7 @@ function injections.setpair(current,factor,rlmode,r2lflag,spec,injection) -- r2l
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
@@ -295,8 +309,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
@@ -333,15 +346,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
@@ -352,8 +365,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
@@ -374,8 +386,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
@@ -384,15 +450,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
@@ -438,7 +509,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
@@ -480,7 +551,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 traverse_char(n) do
showchar(n,where)
show(n,what,where," ")
end
@@ -488,8 +559,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)
@@ -537,6 +609,7 @@ local function show_result(head)
end
current = getnext(current)
end
+ report_injections()
end
-- G +D-pre G
@@ -556,7 +629,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
@@ -569,46 +642,42 @@ local function inject_kerns_only(head,where)
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))
+ head = insert_node_before(head,current,fontkern(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))
+ setlink(posttail,fontkern(leftkern))
done = true
end
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))
+ setlink(replacetail,fontkern(leftkern))
done = true
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
+ setfield(prev,"replace",fontkern(leftkern)) -- maybe also leftkern
end
end
end
@@ -618,11 +687,11 @@ local function inject_kerns_only(head,where)
end
end
prevdisc = nil
- prevglyph = current
+ -- prevglyph = current
elseif char == false then
-- other font
prevdisc = nil
- prevglyph = current
+ -- prevglyph = current
elseif id == disc_code then
pre, post, replace, pretail, posttail, replacetail = getdisc(current,true)
local done = false
@@ -631,12 +700,11 @@ local function inject_kerns_only(head,where)
for n in traverse_char(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
- pre = insert_node_before(pre,n,newkern(leftkern))
+ pre = insert_node_before(pre,n,fontkern(leftkern))
done = true
end
end
@@ -648,12 +716,11 @@ local function inject_kerns_only(head,where)
for n in traverse_char(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
- post = insert_node_before(post,n,newkern(leftkern))
+ post = insert_node_before(post,n,fontkern(leftkern))
done = true
end
end
@@ -665,12 +732,11 @@ local function inject_kerns_only(head,where)
for n in traverse_char(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
- replace = insert_node_before(replace,n,newkern(leftkern))
+ replace = insert_node_before(replace,n,fontkern(leftkern))
done = true
end
end
@@ -680,10 +746,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
@@ -695,13 +761,16 @@ local function inject_kerns_only(head,where)
else
nofregisteredkerns = 0
end
+ if trace_injections then
+ show_result(head)
+ end
return tonode(head), true
end
-local function inject_pairs_only(head,where)
+local function inject_positions_only(head,where)
head = tonut(head)
if trace_injections then
- trace(head,"pairs")
+ trace(head,"positions")
end
local current = head
local prev = nil
@@ -720,7 +789,6 @@ local function inject_pairs_only(head,where)
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
@@ -728,27 +796,30 @@ local function inject_pairs_only(head,where)
if yoffset and yoffset ~= 0 then
setoffsets(current,false,yoffset)
end
- local leftkern = i.leftkern
+ local leftkern = i.leftkern
+ local rightkern = i.rightkern
if leftkern and leftkern ~= 0 then
- head = insert_node_before(head,current,newkern(leftkern))
+ if rightkern and leftkern == -rightkern then
+ setoffsets(current,leftkern,false)
+ rightkern = 0
+ else
+ head = insert_node_before(head,current,fontkern(leftkern))
+ end
end
- local rightkern = i.rightkern
if rightkern and rightkern ~= 0 then
- insert_node_after(head,current,newkern(rightkern))
+ insert_node_after(head,current,fontkern(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
+ setfield(next,"replace",fontkern(rightkern)) -- maybe also leftkern
end
end
end
@@ -757,23 +828,21 @@ local function inject_pairs_only(head,where)
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))
+ setlink(posttail,fontkern(leftkern))
done = true
end
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))
+ setlink(replacetail,fontkern(leftkern))
done = true
end
end
@@ -783,7 +852,7 @@ local function inject_pairs_only(head,where)
-- new .. okay?
local leftkern = i.leftkern
if leftkern and leftkern ~= 0 then
- setfield(prev,"replace",newkern(leftkern)) -- maybe also leftkern
+ setfield(prev,"replace",fontkern(leftkern)) -- maybe also leftkern
end
end
end
@@ -805,7 +874,6 @@ local function inject_pairs_only(head,where)
for n in traverse_char(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
@@ -814,12 +882,12 @@ local function inject_pairs_only(head,where)
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
@@ -831,7 +899,6 @@ local function inject_pairs_only(head,where)
for n in traverse_char(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
@@ -840,12 +907,12 @@ local function inject_pairs_only(head,where)
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
@@ -857,7 +924,6 @@ local function inject_pairs_only(head,where)
for n in traverse_char(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
@@ -866,12 +932,12 @@ local function inject_pairs_only(head,where)
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
@@ -882,13 +948,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
@@ -897,13 +962,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
@@ -926,7 +990,10 @@ 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
end
@@ -934,9 +1001,7 @@ end
local function showoffset(n,flag)
local x, y = getoffsets(n)
if x ~= 0 or y ~= 0 then
- setcolor(n,flag and "darkred" or "darkgreen")
- else
- resetcolor(n)
+ setcolor(n,"darkgray")
end
end
@@ -950,8 +1015,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
@@ -979,46 +1042,46 @@ local function inject_everything(head,where)
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 - 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
-- 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 - rightkern -- seguiemj needs the rightkern
end
end
else
- -- if pn.markdir < 0 then
- -- ox = px - pn.markx
- -- -- report_injections("r2l case 3: %p",ox)
- -- else
- -- -- ox = px - getwidth(p) + 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 = getwidth(n) -- in arial marks have widths
if wn and wn ~= 0 then
@@ -1027,34 +1090,99 @@ local function inject_everything(head,where)
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))
+ --
+ -- -- 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 = ny + py + pn.marky
+ 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 next = getnext(current)
local char, id = ischar(current)
if char then
local p = rawget(properties,current)
+ -- begin of temp fix --
+ if hascursives 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 = rawget(p,"injections")
local i = p.injections
+ -- begin of temp fix --
+ if hascursives 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 hascursives 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
@@ -1115,28 +1243,31 @@ local function inject_everything(head,where)
end
end
-- left|glyph|right
- local leftkern = i.leftkern
+ local leftkern = i.leftkern
+ local rightkern = i.rightkern
if leftkern and leftkern ~= 0 then
- head = insert_node_before(head,current,newkern(leftkern))
+ if rightkern and leftkern == -rightkern then
+ setoffsets(current,leftkern,false)
+ rightkern = 0
+ else
+ head = insert_node_before(head,current,fontkern(leftkern))
+ end
end
- local rightkern = i.rightkern
if rightkern and rightkern ~= 0 then
- insert_node_after(head,current,newkern(rightkern))
+ insert_node_after(head,current,fontkern(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
+ setfield(next,"replace",fontkern(rightkern)) -- maybe also leftkern
end
end
end
@@ -1146,33 +1277,30 @@ local function inject_everything(head,where)
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))
+ setlink(posttail,fontkern(leftkern))
done = true
end
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))
+ setlink(replacetail,fontkern(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
+ setfield(prev,"replace",fontkern(leftkern)) -- maybe also leftkern
end
end
end
@@ -1208,7 +1336,6 @@ local function inject_everything(head,where)
for n in traverse_char(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
@@ -1217,12 +1344,12 @@ local function inject_everything(head,where)
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
@@ -1240,7 +1367,6 @@ local function inject_everything(head,where)
for n in traverse_char(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
@@ -1249,12 +1375,12 @@ local function inject_everything(head,where)
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
@@ -1272,7 +1398,6 @@ local function inject_everything(head,where)
for n in traverse_char(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
@@ -1281,12 +1406,12 @@ local function inject_everything(head,where)
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
@@ -1303,13 +1428,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
@@ -1318,13 +1442,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
@@ -1339,6 +1462,7 @@ local function inject_everything(head,where)
else
prevglyph = nil
prevdisc = nil
+base = nil
end
prev = current
current = next
@@ -1360,7 +1484,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)
@@ -1372,10 +1495,13 @@ 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
+ if trace_injections then
+ show_result(head)
end
return tonode(head), true
end
@@ -1468,7 +1594,6 @@ local function injectspaces(head)
if not triggers then
return head, false
end
-
local lastfont = nil
local spacekerns = nil
local leftkerns = nil
@@ -1477,6 +1602,7 @@ local function injectspaces(head)
local threshold = 0
local leftkern = false
local rightkern = false
+ local nuthead = tonut(head)
local function updatefont(font,trig)
leftkerns = trig.left
@@ -1486,7 +1612,7 @@ local function injectspaces(head)
factor = getthreshold(font)
end
- for n in traverse_id(glue_code,tonut(head)) do
+ for n in traverse_id(glue_code,nuthead) do
local prev, next = getspaceboth(n)
local prevchar = prev and ischar(prev)
local nextchar = next and ischar(next)
@@ -1518,29 +1644,59 @@ local function injectspaces(head)
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
+ local h = insert_node_before(nuthead,n,italickern(lnew))
+ if h == nuthead then
+ head = tonode(h)
+ nuthead = h
+ end
+ insert_node_after(nuthead,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
- setwidth(n,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(nuthead,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
- setwidth(n,new)
end
end
leftkern = false
elseif rightkern 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)
+ if useitalickerns then
+ local new = rightkern * factor
+ if trace_spaces then
+ report_spaces("%C [%p + %p]",nextchar,old,new)
+ end
+ insert_node_after(nuthead,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
- setwidth(n,new)
end
rightkern = false
end
@@ -1562,11 +1718,11 @@ 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")