summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ots.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ots.lua')
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ots.lua318
1 files changed, 127 insertions, 191 deletions
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ots.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ots.lua
index 21225c2274f..d63d524ccb2 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ots.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ots.lua
@@ -124,7 +124,7 @@ local trace_cursive = false registertracker("otf.cursive", function(v
local trace_preparing = false registertracker("otf.preparing", function(v) trace_preparing = v end)
local trace_bugs = false registertracker("otf.bugs", function(v) trace_bugs = v end)
local trace_details = false registertracker("otf.details", function(v) trace_details = v end)
-local trace_applied = false registertracker("otf.applied", function(v) trace_applied = v end)
+----- trace_applied = false registertracker("otf.applied", function(v) trace_applied = v end)
local trace_steps = false registertracker("otf.steps", function(v) trace_steps = v end)
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)
@@ -145,10 +145,8 @@ local report_direct = logs.reporter("fonts","otf direct")
local report_subchain = logs.reporter("fonts","otf subchain")
local report_chain = logs.reporter("fonts","otf chain")
local report_process = logs.reporter("fonts","otf process")
------ report_prepare = logs.reporter("fonts","otf prepare")
local report_warning = logs.reporter("fonts","otf warning")
local report_run = logs.reporter("fonts","otf run")
-local report_check = logs.reporter("fonts","otf check")
registertracker("otf.replacements", "otf.singles,otf.multiples,otf.alternatives,otf.ligatures")
registertracker("otf.positions","otf.marks,otf.kerns,otf.cursive")
@@ -185,10 +183,7 @@ local setlink = nuts.setlink
local ischar = nuts.is_char
-local insert_node_before = nuts.insert_before
local insert_node_after = nuts.insert_after
-local delete_node = nuts.delete
-local remove_node = nuts.remove
local copy_node = nuts.copy
local copy_node_list = nuts.copy_list
local find_node_tail = nuts.tail
@@ -197,6 +192,7 @@ local free_node = nuts.free
local end_of_math = nuts.end_of_math
local traverse_nodes = nuts.traverse
local traverse_id = nuts.traverse_id
+local remove_node = nuts.remove
local setmetatableindex = table.setmetatableindex
@@ -244,7 +240,7 @@ local cursonce = true
local fonthashes = fonts.hashes
local fontdata = fonthashes.identifiers
-local otffeatures = fonts.constructors.newfeatures("otf")
+local otffeatures = fonts.constructors.features.otf
local registerotffeature = otffeatures.register
local onetimemessage = fonts.loggers.onetimemessage or function() end
@@ -1241,7 +1237,7 @@ function chainprocs.gsub_multiple(head,start,stop,dataset,sequence,currentlookup
if trace_multiples then
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?
+ return multiple_glyphs(head,start,replacement,sequence.flags[1])
end
return head, start, false
end
@@ -2038,67 +2034,6 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
return head, start, ok
end
--- helpers from elsewhere
-
--- local function currentmatch(current,n,l)
--- while current do
--- if getid(current) ~= glyph_code then
--- return false
--- elseif seq[n][getchar(current)] then
--- n = n + 1
--- current = getnext(current)
--- if not current then
--- return true, n, current
--- elseif n > l then
--- -- match = false
--- return true, n, current
--- end
--- else
--- return false
--- end
--- end
--- end
---
--- local function aftermatch(current,n,l)
--- while current do
--- if getid(current) ~= glyph_code then
--- return false
--- elseif seq[n][getchar(current)] then
--- n = n + 1
--- current = getnext(current)
--- if not current then
--- return true, n, current
--- elseif n > l then
--- -- match = false
--- return true, n, current
--- end
--- else
--- return false
--- end
--- end
--- end
---
--- local function beforematch(current,n)
--- local finish = getprev(current)
--- local current = find_node_tail(current)
--- while current do
--- if getid(current) ~= glyph_code then
--- return false
--- elseif seq[n][getchar(current)] then
--- n = n - 1
--- current = getprev(current)
--- if not current or current == finish then
--- return true, n, current
--- elseif n < 1 then
--- -- match = false
--- return true, n, current
--- end
--- else
--- return false
--- end
--- end
--- end
-
local noflags = { false, false, false, false }
local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
@@ -2121,9 +2056,10 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
local ck = contexts[k]
local seq = ck[3]
local s = #seq
+ local size = 1
-- f..l = mid string
if s == 1 then
- -- never happens
+ -- this seldom happens as it makes no sense (bril, ebgaramond, husayni, minion)
local char = ischar(current,currentfont)
if char then
match = seq[1][char]
@@ -2134,48 +2070,34 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
local f = ck[4]
local l = ck[5]
-- current match
- if f == 1 and f == l then -- current only
- -- already a hit
- -- match = true
- else -- before/current/after | before/current | current/after
- -- no need to test first hit (to be optimized)
- if f == l then -- new, else last out of sync (f is > 1)
- -- match = true
- else
- local discfound = nil
- local n = f + 1
- last = getnext(last) -- the second in current (first already matched)
- while n <= l do
- if not last and (sweeptype == "post" or sweeptype == "replace") then
- last = getnext(sweepnode)
- sweeptype = nil
- end
- if last then
- local char, id = ischar(last,currentfont)
- if char then
- local ccd = descriptions[char]
- if ccd then
- local class = ccd.class or "base"
- 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(dataset,sequence,char,ck,class)
- end
+ size = l - f + 1
+ if size > 1 then
+ -- before/current/after | before/current | current/after
+ local discfound = nil
+ local n = f + 1
+ last = getnext(last) -- the second in current (first already matched)
+ while n <= l do
+ if not last and (sweeptype == "post" or sweeptype == "replace") then
+ last = getnext(sweepnode)
+ sweeptype = nil
+ end
+ if last then
+ local char, id = ischar(last,currentfont)
+ if char then
+ local ccd = descriptions[char]
+ if ccd then
+ local class = ccd.class or "base"
+ 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(dataset,sequence,char,ck,class)
+ end
+ last = getnext(last)
+ elseif seq[n][char] then
+ if n < l then
last = getnext(last)
- elseif seq[n][char] then
- if n < l then
- last = getnext(last)
- end
- n = n + 1
- else
- if discfound then
- notmatchreplace[discfound] = true
- match = not notmatchpre[discfound]
- else
- match = false
- end
- break
end
+ n = n + 1
else
if discfound then
notmatchreplace[discfound] = true
@@ -2185,7 +2107,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
break
end
- elseif char == false then
+ else
if discfound then
notmatchreplace[discfound] = true
match = not notmatchpre[discfound]
@@ -2193,60 +2115,68 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
match = false
end
break
- elseif id == disc_code then
- diskseen = true
- discfound = last
- notmatchpre[last] = nil
- notmatchpost[last] = true
- notmatchreplace[last] = nil
- local pre, post, replace = getdisc(last)
- if pre then
- local n = n
- while pre do
- if seq[n][getchar(pre)] then
- n = n + 1
- pre = getnext(pre)
- if n > l then
- break
- end
- else
- notmatchpre[last] = true
+ end
+ elseif char == false then
+ if discfound then
+ notmatchreplace[discfound] = true
+ match = not notmatchpre[discfound]
+ else
+ match = false
+ end
+ break
+ elseif id == disc_code then
+ diskseen = true
+ discfound = last
+ notmatchpre[last] = nil
+ notmatchpost[last] = true
+ notmatchreplace[last] = nil
+ local pre, post, replace = getdisc(last)
+ if pre then
+ local n = n
+ while pre do
+ if seq[n][getchar(pre)] then
+ n = n + 1
+ pre = getnext(pre)
+ if n > l then
break
end
- end
- if n <= l then
+ else
notmatchpre[last] = true
+ break
end
- else
+ end
+ if n <= l then
notmatchpre[last] = true
end
- if replace then
- -- so far we never entered this branch
- while replace do
- if seq[n][getchar(replace)] then
- n = n + 1
- replace = getnext(replace)
- if n > l then
- break
- end
- else
- notmatchreplace[last] = true
- match = not notmatchpre[last]
+ else
+ notmatchpre[last] = true
+ end
+ if replace then
+ -- so far we never entered this branch
+ while replace do
+ if seq[n][getchar(replace)] then
+ n = n + 1
+ replace = getnext(replace)
+ if n > l then
break
end
+ else
+ notmatchreplace[last] = true
+ match = not notmatchpre[last]
+ break
end
- match = not notmatchpre[last]
end
- -- maybe only if match
- last = getnext(last)
- else
- match = false
- break
+ match = not notmatchpre[last]
end
+ -- maybe only if match
+ last = getnext(last)
else
match = false
break
end
+ else
+ match = false
+ break
end
end
end
@@ -2514,7 +2444,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
end
if match then
- -- can lookups be of a different type ?
+ -- Can lookups be of a different type?
local diskchain = diskseen or sweepnode
if trace_contexts then
local rule = ck[1]
@@ -2528,8 +2458,12 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
local chainlookups = ck[6]
if chainlookups then
local nofchainlookups = #chainlookups
- -- we can speed this up if needed
- if nofchainlookups == 1 then
+ -- Lookups can be like { 1, false, 3 } or { false, 2 } or basically anything and
+ -- #lookups can be less than #current
+ if size == 1 then
+ -- if nofchainlookups > size then
+ -- -- bad rules
+ -- end
local chainlookup = chainlookups[1]
local chainkind = chainlookup.type
local chainproc = chainprocs[chainkind]
@@ -2547,8 +2481,16 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
logprocess("%s: %s is not yet supported (1)",cref(dataset,sequence),chainkind)
end
else
+ -- See LookupType 5: Contextual Substitution Subtable. Now it becomes messy. The
+ -- easiest case is where #current maps on #lookups i.e. one-to-one. But what if
+ -- we have a ligature. Cf the spec we then need to advance one character but we
+ -- really need to test it as there are fonts out there that are fuzzy and have
+ -- too many lookups:
+ --
+ -- U+1105 U+119E U+1105 U+119E : sourcehansansklight: script=hang ccmp=yes
+ --
local i = 1
- while start and true do
+ while start do
if skipped then
while start do -- todo: use properties
local char = getchar(start)
@@ -2565,12 +2507,8 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
end
end
- -- see remark in ms standard under : LookupType 5: Contextual Substitution Subtable
- local chainlookup = chainlookups[1] -- should be i when they can be different
- if not chainlookup then
- -- we just advance
- i = i + 1 -- shouldn't that be #current
- else
+ local chainlookup = chainlookups[i]
+ if chainlookup then
local chainkind = chainlookup.type
local chainproc = chainprocs[chainkind]
if chainproc then
@@ -2583,29 +2521,18 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
-- messy since last can be changed !
if ok then
done = true
- if n and n > 1 then
- -- we have a ligature (cf the spec we advance one but we really need to test it
- -- as there are fonts out there that are fuzzy and have too many lookups:
- --
- -- U+1105 U+119E U+1105 U+119E : sourcehansansklight: script=hang ccmp=yes
- --
- if i + n > nofchainlookups then
- -- if trace_contexts then
- -- logprocess("%s: quitting lookups",cref(dataset,sequence))
- -- end
- break
- else
- -- we need to carry one
- end
+ if n and n > 1 and i + n > nofchainlookups then
+ -- this is a safeguard, we just ignore the rest of the lookups
+ break
end
end
else
-- actually an error
logprocess("%s: %s is not yet supported (2)",cref(dataset,sequence),chainkind)
end
- i = i + 1
end
- if i > nofchainlookups or not start then
+ i = i + 1
+ if i > size or not start then
break
elseif start then
start = getnext(start)
@@ -2613,6 +2540,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
end
else
+ -- todo: needs checking for holes in the replacements
local replacements = ck[7]
if replacements then
head, start, done = reversesub(head,start,last,dataset,sequence,replacements,rlmode)
@@ -3064,7 +2992,7 @@ local function c_run_single(head,font,attr,lookupcache,step,dataset,sequence,rlm
while start do
local char = ischar(start,font)
if char then
- local a = getattr(start,0)
+ local a = attr and getattr(start,0)
if not a or (a == attr) then
local lookupmatch = lookupcache[char]
if lookupmatch then
@@ -3097,7 +3025,7 @@ local function t_run_single(start,stop,font,attr,lookupcache)
while start ~= stop do
local char = ischar(start,font)
if char then
- local a = getattr(start,0)
+ local a = attr and getattr(start,0)
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
@@ -3132,7 +3060,7 @@ local function t_run_single(start,stop,font,attr,lookupcache)
end
-- local function d_run_single(prev,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
--- local a = getattr(prev,0)
+-- local a = attr and getattr(prev,0)
-- if not a or (a == attr) then
-- local char = ischar(prev) -- can be disc
-- if char then
@@ -3149,7 +3077,7 @@ end
-- end
local function k_run_single(sub,injection,last,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- local a = getattr(sub,0)
+ local a = attr and getattr(sub,0)
if not a or (a == attr) then
for n in traverse_nodes(sub) do -- only gpos
if n == last then
@@ -3181,7 +3109,7 @@ local function c_run_multiple(head,font,attr,steps,nofsteps,dataset,sequence,rlm
while start do
local char = ischar(start,font)
if char then
- local a = getattr(start,0)
+ local a = attr and getattr(start,0)
if not a or (a == attr) then
for i=1,nofsteps do
local step = steps[i]
@@ -3228,7 +3156,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
while start ~= stop do
local char = ischar(start,font)
if char then
- local a = getattr(start,0)
+ local a = attr and getattr(start,0)
if not a or (a == attr) then
for i=1,nofsteps do
local step = steps[i]
@@ -3271,7 +3199,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
end
-- local function d_run_multiple(prev,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
--- local a = getattr(prev,0)
+-- local a = attr and getattr(prev,0)
-- if not a or (a == attr) then
-- local char = ischar(prev) -- can be disc
-- if char then
@@ -3297,7 +3225,7 @@ end
-- end
local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
- local a = getattr(sub,0)
+ local a = attr and getattr(sub,0)
if not a or (a == attr) then
for n in traverse_nodes(sub) do -- only gpos
if n == last then
@@ -3394,6 +3322,14 @@ local function featuresprocessor(head,font,attr)
end
+ -- some 10% faster when no dynamics but hardly measureable on real runs .. but: it only
+ -- works when we have no other dynamics as otherwise the zero run will be applied to the
+ -- whole stream for which we then need to pass another variable which we won't
+
+ -- if attr == 0 then
+ -- attr = false
+ -- end
+
head = tonut(head)
if trace_steps then
@@ -3405,7 +3341,7 @@ local function featuresprocessor(head,font,attr)
local done = false
local datasets = otf.dataset(tfmdata,font,attr)
- local dirstack = { } -- could move outside function btu we can have local runss
+ local dirstack = { } -- could move outside function but we can have local runs
sweephead = { }
@@ -3451,7 +3387,7 @@ local function featuresprocessor(head,font,attr)
while start do
local char = ischar(start,font)
if char then
- local a = getattr(start,0)
+ local a = attr and getattr(start,0)
if not a or (a == attr) then
for i=1,nofsteps do
local step = steps[i]
@@ -3485,18 +3421,15 @@ local function featuresprocessor(head,font,attr)
local start = head -- local ?
rlmode = 0 -- to be checked ?
if nofsteps == 1 then -- happens often
-
local step = steps[1]
local lookupcache = step.coverage
if not lookupcache then
- -- can't happen, no check in loop either
report_missing_coverage(dataset,sequence)
else
-
while start do
local char, id = ischar(start,font)
if char then
- local a = getattr(start,0)
+ local a = attr and getattr(start,0)
if a then
a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
else
@@ -3553,7 +3486,7 @@ local function featuresprocessor(head,font,attr)
while start do
local char, id = ischar(start,font)
if char then
- local a = getattr(start,0)
+ local a = attr and getattr(start,0)
if a then
a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
else
@@ -3652,6 +3585,9 @@ registerotffeature {
}
}
+otf.nodemodeinitializer = featuresinitializer
+otf.featuresprocessor = featuresprocessor
+
-- This can be used for extra handlers, but should be used with care!
otf.handlers = handlers -- used in devanagari