summaryrefslogtreecommitdiff
path: root/tex/context/base/font-ots.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/font-ots.lua')
-rw-r--r--tex/context/base/font-ots.lua790
1 files changed, 453 insertions, 337 deletions
diff --git a/tex/context/base/font-ots.lua b/tex/context/base/font-ots.lua
index 3bb2d326a..dd50a2e62 100644
--- a/tex/context/base/font-ots.lua
+++ b/tex/context/base/font-ots.lua
@@ -196,7 +196,6 @@ local wildcard = "*"
local default = "dflt"
local nodecodes = nodes.nodecodes
-local whatcodes = nodes.whatcodes
local glyphcodes = nodes.glyphcodes
local disccodes = nodes.disccodes
@@ -204,8 +203,8 @@ local glyph_code = nodecodes.glyph
local glue_code = nodecodes.glue
local disc_code = nodecodes.disc
local math_code = nodecodes.math
-local dir_code = nodecodes.dir or whatcodes.dir
-local localpar_code = nodecodes.localpar or whatcodes.localpar
+local dir_code = nodecodes.dir
+local localpar_code = nodecodes.localpar
local discretionary_code = disccodes.discretionary
local ligature_code = glyphcodes.ligature
@@ -314,7 +313,9 @@ local function gref(n) -- currently the same as in font-otb
end
local function cref(dataset,sequence,index)
- if index then
+ if not dataset then
+ return "no valid dataset"
+ elseif index then
return formatters["feature %a, type %a, chain lookup %a, index %a"](dataset[4],sequence.type,sequence.name,index)
else
return formatters["feature %a, type %a, chain lookup %a"](dataset[4],sequence.type,sequence.name)
@@ -671,7 +672,7 @@ local function multiple_glyphs(head,start,multiple,ignoremarks)
setchar(start,multiple[1])
if nofmultiples > 1 then
local sn = getnext(start)
- for k=2,nofmultiples do -- todo: use insert_node
+ for k=2,nofmultiples do
-- untested:
--
-- while ignoremarks and marks[getchar(sn)] then
@@ -680,11 +681,7 @@ local function multiple_glyphs(head,start,multiple,ignoremarks)
local n = copy_node(start) -- ignore components
resetinjection(n)
setchar(n,multiple[k])
- setboth(n,start,sn)
- if sn then
- setprev(sn,n)
- end
- setnext(start,n)
+ insert_node_after(head,start,n)
start = n
end
end
@@ -777,9 +774,9 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature)
local startchar = getchar(start)
if marks[startchar] then
while current do
- local id = getid(current)
- if ischar(current,currentfont) then
- local lg = ligature[getchar(current)]
+ local ch = ischar(current,currentfont)
+ if ch then
+ local lg = ligature[ch]
if lg then
stop = current
ligature = lg
@@ -814,8 +811,8 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature)
local id = getid(current)
-- weird test here
if id == glyph_code then -- not needed
- if ischar(current,currentfont) then
- local char = getchar(current)
+ local char = ischar(current,currentfont)
+ if char then
if skipmark and marks[char] then
current = getnext(current)
else -- ligature is a tree
@@ -894,50 +891,54 @@ function handlers.gpos_pair(head,start,dataset,sequence,kerns,rlmode,step,i,inje
else
local prev = start
local done = false
- while snext and ischar(snext,currentfont) do
- local nextchar = getchar(snext)
- local krn = kerns[nextchar]
- if not krn and marks[nextchar] then
- prev = snext
- snext = getnext(snext)
- elseif not krn then
- break
- elseif step.format == "pair" then
- local a, b = krn[1], krn[2]
- if optimizekerns then
- -- this permits a mixed table, but we could also decide to optimize this
- -- in the loader and use format 'kern'
- if not b and a[1] == 0 and a[2] == 0 and a[4] == 0 then
- local k = setkern(snext,factor,rlmode,a[3],injection)
+ while snext do
+ local nextchar = ischar(snext,currentfont)
+ if nextchar then
+ local krn = kerns[nextchar]
+ if not krn and marks[nextchar] then
+ prev = snext
+ snext = getnext(snext)
+ elseif not krn then
+ break
+ elseif step.format == "pair" then
+ local a, b = krn[1], krn[2]
+ if optimizekerns then
+ -- this permits a mixed table, but we could also decide to optimize this
+ -- in the loader and use format 'kern'
+ if not b and a[1] == 0 and a[2] == 0 and a[4] == 0 then
+ local k = setkern(snext,factor,rlmode,a[3],injection)
+ if trace_kerns then
+ logprocess("%s: shifting single %s by %p",pref(dataset,sequence),gref(nextchar),k)
+ end
+ done = true
+ break
+ end
+ end
+ if a and #a > 0 then
+ local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,injection)
if trace_kerns then
- logprocess("%s: shifting single %s by %p",pref(dataset,sequence),gref(nextchar),k)
+ local startchar = getchar(start)
+ logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections")
end
- done = true
- break
end
- end
- if a and #a > 0 then
- local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,injection)
- if trace_kerns then
- local startchar = getchar(start)
- logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections")
+ if b and #b > 0 then
+ local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,injection)
+ if trace_kerns then
+ local startchar = getchar(snext)
+ logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections")
+ end
end
- end
- if b and #b > 0 then
- local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,injection)
+ done = true
+ break
+ elseif krn ~= 0 then
+ local k = setkern(snext,factor,rlmode,krn,injection)
if trace_kerns then
- local startchar = getchar(snext)
- logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections")
+ logprocess("%s: inserting kern %p between %s and %s as %s",pref(dataset,sequence),k,gref(getchar(prev)),gref(nextchar),injection or "injections")
end
+ done = true
+ break
end
- done = true
- break
- elseif krn ~= 0 then
- local k = setkern(snext,factor,rlmode,krn,injection)
- if trace_kerns then
- logprocess("%s: inserting kern %p between %s and %s as %s",pref(dataset,sequence),k,gref(getchar(prev)),gref(nextchar),injection or "injections")
- end
- done = true
+ else
break
end
end
@@ -956,36 +957,47 @@ function handlers.gpos_mark2base(head,start,dataset,sequence,markanchors,rlmode)
local markchar = getchar(start)
if marks[markchar] then
local base = getprev(start) -- [glyph] [start=mark]
- if base and ischar(base,currentfont) then
- local basechar = getchar(base)
- if marks[basechar] then
- while true do
- base = getprev(base)
- if base and ischar(base,currentfont) then
- basechar = getchar(base)
- if not marks[basechar] then
- break
- end
- else
- if trace_bugs then
- logwarning("%s: no base for mark %s",pref(dataset,sequence),gref(markchar))
+ if base then
+ local basechar = ischar(base,currentfont)
+ if basechar then
+ if marks[basechar] then
+ while true do
+ base = getprev(base)
+ if base then
+ basechar = ischar(base,currentfont)
+ if basechar then
+ if not marks[basechar] then
+ break
+ end
+ else
+ if trace_bugs then
+ logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),1)
+ end
+ return head, start, false
+ end
+ else
+ if trace_bugs then
+ logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),2)
+ end
+ return head, start, false
end
- return head, start, false
end
end
- end
- local ba = markanchors[1][basechar]
- if ba then
- local ma = markanchors[2]
- local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
- if trace_marks then
- logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
- pref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+ local ba = markanchors[1][basechar]
+ if ba then
+ local ma = markanchors[2]
+ local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
+ if trace_marks then
+ logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
+ pref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+ end
+ return head, start, true
end
- return head, start, true
+ elseif trace_bugs then
+ logwarning("%s: nothing preceding, case %i",pref(dataset,sequence),1)
end
elseif trace_bugs then
- logwarning("%s: prev node is no char",pref(dataset,sequence))
+ logwarning("%s: nothing preceding, case %i",pref(dataset,sequence),2)
end
elseif trace_bugs then
logwarning("%s: mark %s is no mark",pref(dataset,sequence),gref(markchar))
@@ -999,49 +1011,60 @@ function handlers.gpos_mark2ligature(head,start,dataset,sequence,markanchors,rlm
local markchar = getchar(start)
if marks[markchar] then
local base = getprev(start) -- [glyph] [optional marks] [start=mark]
- if base and ischar(base,currentfont) then
- local basechar = getchar(base)
- if marks[basechar] then
- while true do
- base = getprev(base)
- if base and ischar(base,currentfont) then
- basechar = getchar(base)
- if not marks[basechar] then
- break
- end
- else
- if trace_bugs then
- logwarning("%s: no base for mark %s",pref(dataset,sequence),gref(markchar))
+ if base then
+ local basechar = ischar(base,currentfont)
+ if basechar then
+ if marks[basechar] then
+ while true do
+ base = getprev(base)
+ if base then
+ basechar = ischar(base,currentfont)
+ if basechar then
+ if not marks[basechar] then
+ break
+ end
+ else
+ if trace_bugs then
+ logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),1)
+ end
+ return head, start, false
+ end
+ else
+ if trace_bugs then
+ logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),2)
+ end
+ return head, start, false
end
- return head, start, false
end
end
- end
- local ba = markanchors[1][basechar]
- if ba then
- local ma = markanchors[2]
- if ma then
- local index = getligaindex(start)
- ba = ba[index]
- if ba then
- local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar]) -- index
- if trace_marks then
- logprocess("%s, anchor %s, index %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
- pref(dataset,sequence),anchor,index,bound,gref(markchar),gref(basechar),index,dx,dy)
- end
- return head, start, true
- else
- if trace_bugs then
- logwarning("%s: no matching anchors for mark %s and baselig %s with index %a",pref(dataset,sequence),gref(markchar),gref(basechar),index)
+ local ba = markanchors[1][basechar]
+ if ba then
+ local ma = markanchors[2]
+ if ma then
+ local index = getligaindex(start)
+ ba = ba[index]
+ if ba then
+ local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar]) -- index
+ if trace_marks then
+ logprocess("%s, anchor %s, index %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
+ pref(dataset,sequence),anchor,index,bound,gref(markchar),gref(basechar),index,dx,dy)
+ end
+ return head, start, true
+ else
+ if trace_bugs then
+ logwarning("%s: no matching anchors for mark %s and baselig %s with index %a",pref(dataset,sequence),gref(markchar),gref(basechar),index)
+ end
end
end
+ elseif trace_bugs then
+ -- logwarning("%s: char %s is missing in font",pref(dataset,sequence),gref(basechar))
+ onetimemessage(currentfont,basechar,"no base anchors",report_fonts)
end
elseif trace_bugs then
- -- logwarning("%s: char %s is missing in font",pref(dataset,sequence),gref(basechar))
- onetimemessage(currentfont,basechar,"no base anchors",report_fonts)
+ logwarning("%s: prev node is no char, case %i",pref(dataset,sequence),1)
end
elseif trace_bugs then
- logwarning("%s: prev node is no char",pref(dataset,sequence))
+ logwarning("%s: prev node is no char, case %i",pref(dataset,sequence),2)
end
elseif trace_bugs then
logwarning("%s: mark %s is no mark",pref(dataset,sequence),gref(markchar))
@@ -1064,17 +1087,19 @@ function handlers.gpos_mark2mark(head,start,dataset,sequence,markanchors,rlmode)
end
end
end
- if base and ischar(base,currentfont) then -- subtype test can go
- local basechar = getchar(base)
- local ba = markanchors[1][basechar] -- slot 1 has been made copy of the class hash
- if ba then
- local ma = markanchors[2]
- local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true)
- if trace_marks then
- logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
- pref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+ if base then
+ local basechar = ischar(base,currentfont)
+ if basechar then -- subtype test can go
+ local ba = markanchors[1][basechar] -- slot 1 has been made copy of the class hash
+ if ba then
+ local ma = markanchors[2]
+ local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true)
+ if trace_marks then
+ logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
+ pref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+ end
+ return head, start, true
end
- return head, start, true
end
end
elseif trace_bugs then
@@ -1094,9 +1119,11 @@ function handlers.gpos_cursive(head,start,dataset,sequence,exitanchors,rlmode,st
end
else
local nxt = getnext(start)
- while not done and nxt and ischar(nxt,currentfont) do
- local nextchar = getchar(nxt)
- if marks[nextchar] then
+ while not done and nxt do
+ local nextchar = ischar(nxt,currentfont)
+ if not nextchar then
+ break
+ elseif marks[nextchar] then
-- should not happen (maybe warning)
nxt = getnext(nxt)
else
@@ -1159,7 +1186,7 @@ local logwarning = report_chain
-- in a bit weird way. There is no lookup and the replacement comes from the lookup
-- itself. It is meant mostly for dealing with Urdu.
-function chainprocs.reversesub(head,start,stop,dataset,sequence,replacements,rlmode)
+local function reversesub(head,start,stop,dataset,sequence,replacements,rlmode)
local char = getchar(start)
local replacement = replacements[char]
if replacement then
@@ -1174,6 +1201,9 @@ function chainprocs.reversesub(head,start,stop,dataset,sequence,replacements,rlm
end
end
+
+chainprocs.reversesub = reversesub
+
--[[ldx--
<p>This chain stuff is somewhat tricky since we can have a sequence of actions to be
applied: single, alternate, multiple or ligature where ligature can be an invalid
@@ -1282,7 +1312,7 @@ function chainprocs.gsub_multiple(head,start,stop,dataset,sequence,currentlookup
end
else
if trace_multiples then
- logprocess("%s: replacing %s by multiple characters %s",cref(dataset,sequence),gref(startchar),gref(replacements))
+ logprocess("%s: replacing %s by multiple characters %s",cref(dataset,sequence),gref(startchar),gref(replacement))
end
return multiple_glyphs(head,start,replacement,currentlookup.flags[1]) -- not sequence.flags?
end
@@ -1463,8 +1493,11 @@ function chainprocs.gpos_pair(head,start,stop,dataset,sequence,currentlookup,rlm
if kerns then
local prev = start
local done = false
- while snext and ischar(snext,currentfont) do
- local nextchar = getchar(snext)
+ while snext do
+ local nextchar = ischar(snext,currentfont)
+ if not nextchar then
+ break
+ end
local krn = kerns[nextchar]
if not krn and marks[nextchar] then
prev = snext
@@ -1527,38 +1560,49 @@ function chainprocs.gpos_mark2base(head,start,stop,dataset,sequence,currentlooku
local markanchors = steps[1].coverage[markchar] -- always 1 step
if markanchors then
local base = getprev(start) -- [glyph] [start=mark]
- if base and ischar(base,currentfont) then
- local basechar = getchar(base)
- if marks[basechar] then
- while true do
- base = getprev(base)
- if base and ischar(base,currentfont) then
- basechar = getchar(base)
- if not marks[basechar] then
- break
- end
- else
- if trace_bugs then
- logwarning("%s: no base for mark %s",pref(dataset,sequence),gref(markchar))
+ if base then
+ local basechar = ischar(base,currentfont)
+ if basechar then
+ if marks[basechar] then
+ while true do
+ base = getprev(base)
+ if base then
+ local basechar = ischar(base,currentfont)
+ if basechar then
+ if not marks[basechar] then
+ break
+ end
+ else
+ if trace_bugs then
+ logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),1)
+ end
+ return head, start, false
+ end
+ else
+ if trace_bugs then
+ logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),2)
+ end
+ return head, start, false
end
- return head, start, false
end
end
- end
- local ba = markanchors[1][basechar]
- if ba then
- local ma = markanchors[2]
- if ma then
- local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
- if trace_marks then
- logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
- cref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+ local ba = markanchors[1][basechar]
+ if ba then
+ local ma = markanchors[2]
+ if ma then
+ local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
+ if trace_marks then
+ logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
+ cref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+ end
+ return head, start, true
end
- return head, start, true
end
+ elseif trace_bugs then
+ logwarning("%s: prev node is no char, case %i",cref(dataset,sequence),1)
end
elseif trace_bugs then
- logwarning("%s: prev node is no char",cref(dataset,sequence))
+ logwarning("%s: prev node is no char, case %i",cref(dataset,sequence),2)
end
elseif trace_bugs then
logwarning("%s: mark %s has no anchors",cref(dataset,sequence),gref(markchar))
@@ -1580,42 +1624,53 @@ function chainprocs.gpos_mark2ligature(head,start,stop,dataset,sequence,currentl
local markanchors = steps[1].coverage[markchar] -- always 1 step
if markanchors then
local base = getprev(start) -- [glyph] [optional marks] [start=mark]
- if base and ischar(base,currentfont) then
- local basechar = getchar(base)
- if marks[basechar] then
- while true do
- base = getprev(base)
- if base and ischar(base,currentfont) then
- basechar = getchar(base)
- if not marks[basechar] then
- break
- end
- else
- if trace_bugs then
- logwarning("%s: no base for mark %s",cref(dataset,sequence),markchar)
+ if base then
+ local basechar = ischar(base,currentfont)
+ if basechar then
+ if marks[basechar] then
+ while true do
+ base = getprev(base)
+ if base then
+ local basechar = ischar(base,currentfont)
+ if basechar then
+ if not marks[basechar] then
+ break
+ end
+ else
+ if trace_bugs then
+ logwarning("%s: no base for mark %s, case %i",cref(dataset,sequence),markchar,1)
+ end
+ return head, start, false
+ end
+ else
+ if trace_bugs then
+ logwarning("%s: no base for mark %s, case %i",cref(dataset,sequence),markchar,2)
+ end
+ return head, start, false
end
- return head, start, false
end
end
- end
- local ba = markanchors[1][basechar]
- if ba then
- local ma = markanchors[2]
- if ma then
- local index = getligaindex(start)
- ba = ba[index]
- if ba then
- local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
- if trace_marks then
- logprocess("%s, anchor %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
- cref(dataset,sequence),anchor,a or bound,gref(markchar),gref(basechar),index,dx,dy)
+ local ba = markanchors[1][basechar]
+ if ba then
+ local ma = markanchors[2]
+ if ma then
+ local index = getligaindex(start)
+ ba = ba[index]
+ if ba then
+ local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
+ if trace_marks then
+ logprocess("%s, anchor %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
+ cref(dataset,sequence),anchor,a or bound,gref(markchar),gref(basechar),index,dx,dy)
+ end
+ return head, start, true
end
- return head, start, true
end
end
+ elseif trace_bugs then
+ logwarning("%s, prev node is no char, case %i",cref(dataset,sequence),1)
end
elseif trace_bugs then
- logwarning("%s, prev node is no char",cref(dataset,sequence))
+ logwarning("%s, prev node is no char, case %i",cref(dataset,sequence),2)
end
elseif trace_bugs then
logwarning("%s, mark %s has no anchors",cref(dataset,sequence),gref(markchar))
@@ -1648,22 +1703,26 @@ function chainprocs.gpos_mark2mark(head,start,stop,dataset,sequence,currentlooku
end
end
end
- if base and ischar(base,currentfont) then -- subtype test can go
- local basechar = getchar(base)
- local ba = markanchors[1][basechar]
- if ba then
- local ma = markanchors[2]
- if ma then
- local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true)
- if trace_marks then
- logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
- cref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+ if base then -- subtype test can go
+ local basechar = ischar(base,currentfont)
+ if basechar then
+ local ba = markanchors[1][basechar]
+ if ba then
+ local ma = markanchors[2]
+ if ma then
+ local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true)
+ if trace_marks then
+ logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
+ cref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+ end
+ return head, start, true
end
- return head, start, true
end
+ elseif trace_bugs then
+ logwarning("%s: prev node is no mark, case %i",cref(dataset,sequence),1)
end
elseif trace_bugs then
- logwarning("%s: prev node is no mark",cref(dataset,sequence))
+ logwarning("%s: prev node is no mark, case %i",cref(dataset,sequence),2)
end
elseif trace_bugs then
logwarning("%s: mark %s has no anchors",cref(dataset,sequence),gref(markchar))
@@ -1692,9 +1751,11 @@ function chainprocs.gpos_cursive(head,start,stop,dataset,sequence,currentlookup,
end
else
local nxt = getnext(start)
- while not done and nxt and ischar(nxt,currentfont) do
- local nextchar = getchar(nxt)
- if marks[nextchar] then
+ while not done and nxt do
+ local nextchar = ischar(nxt,currentfont)
+ if not nextchar then
+ break
+ elseif marks[nextchar] then
-- should not happen (maybe warning)
nxt = getnext(nxt)
else
@@ -1934,11 +1995,16 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
local cprev = getprev(start)
local insertedmarks = 0
- while cprev and ischar(cf,currentfont) and marks[getchar(cf)] do
- insertedmarks = insertedmarks + 1
- cf = cprev
- startishead = cf == head
- cprev = getprev(cprev)
+ while cprev do
+ local char = ischar(cf,currentfont)
+ if char and marks[char] then
+ insertedmarks = insertedmarks + 1
+ cf = cprev
+ startishead = cf == head
+ cprev = getprev(cprev)
+ else
+ break
+ end
end
setprev(lookaheaddisc,cprev)
@@ -1985,10 +2051,15 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
local cnext = getnext(start)
local insertedmarks = 0
- while cnext and ischar(cnext,currentfont) and marks[getchar(cnext)] do
- insertedmarks = insertedmarks + 1
- cl = cnext
- cnext = getnext(cnext)
+ while cnext do
+ local char = ischar(cnext,currentfont)
+ if char and marks[char] then
+ insertedmarks = insertedmarks + 1
+ cl = cnext
+ cnext = getnext(cnext)
+ else
+ break
+ end
end
if cnext then
setprev(cnext,backtrackdisc)
@@ -2119,7 +2190,8 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
-- f..l = mid string
if s == 1 then
-- never happens
- match = ischar(current,currentfont) and seq[1][getchar(current)]
+ local char = ischar(current,currentfont)
+ match = char and seq[1][char]
else
-- maybe we need a better space check (maybe check for glue or category or combination)
-- we cannot optimize for n=2 because there can be disc nodes
@@ -2145,8 +2217,8 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
if last then
local id = getid(last)
if id == glyph_code then
- if ischar(last,currentfont) then
- local char = getchar(last)
+ local char = ischar(last,currentfont)
+ if char then
local ccd = descriptions[char]
if ccd then
local class = ccd.class or "base"
@@ -2259,15 +2331,15 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
if prev then
local id = getid(prev)
if id == glyph_code then
- if ischar(prev,currentfont) then
- local char = getchar(prev)
+ local char = ischar(prev,currentfont)
+ if char then
local ccd = descriptions[char]
if ccd then
local class = ccd.class
if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
skipped = true
if trace_skips then
- show_skip(kind,chainname,char,ck,class)
+ show_skip(dataset,sequence,char,ck,class)
end
elseif seq[n][char] then
n = n -1
@@ -2397,15 +2469,15 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
if current then
local id = getid(current)
if id == glyph_code then
- if ischar(current,currentfont) then
- local char = getchar(current)
+ local char = ischar(current,currentfont)
+ if char then
local ccd = descriptions[char]
if ccd then
local class = ccd.class
if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
skipped = true
if trace_skips then
- show_skip(kind,chainname,char,ck,class)
+ show_skip(dataset,sequence,char,ck,class)
end
elseif seq[n][char] then
n = n + 1
@@ -2534,7 +2606,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
done = true
end
else
- logprocess("%s: %s is not yet supported",cref(dataset,sequence),chainkind)
+ logprocess("%s: %s is not yet supported (1)",cref(dataset,sequence),chainkind)
end
else
local i = 1
@@ -2591,7 +2663,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
else
-- actually an error
- logprocess("%s: %s is not yet supported",cref(dataset,sequence),chainkind)
+ logprocess("%s: %s is not yet supported (2)",cref(dataset,sequence),chainkind)
end
i = i + 1
end
@@ -2605,7 +2677,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
else
local replacements = ck[7]
if replacements then
- head, start, done = chainprocs.reversesub(head,start,last,dataset,sequence,replacements,rlmode)
+ head, start, done = reversesub(head,start,last,dataset,sequence,replacements,rlmode)
else
done = quit_on_no_replacement -- can be meant to be skipped / quite inconsistent in fonts
if trace_contexts then
@@ -2632,6 +2704,23 @@ handlers.gsub_reversecontextchain = handle_contextchain
handlers.gpos_contextchain = handle_contextchain
handlers.gpos_context = handle_contextchain
+-- this needs testing
+
+function chained_contextchain(head,start,stop,dataset,sequence,currentlookup,rlmode)
+ local steps = currentlookup.steps
+ local nofsteps = currentlookup.nofsteps
+ if nofsteps > 1 then
+ reportmoresteps(dataset,sequence)
+ end
+ return handle_contextchain(head,start,dataset,sequence,currentlookup,rlmode)
+end
+
+chainprocs.gsub_context = chained_contextchain
+chainprocs.gsub_contextchain = chained_contextchain
+chainprocs.gsub_reversecontextchain = chained_contextchain
+chainprocs.gpos_contextchain = chained_contextchain
+chainprocs.gpos_context = chained_contextchain
+
local missing = setmetatableindex("table")
local function logprocess(...)
@@ -2667,20 +2756,33 @@ end)
-- fonts.hashes.sequences = sequencelists
-local autofeatures = fonts.analyzers.features -- was: constants
+local autofeatures = fonts.analyzers.features
+local featuretypes = otf.tables.featuretypes
+local defaultscript = otf.features.checkeddefaultscript
+local defaultlanguage = otf.features.checkeddefaultlanguage
-local function initialize(sequence,script,language,enabled)
+local function initialize(sequence,script,language,enabled,autoscript,autolanguage)
local features = sequence.features
if features then
local order = sequence.order
if order then
- for i=1,#order do --
- local kind = order[i] --
+ local featuretype = featuretypes[sequence.type or "unknown"]
+ for i=1,#order do
+ local kind = order[i]
local valid = enabled[kind]
if valid then
- local scripts = features[kind] --
- local languages = scripts[script] or scripts[wildcard]
- if languages and (languages[language] or languages[wildcard]) then
+ local scripts = features[kind]
+ local languages = scripts and (
+ scripts[script] or
+ scripts[wildcard] or
+ (autoscript and defaultscript(featuretype,autoscript,scripts))
+ )
+ local enabled = languages and (
+ languages[language] or
+ languages[wildcard] or
+ (autolanguage and defaultlanguage(featuretype,autolanguage,languages))
+ )
+ if enabled then
return { valid, autofeatures[kind] or false, sequence, kind }
end
end
@@ -2693,11 +2795,13 @@ local function initialize(sequence,script,language,enabled)
end
function otf.dataset(tfmdata,font) -- generic variant, overloaded in context
- local shared = tfmdata.shared
- local properties = tfmdata.properties
- local language = properties.language or "dflt"
- local script = properties.script or "dflt"
- local enabled = shared.features
+ local shared = tfmdata.shared
+ local properties = tfmdata.properties
+ local language = properties.language or "dflt"
+ local script = properties.script or "dflt"
+ local enabled = shared.features
+ local autoscript = enabled and enabled.autoscript
+ local autolanguage = enabled and enabled.autolanguage
local res = resolved[font]
if not res then
res = { }
@@ -2716,7 +2820,7 @@ function otf.dataset(tfmdata,font) -- generic variant, overloaded in context
rs[language] = rl
local sequences = tfmdata.resources.sequences
for s=1,#sequences do
- local v = enabled and initialize(sequences[s],script,language,enabled)
+ local v = enabled and initialize(sequences[s],script,language,enabled,autoscript,autolanguage)
if v then
rl[#rl+1] = v
end
@@ -2746,8 +2850,13 @@ local function kernrun(disc,run)
-- can be optional, because why on earth do we get a disc after a mark (okay, maybe when a ccmp
-- has happened but then it should be in the disc so basically this test indicates an error)
--
- while prevmarks and ischar(prevmarks,currentfont) and marks[getchar(prevmarks)] do
- prevmarks = getprev(prevmarks)
+ while prevmarks do
+ local char = ischar(prevmarks,currentfont)
+ if char and marks[char] then
+ prevmarks = getprev(prevmarks)
+ else
+ break
+ end
end
--
if prev and (pre or replace) and not ischar(prev,currentfont) then
@@ -3014,8 +3123,9 @@ local function featuresprocessor(head,font,attr)
-- 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
- local id = getid(start)
- if ischar(start,font) then
+ local id = getid(start)
+ local char = ischar(start,font)
+ if char then
local a = getattr(start,0)
if a then
a = a == attr
@@ -3023,7 +3133,6 @@ local function featuresprocessor(head,font,attr)
a = true
end
if a then
- local char = getchar(start)
for i=1,nofsteps do
local step = steps[i]
local lookupcache = step.coverage
@@ -3069,32 +3178,35 @@ local function featuresprocessor(head,font,attr)
while start do
local id = getid(start)
if id ~= glyph_code then
- -- very unlikely
+ -- very unlikely (if so we could use ischar)
start = getnext(start)
- elseif ischar(start,font) then
- local a = getattr(start,0)
--- if a then
--- a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
--- else
--- a = not attribute or getprop(start,a_state) == attribute
--- end
--- if a then
-if not a or (a == attr) then
- local lookupmatch = lookupcache[getchar(start)]
- if lookupmatch then
- -- sequence kan weg
- local ok
- head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1)
- if ok then
- done = true
+ else
+ local char = ischar(start,font)
+ if char then
+ local a = getattr(start,0)
+ -- if a then
+ -- a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
+ -- else
+ -- a = not attribute or getprop(start,a_state) == attribute
+ -- end
+ -- if a then
+ if not a or (a == attr) then
+ local lookupmatch = lookupcache[char]
+ if lookupmatch then
+ -- sequence kan weg
+ local ok
+ head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1)
+ if ok then
+ done = true
+ end
end
+ if start then start = getnext(start) end
+ else
+ start = getnext(start)
end
- if start then start = getnext(start) end
else
- start = getnext(start)
+ return head, false
end
- else
- return head, false
end
end
if done then
@@ -3106,16 +3218,17 @@ if not a or (a == attr) then
local function t_run(start,stop)
while start ~= stop do
local id = getid(start)
- if ischar(start,font) then
+ local char = ischar(start,font)
+ if char then
local a = getattr(start,0)
--- if a then
--- a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
--- else
--- a = not attribute or getprop(start,a_state) == attribute
--- end
--- if a then
-if not a or (a == attr) then
- local lookupmatch = lookupcache[getchar(start)]
+ -- if a then
+ -- a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
+ -- else
+ -- a = not attribute or getprop(start,a_state) == attribute
+ -- end
+ -- if a then
+ if not a or (a == attr) then
+ local lookupmatch = lookupcache[char]
if lookupmatch then -- hm, hyphens can match (tlig) so we need to really check
-- if we need more than ligatures we can outline the code and use functions
local s = getnext(start)
@@ -3143,13 +3256,13 @@ if not a or (a == attr) then
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
-if not a or (a == attr) then
+ -- 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
+ if not a or (a == attr) then
local lookupmatch = lookupcache[getchar(prev)]
if lookupmatch then
-- sequence kan weg
@@ -3164,13 +3277,13 @@ if not a or (a == attr) then
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
-if not a or (a == attr) then
+ -- 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
+ if not a or (a == attr) then
-- sequence kan weg
for n in traverse_nodes(sub) do -- only gpos
if n == last then
@@ -3196,7 +3309,8 @@ if not a or (a == attr) then
while start do
local id = getid(start)
if id == glyph_code then
- if ischar(start,font) then
+ local char = ischar(start,font)
+ if char then
local a = getattr(start,0)
if a then
a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
@@ -3204,7 +3318,6 @@ if not a or (a == attr) then
a = not attribute or getprop(start,a_state) == attribute
end
if a then
- local char = getchar(start)
local lookupmatch = lookupcache[char]
if lookupmatch then
-- sequence kan weg
@@ -3293,43 +3406,45 @@ if not a or (a == attr) then
if id ~= glyph_code then
-- very unlikely
start = getnext(start)
- elseif ischar(start,font) then
- local a = getattr(start,0)
--- if a then
--- a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
--- else
--- a = not attribute or getprop(start,a_state) == attribute
--- end
--- if a then
-if not a or (a == attr) then
- local char = getchar(start)
- for i=1,nofsteps do
- local step = steps[i]
- local lookupcache = step.coverage
- if lookupcache then
- 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,sequence,lookupmatch,rlmode,step,i)
- if ok then
- done = true
- break
- elseif not start then
- -- don't ask why ... shouldn't happen
- break
+ else
+ local char = ischar(start,font)
+ if char then
+ local a = getattr(start,0)
+ -- if a then
+ -- a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
+ -- else
+ -- a = not attribute or getprop(start,a_state) == attribute
+ -- end
+ -- if a then
+ if not a or (a == attr) then
+ for i=1,nofsteps do
+ local step = steps[i]
+ local lookupcache = step.coverage
+ if lookupcache then
+ 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,sequence,lookupmatch,rlmode,step,i)
+ if ok then
+ done = true
+ break
+ elseif not start then
+ -- don't ask why ... shouldn't happen
+ break
+ end
end
+ else
+ report_missing_cache(dataset,sequence)
end
- else
- report_missing_cache(dataset,sequence)
end
+ if start then start = getnext(start) end
+ else
+ start = getnext(start)
end
- if start then start = getnext(start) end
else
- start = getnext(start)
+ return head, false
end
- else
- return head, false
end
end
if done then
@@ -3340,13 +3455,13 @@ if not a or (a == attr) then
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
-if not a or (a == attr) then
+ -- 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
+ if not a or (a == attr) then
-- brr prev can be disc
local char = getchar(prev)
for i=1,nofsteps do
@@ -3371,13 +3486,13 @@ if not a or (a == attr) then
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
-if not a or (a == attr) then
+ -- 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
+ if not a or (a == attr) then
for n in traverse_nodes(sub) do -- only gpos
if n == last then
break
@@ -3410,17 +3525,17 @@ if not a or (a == attr) then
local function t_run(start,stop)
while start ~= stop do
- local id = getid(start)
- if ischar(start,font) then
+ local id = getid(start)
+ local char = ischar(start,font)
+ if char then
local a = getattr(start,0)
--- if a then
--- a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
--- else
--- a = not attribute or getprop(start,a_state) == attribute
--- end
--- if a then
-if not a or (a == attr) then
- local char = getchar(start)
+ -- if a then
+ -- a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
+ -- else
+ -- a = not attribute or getprop(start,a_state) == attribute
+ -- end
+ -- if a then
+ if not a or (a == attr) then
for i=1,nofsteps do
local step = steps[i]
local lookupcache = step.coverage
@@ -3458,7 +3573,8 @@ if not a or (a == attr) then
while start do
local id = getid(start)
if id == glyph_code then
- if ischar(start,font) then
+ local char = ischar(start,font)
+ if char then
local a = getattr(start,0)
if a then
a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
@@ -3470,7 +3586,7 @@ if not a or (a == attr) then
local step = steps[i]
local lookupcache = step.coverage
if lookupcache then
- local char = 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