summaryrefslogtreecommitdiff
path: root/tex/context/base/font-otn.lua
diff options
context:
space:
mode:
authorContext Git Mirror Bot <phg42.2a@gmail.com>2014-12-03 19:15:05 +0100
committerContext Git Mirror Bot <phg42.2a@gmail.com>2014-12-03 19:15:05 +0100
commit606f30879286f37c0cf0ef42bc225e835d0d596d (patch)
tree969577a4f86a2d1e9c085bda80812ebb45c074cb /tex/context/base/font-otn.lua
parent8fa06810ed0fdc14d3c45eefff9a41800a84150b (diff)
downloadcontext-606f30879286f37c0cf0ef42bc225e835d0d596d.tar.gz
2014-12-03 18:28:00
Diffstat (limited to 'tex/context/base/font-otn.lua')
-rw-r--r--tex/context/base/font-otn.lua568
1 files changed, 417 insertions, 151 deletions
diff --git a/tex/context/base/font-otn.lua b/tex/context/base/font-otn.lua
index 32dc820d3..e23a1366c 100644
--- a/tex/context/base/font-otn.lua
+++ b/tex/context/base/font-otn.lua
@@ -129,16 +129,14 @@ results in different tables.</p>
-- Todo: make plugin feature that operates on char/glyphnode arrays
-local concat, insert, remove = table.concat, table.insert, table.remove
-local gmatch, gsub, find, match, lower, strip = string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip
-local type, next, tonumber, tostring = type, next, tonumber, tostring
-local lpegmatch = lpeg.match
+local type, next, tonumber = type, next, tonumber
local random = math.random
local formatters = string.formatters
local logs, trackers, nodes, attributes = logs, trackers, nodes, attributes
-local registertracker = trackers.register
+local registertracker = trackers.register
+local registerdirective = directives.register
local fonts = fonts
local otf = fonts.handlers.otf
@@ -160,6 +158,11 @@ local trace_steps = false registertracker("otf.steps", function(v
local trace_skips = false registertracker("otf.skips", function(v) trace_skips = v end)
local trace_directions = false registertracker("otf.directions", function(v) trace_directions = v end)
+local kernruns = true registerdirective("otf.kernruns", function(v) kernruns = v end)
+local discruns = true registerdirective("otf.discruns", function(v) discruns = v end)
+local compruns = true registerdirective("otf.compruns", function(v) compruns = v end)
+local zwnjruns = true registerdirective("otf.zwnjruns", function(v) zwnjruns = v end)
+
local report_direct = logs.reporter("fonts","otf direct")
local report_subchain = logs.reporter("fonts","otf subchain")
local report_chain = logs.reporter("fonts","otf chain")
@@ -194,12 +197,14 @@ local getfont = nuts.getfont
local getsubtype = nuts.getsubtype
local getchar = nuts.getchar
+local insert_node_before = nuts.insert_before
local insert_node_after = nuts.insert_after
local delete_node = nuts.delete
local copy_node = nuts.copy
local find_node_tail = nuts.tail
local flush_node_list = nuts.flush_list
local end_of_math = nuts.end_of_math
+local traverse_nodes = nuts.traverse
local setmetatableindex = table.setmetatableindex
@@ -416,9 +421,36 @@ local function getcomponentindex(start)
end
end
--- eventually we will do positioning in an other way (needs addional w/h/d fields)
+local a_noligature = attributes.private("noligature")
+local prehyphenchar = languages and languages.prehyphenchar
+local posthyphenchar = languages and languages.posthyphenchar
+
+if not prehyphenchar then
+
+ local newlang = lang.new
+ local getpre = lang.prehyphenchar
+ local getpost = lang.posthyphenchar
+
+ prehyphenchar = function(l) local l = newlang(l) return l and getpre (l) or -1 end
+ posthyphenchar = function(l) local l = newlang(l) return l and getpost(l) or -1 end
+
+end
local function toligature(kind,lookupname,head,start,stop,char,markflag,discfound) -- brr head
+
+ -- not here:
+
+ -- for n in nuts.traverse(glyph_code,start) do
+ -- if getid(n) == glyph_code and getchar(n) == zwnj then
+ -- return head, start
+ -- end
+ -- if n == stop then break end
+ -- end
+
+ if getattr(start,a_noligature) == 1 then
+ -- so we can do: e\noligature{ff}e e\noligature{f}fie (we only look at the first)
+ return head, start
+ end
if start == stop and getchar(start) == char then
resetinjection(start)
setfield(start,"char",char)
@@ -426,6 +458,7 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
end
local prev = getprev(start)
local next = getnext(stop)
+ local comp = start
setfield(start,"prev",nil)
setfield(stop,"next",nil)
local base = copy_glyph(start)
@@ -435,7 +468,7 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
resetinjection(base)
setfield(base,"char",char)
setfield(base,"subtype",ligature_code)
- setfield(base,"components",start) -- start can have components
+ setfield(base,"components",comp) -- start can have components .. do we need to flush?
if prev then
setfield(prev,"next",base)
end
@@ -483,6 +516,56 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
end
start = getnext(start)
end
+ elseif not kernruns or not discruns or not compruns then
+ -- disabled
+ elseif getsubtype(discfound) == discretionary_code then
+ -- maybe some day
+ else
+ -- forget about marks .. probably no scripts that hyphenate and have marks
+ -- todo: check for special disc nodes (with pre's and so)
+ -- todo: use insert_before
+ local prev = getfield(discfound,"prev")
+ local next = getfield(discfound,"next")
+ if prev and next then
+ setfield(next,"prev",nil)
+ setfield(prev,"next",nil)
+ local l = getfield(comp,"lang")
+ local p = prehyphenchar(l)
+ if p and p > 0 then
+ local c = copy_node(comp)
+ local t = find_node_tail(comp)
+ setfield(c,"char",p)
+ comp = insert_node_after(comp,t,c)
+ end
+ local p = posthyphenchar(l)
+ if p and p > 0 then
+ local c = copy_node(next)
+ setfield(c,"char",p)
+ next = insert_node_before(next,next,c)
+ end
+ setfield(discfound,"pre",comp)
+ setfield(discfound,"post",next)
+ --
+ local prev = getfield(base,"prev")
+ local next = getfield(base,"next")
+ --
+ -- remove_node(prev,prev)
+ -- insert_node_after(prev,prev,discfound)
+ --
+ setfield(prev,"next",discfound)
+ setfield(next,"prev",discfound)
+ setfield(discfound,"next",next)
+ setfield(discfound,"prev",prev)
+ --
+ setfield(base,"next",nil)
+ setfield(base,"prev",nil)
+ setfield(base,"components",nil)
+ setfield(discfound,"replace",base)
+ setfield(discfound,"subtype",discretionary_code)
+ base = next
+ else
+ -- weird disc .. maybe some day
+ end
end
return head, base
end
@@ -587,7 +670,7 @@ function handlers.gsub_multiple(head,start,kind,lookupname,multiple,sequence)
end
function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
- local s, stop, discfound = getnext(start), nil, false
+ local s, stop = getnext(start), nil
local startchar = getchar(start)
if marks[startchar] then
while s do
@@ -615,25 +698,26 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
else
head, start = markstoligature(kind,lookupname,head,start,stop,lig)
end
- return head, start, true
+ return head, start, true, false
else
-- ok, goto next lookup
end
end
else
- local skipmark = sequence.flags[1]
+ local skipmark = sequence.flags[1]
+ local discfound = false
while s do
local id = getid(s)
- if id == glyph_code and getsubtype(s)<256 then
- if getfont(s) == currentfont then
+ if id == glyph_code and getsubtype(s)<256 then -- not needed
+ if getfont(s) == currentfont then -- also not needed only when mark
local char = getchar(s)
if skipmark and marks[char] then
s = getnext(s)
else
- local lg = ligature[char]
+ local lg = ligature[char] -- can there be multiple in a row? maybe in a bad font
if lg then
- stop = s
ligature = lg
+ stop = s
s = getnext(s)
else
break
@@ -643,7 +727,8 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
break
end
elseif id == disc_code then
- discfound = true
+ discfound = s
+ stop = s
s = getnext(s)
else
break
@@ -667,12 +752,12 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(kind,lookupname),gref(startchar),gref(lig))
end
end
- return head, start, true
+ return head, start, true, discfound
else
-- weird but happens
end
end
- return head, start, false
+ return head, start, false, discfound
end
--[[ldx--
@@ -920,16 +1005,16 @@ function handlers.gpos_cursive(head,start,kind,lookupname,exitanchors,sequence)
end
end
-function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence)
+function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence,injection)
local startchar = getchar(start)
- local dx, dy, w, h = setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,characters[startchar])
+ local dx, dy, w, h = setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,injection) -- ,characters[startchar])
if trace_kerns then
logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),dx,dy,w,h)
end
return head, start, false
end
-function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence)
+function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence,lookuphash,i,injection)
-- todo: kerns in disc nodes: pre, post, replace -> loop over disc too
-- todo: kerns in components of ligatures
local snext = getnext(start)
@@ -953,14 +1038,14 @@ function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence)
local a, b = krn[2], krn[3]
if a and #a > 0 then
local startchar = getchar(start)
- local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,characters[startchar])
+ local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,injection) -- characters[startchar])
if trace_kerns then
logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
end
end
if b and #b > 0 then
local startchar = getchar(start)
- local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar])
+ local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,injection) -- characters[nextchar])
if trace_kerns then
logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
end
@@ -980,7 +1065,7 @@ function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence)
end
done = true
elseif krn ~= 0 then
- local k = setkern(snext,factor,rlmode,krn)
+ local k = setkern(snext,factor,rlmode,krn,injection)
if trace_kerns then
logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar))
end
@@ -1107,7 +1192,7 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo
local current = start
local subtables = currentlookup.subtables
if #subtables > 1 then
- logwarning("todo: check if we need to loop over the replacements: %s",concat(subtables," "))
+ logwarning("todo: check if we need to loop over the replacements: % t",subtables)
end
while current do
if getid(current) == glyph_code then
@@ -1263,8 +1348,12 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
while s do
local id = getid(s)
if id == disc_code then
+ discfound = s
+if s == stop then
+ break -- okay?
+else
s = getnext(s)
- discfound = true
+end
else
local schar = getchar(s)
if skipmark and marks[schar] then -- marks
@@ -1297,7 +1386,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
end
end
head, start = toligature(kind,lookupname,head,start,stop,l2,currentlookup.flags[1],discfound)
- return head, start, true, nofreplacements
+ return head, start, true, nofreplacements, discfound
elseif trace_bugs then
if start == stop then
logwarning("%s: replacing character %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar))
@@ -1307,7 +1396,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
end
end
end
- return head, start, false, 0
+ return head, start, false, 0, false
end
chainmores.gsub_ligature = chainprocs.gsub_ligature
@@ -1579,7 +1668,7 @@ function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lo
if kerns then
kerns = kerns[startchar] -- needed ?
if kerns then
- local dx, dy, w, h = setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,characters[startchar])
+ local dx, dy, w, h = setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns) -- ,characters[startchar])
if trace_kerns then
logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),dx,dy,w,h)
end
@@ -1619,14 +1708,14 @@ function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,look
local a, b = krn[2], krn[3]
if a and #a > 0 then
local startchar = getchar(start)
- local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,characters[startchar])
+ local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a) -- ,characters[startchar])
if trace_kerns then
logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
end
end
if b and #b > 0 then
local startchar = getchar(start)
- local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar])
+ local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b) -- ,characters[nextchar])
if trace_kerns then
logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
end
@@ -1680,11 +1769,11 @@ local function show_skip(kind,chainname,char,ck,class)
end
end
-local quit_on_no_replacement = true
+local quit_on_no_replacement = true -- maybe per font
+local quit_on_discretionary = false -- only for experiments
-directives.register("otf.chain.quitonnoreplacement",function(value) -- maybe per font
- quit_on_no_replacement = value
-end)
+registerdirective("otf.chain.quitonnoreplacement",function(value) quit_on_no_replacement = value end)
+registerdirective("otf.chain.quitondiscretionary",function(value) quit_on_discretionary = value end)
local function normal_handle_contextchain(head,start,kind,chainname,contexts,sequence,lookuphash)
-- local rule, lookuptype, sequence, f, l, lookups = ck[1], ck[2] ,ck[3], ck[4], ck[5], ck[6]
@@ -1755,7 +1844,12 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
break
end
elseif id == disc_code then
- last = getnext(last)
+ if quit_on_discretionary then
+ match = false
+ break
+ else
+ last = getnext(last)
+ end
else
match = false
break
@@ -1801,7 +1895,12 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
break
end
elseif id == disc_code then
- -- skip 'm
+ if quit_on_discretionary then
+ match = false
+ break
+ else
+ -- skip 'm
+ end
elseif seq[n][32] then
n = n -1
else
@@ -1810,7 +1909,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
prev = getprev(prev)
elseif seq[n][32] then -- somewhat special, as zapfino can have many preceding spaces
- n = n -1
+ n = n - 1
else
match = false
break
@@ -1862,7 +1961,12 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
break
end
elseif id == disc_code then
- -- skip 'm
+ if quit_on_discretionary then
+ match = false
+ break
+ else
+ -- skip 'm
+ end
elseif seq[n][32] then -- brrr
n = n + 1
else
@@ -2149,6 +2253,124 @@ end
-- -- the action
-- end
+-- assumptions:
+--
+-- * languages that use complex disc nodes
+
+-- optimization comes later ...
+
+local function kernrun(disc,run) -- we can assume that prev and next are glyphs
+ if kernruns then
+ --
+ local prev = getprev(disc) -- todo, keep these in the main loop
+ local next = getnext(disc) -- todo, keep these in the main loop
+ --
+ local pre = getfield(disc,"pre")
+ if not pre then
+ -- go on
+ elseif prev then
+ setfield(pre,"prev",prev)
+ setfield(prev,"next",pre)
+ run(prev,"preinjections")
+ setfield(pre,"prev",nil)
+ setfield(prev,"next",disc)
+ else
+ run(pre,"preinjections")
+ end
+ --
+ local post = getfield(disc,"post")
+ if not post then
+ -- go on
+ elseif next then
+ local tail = find_node_tail(post)
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
+ run(post,"postinjections",tail)
+ setfield(tail,"next",nil)
+ setfield(next,"prev",disc)
+ else
+ run(post,"postinjections")
+ end
+ --
+ local replace = getfield(disc,"replace")
+ if not replace then
+ -- this should be already done by discfound
+ elseif prev and next then
+ local tail = find_node_tail(replace)
+ setfield(replace,"prev",prev)
+ setfield(prev,"next",replace)
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
+ run(prev,"replaceinjections",tail)
+ setfield(replace,"prev",nil)
+ setfield(prev,"next",disc)
+ setfield(tail,"next",nil)
+ setfield(next,"prev",disc)
+ elseif prev then
+ setfield(replace,"prev",prev)
+ setfield(prev,"next",replace)
+ run(prev,"replaceinjections")
+ setfield(replace,"prev",nil)
+ setfield(prev,"next",disc)
+ elseif next then
+ local tail = find_node_tail(replace)
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
+ run(replace,"replaceinjections",tail)
+ setfield(tail,"next",nil)
+ setfield(next,"prev",disc)
+ else
+ run(replace,"replaceinjections")
+ end
+ --
+ end
+end
+
+local function comprun(disc,run)
+ if compruns then
+ --
+ local pre = getfield(disc,"pre")
+ if pre then
+ local new = run(pre)
+ if new ~= pre then
+ setfield(disc,"pre",new)
+ end
+ end
+ --
+ local post = getfield(disc,"post")
+ if post then
+ local new = run(post)
+ if new ~= post then
+ setfield(disc,"post",new)
+ end
+ end
+ --
+ local replace = getfield(disc,"replace")
+ if replace then
+ local new = run(replace)
+ if new ~= replace then
+ setfield(disc,"replace",new)
+ end
+ end
+ --
+ end
+end
+
+local function discrun(disc,run)
+ local next = getnext(disc)
+ if discruns and next then
+ local prev = getprev(disc)
+ if prev then
+ setfield(prev,"next",next)
+ -- setfield(next,"prev",prev)
+ run(disc)
+ setfield(prev,"next",disc)
+ -- setfield(next,"prev",disc)
+ end
+ end
+ return next
+end
+
local function featuresprocessor(head,font,attr)
local lookuphash = lookuphashes[font] -- we can also check sequences here
@@ -2193,21 +2415,25 @@ local function featuresprocessor(head,font,attr)
-- todo: retain prev
+ -- We don't goto the next node of a disc node is created so that we can then treat
+ -- the pre, post and replace. It's abit of a hack but works out ok for most cases.
+
for s=1,#datasets do
- local dataset = datasets[s]
- featurevalue = dataset[1] -- todo: pass to function instead of using a global
-
- local sequence = dataset[5] -- sequences[s] -- also dataset[5]
- local rlparmode = 0
- local topstack = 0
- local success = false
- local attribute = dataset[2]
- local chain = dataset[3] -- sequence.chain or 0
- local typ = sequence.type
- local subtables = sequence.subtables
+ local dataset = datasets[s]
+ featurevalue = dataset[1] -- todo: pass to function instead of using a global
+ local attribute = dataset[2]
+ local chain = dataset[3] -- sequence.chain or 0
+ local kind = dataset[4]
+ local sequence = dataset[5] -- sequences[s] -- also dataset[5]
+ local rlparmode = 0
+ local topstack = 0
+ local success = false
+ local typ = sequence.type
+ local gpossing = typ == "gpos_single" or typ == "gpos_pair"
+ local subtables = sequence.subtables
+ local handler = handlers[typ]
if chain < 0 then
-- this is a limited case, no special treatments like 'init' etc
- local handler = handlers[typ]
-- we need to get rid of this slide! probably no longer needed in latest luatex
local start = find_node_tail(head) -- slow (we can store tail because there's always a skip at the end): todo
while start do
@@ -2227,7 +2453,8 @@ local function featuresprocessor(head,font,attr)
if lookupcache then
local lookupmatch = lookupcache[getchar(start)]
if lookupmatch then
- head, start, success = handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
+ -- todo: disc?
+ head, start, success = handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,i)
if success then
break
end
@@ -2248,7 +2475,6 @@ local function featuresprocessor(head,font,attr)
end
end
else
- local handler = handlers[typ]
local ns = #subtables
local start = head -- local ?
rlmode = 0 -- to be checked ?
@@ -2259,8 +2485,7 @@ local function featuresprocessor(head,font,attr)
report_missing_cache(typ,lookupname)
else
- local function subrun(start)
- -- mostly for gsub, gpos would demand a more clever approach
+ local function c_run(start)
local head = start
local done = false
while start do
@@ -2277,7 +2502,7 @@ local function featuresprocessor(head,font,attr)
if lookupmatch then
-- sequence kan weg
local ok
- head, start, ok = handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1)
+ head, start, ok = handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,1)
if ok then
done = true
end
@@ -2292,43 +2517,64 @@ local function featuresprocessor(head,font,attr)
end
if done then
success = true
- return head
end
+ return head
end
- local function kerndisc(disc) -- we can assume that prev and next are glyphs
- local prev = getprev(disc)
- local next = getnext(disc)
- if prev and next then
- setfield(prev,"next",next)
- -- setfield(next,"prev",prev)
- local a = getattr(prev,0)
- if a then
- a = (a == attr) and (not attribute or getprop(prev,a_state) == attribute)
- else
- a = not attribute or getprop(prev,a_state) == attribute
+ local function d_run(prev) -- we can assume that prev and next are glyphs
+ local a = getattr(prev,0)
+ if a then
+ a = (a == attr) and (not attribute or getprop(prev,a_state) == attribute)
+ else
+ a = not attribute or getprop(prev,a_state) == attribute
+ end
+ if a then
+ local lookupmatch = lookupcache[getchar(prev)]
+ if lookupmatch then
+ -- sequence kan weg
+ local h, d, ok = handler(head,prev,kind,lookupname,lookupmatch,sequence,lookuphash,1)
+ if ok then
+ done = true
+ success = true
+ end
end
- if a then
- local lookupmatch = lookupcache[getchar(prev)]
- if lookupmatch then
- -- sequence kan weg
- local h, d, ok = handler(head,prev,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1)
- if ok then
- done = true
- success = true
+ end
+ end
+
+ local function k_run(sub,injection,last)
+ local a = getattr(sub,0)
+ if a then
+ a = (a == attr) and (not attribute or getprop(sub,a_state) == attribute)
+ else
+ a = not attribute or getprop(sub,a_state) == attribute
+ end
+ if a then
+ -- sequence kan weg
+ for n in traverse_nodes(sub) do -- only gpos
+ local id = getid(n)
+ if id == glyph_code then
+ local lookupmatch = lookupcache[getchar(n)]
+ if lookupmatch then
+ local h, d, ok = handler(sub,n,kind,lookupname,lookupmatch,sequence,lookuphash,1,injection)
+ if ok then
+ done = true
+ success = true
+ end
end
+ else
+ -- message
+ end
+ if n == last then
+ break
end
end
- setfield(prev,"next",disc)
- -- setfield(next,"prev",disc)
end
- return next
end
while start do
local id = getid(start)
if id == glyph_code then
- if getfont(start) == font and getsubtype(start) < 256 then
+ if getfont(start) == font and getsubtype(start) < 256 then -- why a 256 test ...
local a = getattr(start,0)
if a then
a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
@@ -2336,14 +2582,19 @@ local function featuresprocessor(head,font,attr)
a = not attribute or getprop(start,a_state) == attribute
end
if a then
- local lookupmatch = lookupcache[getchar(start)]
+ local char = getchar(start)
+ local lookupmatch = lookupcache[char]
if lookupmatch then
-- sequence kan weg
local ok
- head, start, ok = handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1)
+ head, start, ok = handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,1)
if ok then
success = true
+ elseif gpossing and zwnjruns and char == zwnj then
+ discrun(start,d_run)
end
+ elseif gpossing and zwnjruns and char == zwnj then
+ discrun(start,d_run)
end
if start then start = getnext(start) end
else
@@ -2353,25 +2604,15 @@ local function featuresprocessor(head,font,attr)
start = getnext(start)
end
elseif id == disc_code then
- -- mostly for gsub
- if getsubtype(start) == discretionary_code then
- local pre = getfield(start,"pre")
- if pre then
- local new = subrun(pre)
- if new then setfield(start,"pre",new) end
- end
- local post = getfield(start,"post")
- if post then
- local new = subrun(post)
- if new then setfield(start,"post",new) end
- end
- local replace = getfield(start,"replace")
- if replace then
- local new = subrun(replace)
- if new then setfield(start,"replace",new) end
+ local discretionary = getsubtype(start) == discretionary_code
+ if gpossing then
+ if discretionary then
+ kernrun(start,k_run)
+ else
+ discrun(start,d_run)
end
-elseif typ == "gpos_single" or typ == "gpos_pair" then
- kerndisc(start)
+ elseif discretionary then
+ comprun(start,c_run)
end
start = getnext(start)
elseif id == whatsit_code then -- will be function
@@ -2418,10 +2659,10 @@ elseif typ == "gpos_single" or typ == "gpos_pair" then
end
end
end
+
else
- local function subrun(start)
- -- mostly for gsub, gpos would demand a more clever approach
+ local function c_run(start)
local head = start
local done = false
while start do
@@ -2442,7 +2683,7 @@ elseif typ == "gpos_single" or typ == "gpos_pair" then
if lookupmatch then
-- we could move all code inline but that makes things even more unreadable
local ok
- head, start, ok = handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
+ head, start, ok = handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,i)
if ok then
done = true
break
@@ -2465,45 +2706,75 @@ elseif typ == "gpos_single" or typ == "gpos_pair" then
end
if done then
success = true
- return head
end
+ return head
end
- local function kerndisc(disc) -- we can assume that prev and next are glyphs
- local prev = getprev(disc)
- local next = getnext(disc)
- if prev and next then
- setfield(prev,"next",next)
- -- setfield(next,"prev",prev)
- local a = getattr(prev,0)
- if a then
- a = (a == attr) and (not attribute or getprop(prev,a_state) == attribute)
- else
- a = not attribute or getprop(prev,a_state) == attribute
+ local function d_run(prev)
+ local a = getattr(prev,0)
+ if a then
+ a = (a == attr) and (not attribute or getprop(prev,a_state) == attribute)
+ else
+ a = not attribute or getprop(prev,a_state) == attribute
+ end
+ if a then
+ local char = getchar(prev)
+ for i=1,ns do
+ local lookupname = subtables[i]
+ local lookupcache = lookuphash[lookupname]
+ if lookupcache then
+ local lookupmatch = lookupcache[char]
+ if lookupmatch then
+ -- we could move all code inline but that makes things even more unreadable
+ local h, d, ok = handler(head,prev,kind,lookupname,lookupmatch,sequence,lookuphash,i)
+ if ok then
+ done = true
+ break
+ end
+ end
+ else
+ report_missing_cache(typ,lookupname)
+ end
end
- if a then
- for i=1,ns do
- local lookupname = subtables[i]
- local lookupcache = lookuphash[lookupname]
- if lookupcache then
- local lookupmatch = lookupcache[getchar(prev)]
- if lookupmatch then
- -- we could move all code inline but that makes things even more unreadable
- local h, d, ok = handler(head,prev,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
- if ok then
- done = true
- break
+ end
+ end
+
+ local function k_run(sub,injection,last)
+ local a = getattr(sub,0)
+ if a then
+ a = (a == attr) and (not attribute or getprop(sub,a_state) == attribute)
+ else
+ a = not attribute or getprop(sub,a_state) == attribute
+ end
+ if a then
+ for n in traverse_nodes(sub) do -- only gpos
+ local id = getid(n)
+ if id == glyph_code then
+ local char = getchar(n)
+ for i=1,ns do
+ local lookupname = subtables[i]
+ local lookupcache = lookuphash[lookupname]
+ if lookupcache then
+ local lookupmatch = lookupcache[char]
+ if lookupmatch then
+ local h, d, ok = handler(head,n,kind,lookupname,lookupmatch,sequence,lookuphash,i,injection)
+ if ok then
+ done = true
+ break
+ end
end
+ else
+ report_missing_cache(typ,lookupname)
end
- else
- report_missing_cache(typ,lookupname)
end
+ else
+ -- message
+ end
+ if n == last then
+ break
end
end
- setfield(prev,"next",disc)
- -- setfield(next,"prev",disc)
end
- return next
end
while start do
@@ -2521,18 +2792,23 @@ elseif typ == "gpos_single" or typ == "gpos_pair" then
local lookupname = subtables[i]
local lookupcache = lookuphash[lookupname]
if lookupcache then
- local lookupmatch = lookupcache[getchar(start)]
+ local char = getchar(start)
+ local lookupmatch = lookupcache[char]
if lookupmatch then
-- we could move all code inline but that makes things even more unreadable
local ok
- head, start, ok = handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
+ head, start, ok = handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,i)
if ok then
success = true
break
elseif not start then
-- don't ask why ... shouldn't happen
break
+ elseif gpossing and zwnjruns and char == zwnj then
+ discrun(start,d_run)
end
+ elseif gpossing and zwnjruns and char == zwnj then
+ discrun(start,d_run)
end
else
report_missing_cache(typ,lookupname)
@@ -2546,25 +2822,15 @@ elseif typ == "gpos_single" or typ == "gpos_pair" then
start = getnext(start)
end
elseif id == disc_code then
- -- mostly for gsub
- if getsubtype(start) == discretionary_code then
- local pre = getfield(start,"pre")
- if pre then
- local new = subrun(pre)
- if new then setfield(start,"pre",new) end
- end
- local post = getfield(start,"post")
- if post then
- local new = subrun(post)
- if new then setfield(start,"post",new) end
- end
- local replace = getfield(start,"replace")
- if replace then
- local new = subrun(replace)
- if new then setfield(start,"replace",new) end
+ local discretionary = getsubtype(start) == discretionary_code
+ if gpossing then
+ if discretionary then
+ kernrun(start,k_run)
+ else
+ discrun(start,d_run)
end
-elseif typ == "gpos_single" or typ == "gpos_pair" then
- kerndisc(start)
+ elseif discretionary then
+ comprun(start,c_run)
end
start = getnext(start)
elseif id == whatsit_code then