diff options
22 files changed, 715 insertions, 1434 deletions
diff --git a/doc/context/documents/general/qrcs/setup-cs.pdf b/doc/context/documents/general/qrcs/setup-cs.pdf Binary files differindex d8f189292..169da6232 100644 --- a/doc/context/documents/general/qrcs/setup-cs.pdf +++ b/doc/context/documents/general/qrcs/setup-cs.pdf diff --git a/doc/context/documents/general/qrcs/setup-de.pdf b/doc/context/documents/general/qrcs/setup-de.pdf Binary files differindex 67380d06d..b3c94a89f 100644 --- a/doc/context/documents/general/qrcs/setup-de.pdf +++ b/doc/context/documents/general/qrcs/setup-de.pdf diff --git a/doc/context/documents/general/qrcs/setup-en.pdf b/doc/context/documents/general/qrcs/setup-en.pdf Binary files differindex 23591e183..8bb1b96fa 100644 --- a/doc/context/documents/general/qrcs/setup-en.pdf +++ b/doc/context/documents/general/qrcs/setup-en.pdf diff --git a/doc/context/documents/general/qrcs/setup-fr.pdf b/doc/context/documents/general/qrcs/setup-fr.pdf Binary files differindex 6144aafe6..e3f08dc1e 100644 --- a/doc/context/documents/general/qrcs/setup-fr.pdf +++ b/doc/context/documents/general/qrcs/setup-fr.pdf diff --git a/doc/context/documents/general/qrcs/setup-it.pdf b/doc/context/documents/general/qrcs/setup-it.pdf Binary files differindex e165fab39..1bafb0489 100644 --- a/doc/context/documents/general/qrcs/setup-it.pdf +++ b/doc/context/documents/general/qrcs/setup-it.pdf diff --git a/doc/context/documents/general/qrcs/setup-nl.pdf b/doc/context/documents/general/qrcs/setup-nl.pdf Binary files differindex 4a66ebbb4..fa6830213 100644 --- a/doc/context/documents/general/qrcs/setup-nl.pdf +++ b/doc/context/documents/general/qrcs/setup-nl.pdf diff --git a/doc/context/documents/general/qrcs/setup-ro.pdf b/doc/context/documents/general/qrcs/setup-ro.pdf Binary files differindex 930110f89..447d257b7 100644 --- a/doc/context/documents/general/qrcs/setup-ro.pdf +++ b/doc/context/documents/general/qrcs/setup-ro.pdf diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index ad39ff810..ba0e30220 100644 --- a/tex/context/base/mkii/cont-new.mkii +++ b/tex/context/base/mkii/cont-new.mkii @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2017.08.02 18:59} +\newcontextversion{2017.08.02 23:00} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii index 5bb3e1b31..1658e1e7d 100644 --- a/tex/context/base/mkii/context.mkii +++ b/tex/context/base/mkii/context.mkii @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2017.08.02 18:59} +\edef\contextversion{2017.08.02 23:00} %D For those who want to use this: diff --git a/tex/context/base/mkiv/buff-ver.mkiv b/tex/context/base/mkiv/buff-ver.mkiv index 8e76ff139..44fa72932 100644 --- a/tex/context/base/mkiv/buff-ver.mkiv +++ b/tex/context/base/mkiv/buff-ver.mkiv @@ -857,11 +857,11 @@ \begingroup \let\buff_verbatim_type_buffer_indeed\buff_verbatim_type_buffer_indeed_inline \let\setupcurrenttyping\setupcurrenttype % a terrible hack but it saves code - \let\currenttype\v!buffer + \let\currenttype\empty \dodoubleempty\buff_verbatim_type_buffer} \unexpanded\def\buff_verbatim_type_buffer_indeed_inline#1#2% category name - {\doifsomething{#1}{\edef\currenttype{#1}}% probably this line can go + {\edef\currenttype{#1}% \buff_verbatim_initialize_type_one \dostarttaggedchained\t!verbatim\currenttype\??type \clf_typebuffer diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index d5ae4be08..392f1e1fe 100644 --- a/tex/context/base/mkiv/cont-new.mkiv +++ b/tex/context/base/mkiv/cont-new.mkiv @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2017.08.02 18:59} +\newcontextversion{2017.08.02 23:00} %D This file is loaded at runtime, thereby providing an excellent place for %D hacks, patches, extensions and new features. diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index 6c8b58ee3..02ce376f2 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -41,7 +41,7 @@ %D up and the dependencies are more consistent. \edef\contextformat {\jobname} -\edef\contextversion{2017.08.02 18:59} +\edef\contextversion{2017.08.02 23:00} \edef\contextkind {beta} %D For those who want to use this: diff --git a/tex/context/base/mkiv/font-otc.lua b/tex/context/base/mkiv/font-otc.lua index 97a7ad72b..0d470c690 100644 --- a/tex/context/base/mkiv/font-otc.lua +++ b/tex/context/base/mkiv/font-otc.lua @@ -21,6 +21,9 @@ local otf = fonts.handlers.otf local registerotffeature = otf.features.register local setmetatableindex = table.setmetatableindex +local mergesteps = fonts.helpers.mergesteps +local checkflags = fonts.helpers.checkflags + local normalized = { substitution = "substitution", single = "substitution", @@ -605,6 +608,8 @@ local function addfeature(data,feature,specifications) local sublookups = specification.lookups local category = nil -- + checkflags(specification,resources) + -- if sublookups then local s = { } for i=1,#sublookups do @@ -642,7 +647,7 @@ local function addfeature(data,feature,specifications) end end -- - setmetatableindex(steps,fonts.helpers.mergesteps) -- speedup + setmetatableindex(steps,mergesteps) -- speedup -- s[i] = { [stepkey] = steps, @@ -704,7 +709,7 @@ local function addfeature(data,feature,specifications) end end -- - setmetatableindex(steps,fonts.helpers.mergesteps) -- speedup + setmetatableindex(steps,mergesteps) -- speedup -- if featureflags[1] then featureflags[1] = "mark" end if featureflags[2] then featureflags[2] = "ligature" end @@ -720,6 +725,8 @@ local function addfeature(data,feature,specifications) nofsteps = nofsteps, type = steptype, } + -- new + checkflags(sequence,resources) -- position | prepend | append local first, last = getrange(sequences,category) inject(specification,sequences,sequence,first,last,category,feature) diff --git a/tex/context/base/mkiv/font-otj.lua b/tex/context/base/mkiv/font-otj.lua index 8d95e115b..657f1a2a6 100644 --- a/tex/context/base/mkiv/font-otj.lua +++ b/tex/context/base/mkiv/font-otj.lua @@ -356,41 +356,21 @@ function injections.setkern(current,factor,rlmode,x,injection) if not injection then injection = "injections" end - if rlmode and rlmode < 0 then - -- was right kern but why ... we need to check this (kai) - if p then - local i = rawget(p,injection) - if i then - i.leftkern = dx + (i.leftkern or 0) - else - p[injection] = { - leftkern = dx, - } - end + if p then + local i = rawget(p,injection) + if i then + i.leftkern = dx + (i.leftkern or 0) else - properties[current] = { - [injection] = { - leftkern = dx, - }, + p[injection] = { + leftkern = dx, } end else - if p then - local i = rawget(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 + properties[current] = { + [injection] = { + leftkern = dx, + }, + } end return dx, nofregisteredkerns else @@ -410,40 +390,21 @@ function injections.setmove(current,factor,rlmode,x,injection) if not injection then injection = "injections" end - if rlmode and rlmode < 0 then - if p then - local i = rawget(p,injection) - if i then - i.leftkern = dx + (i.leftkern or 0) - else - p[injection] = { - leftkern = dx, - } - end + if p then + local i = rawget(p,injection) + if i then + i.leftkern = dx + (i.leftkern or 0) else - properties[current] = { - [injection] = { - leftkern = dx, - }, + p[injection] = { + leftkern = dx, } end else - if p then - local i = rawget(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 + properties[current] = { + [injection] = { + leftkern = dx, + }, + } end return dx, nofregisteredkerns else diff --git a/tex/context/base/mkiv/font-ots.lua b/tex/context/base/mkiv/font-ots.lua index 98a9184ae..e5641f5c5 100644 --- a/tex/context/base/mkiv/font-ots.lua +++ b/tex/context/base/mkiv/font-ots.lua @@ -874,7 +874,7 @@ function handlers.gpos_pair(head,start,dataset,sequence,kerns,rlmode,step,i,inje if marks[nextchar] and sequence.flags[1] then prev = snext snext = getnext(snext) --- elseif sequence.markclass and sequence.markclass[nextchar] then +-- elseif sequence.markclass and sequence.markclass[nextchar] then -- skipsome -- prev = snext -- snext = getnext(snext) else @@ -1489,7 +1489,7 @@ function chainprocs.gpos_pair(head,start,stop,dataset,sequence,currentlookup,rlm if marks[nextchar] and sequence.flags[1] then prev = snext snext = getnext(snext) --- elseif sequence.markclass and sequence.markclass[nextchar] then +-- elseif sequence.markclass and sequence.markclass[nextchar] then - skipsome -- prev = snext -- snext = getnext(snext) else @@ -1873,7 +1873,7 @@ end local noflags = { false, false, false, false } -local function chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped) +local function chainrun(head,start,last,dataset,sequence,rlmode,ck,skipsome) -- skipped) local size = ck[5] - ck[4] + 1 local chainlookups = ck[6] @@ -1922,33 +1922,20 @@ local function chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped) -- It's very unlikely that we will have skip classes here but still ... we seldom -- enter this branch anyway. - local skipmark - local skipligature - local skipbase - local markclass - if skipped then - local flags = sequence.flags or noflags - skipmark = flags[1] - skipligature = flags[2] - skipbase = flags[3] - markclass = sequence.markclass + if skipsome then + skipsome = sequence.skipsome end local i = 1 local laststart = start local nofchainlookups = #chainlookups -- useful? while start do - if skipped then -- hm, so we know we skip some + if skipsome then -- hm, so we know we skip some while start do - local char, id = ischar(start,currentfont) + local char = ischar(start,currentfont) if char then - local class = classes[char] - if class then - if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then - start = getnext(start) - else - break - end + if skipsome[char] then + start = getnext(start) else break end @@ -1971,7 +1958,7 @@ local function chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped) done = true if n and n > 1 and i + n > nofchainlookups then -- this is a safeguard, we just ignore the rest of the lookups -i = size -- prevents an advance + i = size -- prevents an advance break end end @@ -2354,505 +2341,448 @@ end -- tests because they have many steps with one context (having multiple contexts makes more sense) -- also because we (can) reduce them. -local function traditional_handle_contextchain(head,start,dataset,sequence,contexts,rlmode) - local sweepnode = sweepnode - local sweeptype = sweeptype - local currentfont = currentfont - local diskseen = false - local checkdisc = sweeptype and getprev(head) - local flags = sequence.flags or noflags - local done = false - local markclass = sequence.markclass - local skipmark = flags[1] - local skipligature = flags[2] - local skipbase = flags[3] - -- local skipsome = skipmark ~= false or skipligature ~= false or skipbase ~= false or markclass - local skipsome = flags[5] - local skipped = false - local startprev, - startnext = getboth(start) - - for k=1,#contexts do -- i've only seen ccmp having > 1 (e.g. dejavu) - local match = true - local current = start - local last = start - local ck = contexts[k] - local seq = ck[3] - local s = #seq - -- f..l = mid string - if s == 1 then - -- this seldom happens as it makes no sense (bril, ebgaramond, husayni, minion) - local char = ischar(current,currentfont) - if char and not seq[1][char] then - match = false - end - 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 - local f = ck[4] - local l = ck[5] - -- current match - -- seq[f][ischar(current,currentfont)] is not nil - if l > f then - -- before/current/after | before/current | current/after - local discfound -- = nil - local n = f + 1 - last = startnext -- 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 - if skipsome then - local class = classes[char] - 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) - end - n = n + 1 - else - if discfound then - notmatchreplace[discfound] = true - if notmatchpre[discfound] then - match = false - end - else - match = false - end - break - end - else - if seq[n][char] then - if n < l then - last = getnext(last) - end - n = n + 1 - else - if discfound then - notmatchreplace[discfound] = true - if notmatchpre[discfound] then - match = false - end - else - match = false - end - break - end - end - elseif char == false then - if discfound then - notmatchreplace[discfound] = true - if notmatchpre[discfound] then - match = false - end - 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 - if n > l then - break - end - pre = getnext(pre) - else - notmatchpre[last] = true - break - end - end - if n <= l then - notmatchpre[last] = true - end - 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 - if n > l then - break - end - replace = getnext(replace) - else - notmatchreplace[last] = true - if notmatchpre[last] then - match = false - end - break - end - end - -- why here again - if notmatchpre[last] then - match = false - end - end - -- maybe only if match - last = getnext(last) - else - match = false - break - end - else - match = false - break - end - end - end - -- before - if match and f > 1 then - if startprev then - local prev = startprev - if prev == checkdisc and (sweeptype == "pre" or sweeptype == "replace") then - prev = getprev(sweepnode) - end - if prev then - local discfound -- = nil - local n = f - 1 - while n >= 1 do - if prev then - local char, id = ischar(prev,currentfont) - if char then - if skipsome then - local class = classes[char] - 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 - prev = getprev(prev) - elseif seq[n][char] then - if n > 1 then - prev = getprev(prev) - end - n = n - 1 - else - if discfound then - notmatchreplace[discfound] = true - if notmatchpost[discfound] then - match = false - end - else - match = false - end - break - end - else - if seq[n][char] then - if n > 1 then - prev = getprev(prev) - end - n = n - 1 - else - if discfound then - notmatchreplace[discfound] = true - if notmatchpost[discfound] then - match = false - end - else - match = false - end - break - end - end - elseif char == false then - if discfound then - notmatchreplace[discfound] = true - if notmatchpost[discfound] then - match = false - end - else - match = false - end - break - elseif id == disc_code then - -- the special case: f i where i becomes dottless i .. - diskseen = true - discfound = prev - notmatchpre[prev] = true - notmatchpost[prev] = nil - notmatchreplace[prev] = nil - local pre, post, replace, pretail, posttail, replacetail = getdisc(prev,true) - if pre ~= start and post ~= start and replace ~= start then - if post then - local n = n - while posttail do - if seq[n][getchar(posttail)] then - n = n - 1 - if posttail == post then - break - else - if n < 1 then - break - end - posttail = getprev(posttail) - end - else - notmatchpost[prev] = true - break - end - end - if n >= 1 then - notmatchpost[prev] = true - end - else - notmatchpost[prev] = true - end - if replace then - -- we seldom enter this branch (e.g. on brill efficient) - while replacetail do - if seq[n][getchar(replacetail)] then - n = n - 1 - if replacetail == replace then - break - else - if n < 1 then - break - end - replacetail = getprev(replacetail) - end - else - notmatchreplace[prev] = true - if notmatchpost[prev] then - match = false - end - break - end - end - if not match then - break - end - end - end - -- maybe only if match - prev = getprev(prev) - -- elseif id == glue_code and seq[n][32] and isspace(prev,threshold,id) then - -- n = n - 1 - -- prev = getprev(prev) - elseif id == glue_code then - local sn = seq[n] - if (sn[32] and spaces[prev]) or sn[0xFFFC] then - n = n - 1 - prev = getprev(prev) - else - match = false - break - end - elseif seq[n][0xFFFC] then - n = n - 1 - prev = getprev(prev) - else - match = false - break - end - else - match = false - break - end - end - else - match = false - end - else - match = false - end - end - -- after - if match and s > l then - local current = last and getnext(last) - if not current and (sweeptype == "post" or sweeptype == "replace") then - current = getnext(sweepnode) - end - if current then - local discfound -- = nil - -- removed optimization for s-l == 1, we have to deal with marks anyway - local n = l + 1 - while n <= s do - if current then - local char, id = ischar(current,currentfont) - if char then - if skipsome then - local class = classes[char] - 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 - current = getnext(current) -- was absent - elseif seq[n][char] then - if n < s then -- new test - current = getnext(current) -- was absent - end - n = n + 1 - else - if discfound then - notmatchreplace[discfound] = true - if notmatchpre[discfound] then - match = false - end - else - match = false - end - break - end - else - if seq[n][char] then - if n < s then -- new test - current = getnext(current) -- was absent - end - n = n + 1 - else - if discfound then - notmatchreplace[discfound] = true - if notmatchpre[discfound] then - match = false - end - else - match = false - end - break - end - end - elseif char == false then - if discfound then - notmatchreplace[discfound] = true - if notmatchpre[discfound] then - match = false - end - else - match = false - end - break - elseif id == disc_code then - diskseen = true - discfound = current - notmatchpre[current] = nil - notmatchpost[current] = true - notmatchreplace[current] = nil - local pre, post, replace = getdisc(current) - if pre then - local n = n - while pre do - if seq[n][getchar(pre)] then - n = n + 1 - if n > s then - break - end - pre = getnext(pre) - else - notmatchpre[current] = true - break - end - end - if n <= s then - notmatchpre[current] = true - end - else - notmatchpre[current] = true - end - if replace then - -- so far we never entered this branch - while replace do - if seq[n][getchar(replace)] then - n = n + 1 - if n > s then - break - end - replace = getnext(replace) - else - notmatchreplace[current] = true - -- different than others, needs checking if "not" is okay - if not notmatchpre[current] then - match = false - end - break - end - end - if not match then - break - end - else - -- skip 'm - end - current = getnext(current) - -- elseif id == glue_code and seq[n][32] and isspace(current,threshold,id) then - -- n = n + 1 - -- current = getnext(current) - elseif id == glue_code then - local sn = seq[n] - if (sn[32] and spaces[current]) or sn[0xFFFC] then - n = n + 1 - current = getnext(current) - else - match = false - break - end - elseif seq[n][0xFFFC] then - n = n + 1 - current = getnext(current) - else - match = false - break - end - else - match = false - break - end - end - else - match = false - end - end - end - if match then - if trace_contexts then - chaintrac(head,start,dataset,sequence,rlmode,ck,skipped,true) - end - if diskseen or sweepnode then - head, start, done = chaindisk(head,start,dataset,sequence,rlmode,ck,skipped) - else - head, start, done = chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped) - end - if done then - break - else - -- next context - end - -- elseif trace_chains then - -- chaintrac(head,start,dataset,sequence,rlmode,ck,skipped,match) - end - end - if diskseen then - notmatchpre = { } - notmatchpost = { } - notmatchreplace = { } - end - return head, start, done -end +-- local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) +-- local sweepnode = sweepnode +-- local sweeptype = sweeptype +-- local currentfont = currentfont +-- local diskseen = false +-- local checkdisc = sweeptype and getprev(head) +-- local flags = sequence.flags or noflags +-- local done = false +-- local skipsome = sequence.skipsome +-- local skipped = false +-- local startprev, +-- startnext = getboth(start) +-- +-- for k=1,#contexts do -- i've only seen ccmp having > 1 (e.g. dejavu) +-- local match = true +-- local current = start +-- local last = start +-- local ck = contexts[k] +-- local seq = ck[3] +-- local s = #seq +-- -- f..l = mid string +-- if s == 1 then +-- -- this seldom happens as it makes no sense (bril, ebgaramond, husayni, minion) +-- local char = ischar(current,currentfont) +-- if char and not seq[1][char] then +-- match = false +-- end +-- 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 +-- local f = ck[4] +-- local l = ck[5] +-- -- current match +-- -- seq[f][ischar(current,currentfont)] is not nil +-- if l > f then +-- -- before/current/after | before/current | current/after +-- local discfound -- = nil +-- local n = f + 1 +-- last = startnext -- 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 +-- if skipsome and skipsome[char] then +-- skipped = true +-- if trace_skips then +-- show_skip(dataset,sequence,char,ck,classes[char]) +-- end +-- last = getnext(last) +-- else +-- if seq[n][char] then +-- if n < l then +-- last = getnext(last) +-- end +-- n = n + 1 +-- else +-- if discfound then +-- notmatchreplace[discfound] = true +-- if notmatchpre[discfound] then +-- match = false +-- end +-- else +-- match = false +-- end +-- break +-- end +-- end +-- elseif char == false then +-- if discfound then +-- notmatchreplace[discfound] = true +-- if notmatchpre[discfound] then +-- match = false +-- end +-- 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 +-- if n > l then +-- break +-- end +-- pre = getnext(pre) +-- else +-- notmatchpre[last] = true +-- break +-- end +-- end +-- if n <= l then +-- notmatchpre[last] = true +-- end +-- 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 +-- if n > l then +-- break +-- end +-- replace = getnext(replace) +-- else +-- notmatchreplace[last] = true +-- if notmatchpre[last] then +-- match = false +-- end +-- break +-- end +-- end +-- -- why here again +-- if notmatchpre[last] then +-- match = false +-- end +-- end +-- -- maybe only if match +-- last = getnext(last) +-- else +-- match = false +-- break +-- end +-- else +-- match = false +-- break +-- end +-- end +-- end +-- -- before +-- if match and f > 1 then +-- if startprev then +-- local prev = startprev +-- if prev == checkdisc and (sweeptype == "pre" or sweeptype == "replace") then +-- prev = getprev(sweepnode) +-- end +-- if prev then +-- local discfound -- = nil +-- local n = f - 1 +-- while n >= 1 do +-- if prev then +-- local char, id = ischar(prev,currentfont) +-- if char then +-- if skipsome and skipsome[char] then +-- skipped = true +-- if trace_skips then +-- show_skip(dataset,sequence,char,ck,classes[char]) +-- end +-- prev = getprev(prev) +-- else +-- if seq[n][char] then +-- if n > 1 then +-- prev = getprev(prev) +-- end +-- n = n - 1 +-- else +-- if discfound then +-- notmatchreplace[discfound] = true +-- if notmatchpost[discfound] then +-- match = false +-- end +-- else +-- match = false +-- end +-- break +-- end +-- end +-- elseif char == false then +-- if discfound then +-- notmatchreplace[discfound] = true +-- if notmatchpost[discfound] then +-- match = false +-- end +-- else +-- match = false +-- end +-- break +-- elseif id == disc_code then +-- -- the special case: f i where i becomes dottless i .. +-- diskseen = true +-- discfound = prev +-- notmatchpre[prev] = true +-- notmatchpost[prev] = nil +-- notmatchreplace[prev] = nil +-- local pre, post, replace, pretail, posttail, replacetail = getdisc(prev,true) +-- if pre ~= start and post ~= start and replace ~= start then +-- if post then +-- local n = n +-- while posttail do +-- if seq[n][getchar(posttail)] then +-- n = n - 1 +-- if posttail == post then +-- break +-- else +-- if n < 1 then +-- break +-- end +-- posttail = getprev(posttail) +-- end +-- else +-- notmatchpost[prev] = true +-- break +-- end +-- end +-- if n >= 1 then +-- notmatchpost[prev] = true +-- end +-- else +-- notmatchpost[prev] = true +-- end +-- if replace then +-- -- we seldom enter this branch (e.g. on brill efficient) +-- while replacetail do +-- if seq[n][getchar(replacetail)] then +-- n = n - 1 +-- if replacetail == replace then +-- break +-- else +-- if n < 1 then +-- break +-- end +-- replacetail = getprev(replacetail) +-- end +-- else +-- notmatchreplace[prev] = true +-- if notmatchpost[prev] then +-- match = false +-- end +-- break +-- end +-- end +-- if not match then +-- break +-- end +-- end +-- end +-- -- maybe only if match +-- prev = getprev(prev) +-- -- elseif id == glue_code and seq[n][32] and isspace(prev,threshold,id) then +-- -- n = n - 1 +-- -- prev = getprev(prev) +-- elseif id == glue_code then +-- local sn = seq[n] +-- if (sn[32] and spaces[prev]) or sn[0xFFFC] then +-- n = n - 1 +-- prev = getprev(prev) +-- else +-- match = false +-- break +-- end +-- elseif seq[n][0xFFFC] then +-- n = n - 1 +-- prev = getprev(prev) +-- else +-- match = false +-- break +-- end +-- else +-- match = false +-- break +-- end +-- end +-- else +-- match = false +-- end +-- else +-- match = false +-- end +-- end +-- -- after +-- if match and s > l then +-- local current = last and getnext(last) +-- if not current and (sweeptype == "post" or sweeptype == "replace") then +-- current = getnext(sweepnode) +-- end +-- if current then +-- local discfound -- = nil +-- -- removed optimization for s-l == 1, we have to deal with marks anyway +-- local n = l + 1 +-- while n <= s do +-- if current then +-- local char, id = ischar(current,currentfont) +-- if char then +-- if skipsome and skipsome[char] then +-- skipped = true +-- if trace_skips then +-- show_skip(dataset,sequence,char,ck,classes[char]) +-- end +-- current = getnext(current) -- was absent +-- else +-- if seq[n][char] then +-- if n < s then -- new test +-- current = getnext(current) -- was absent +-- end +-- n = n + 1 +-- else +-- if discfound then +-- notmatchreplace[discfound] = true +-- if notmatchpre[discfound] then +-- match = false +-- end +-- else +-- match = false +-- end +-- break +-- end +-- end +-- elseif char == false then +-- if discfound then +-- notmatchreplace[discfound] = true +-- if notmatchpre[discfound] then +-- match = false +-- end +-- else +-- match = false +-- end +-- break +-- elseif id == disc_code then +-- diskseen = true +-- discfound = current +-- notmatchpre[current] = nil +-- notmatchpost[current] = true +-- notmatchreplace[current] = nil +-- local pre, post, replace = getdisc(current) +-- if pre then +-- local n = n +-- while pre do +-- if seq[n][getchar(pre)] then +-- n = n + 1 +-- if n > s then +-- break +-- end +-- pre = getnext(pre) +-- else +-- notmatchpre[current] = true +-- break +-- end +-- end +-- if n <= s then +-- notmatchpre[current] = true +-- end +-- else +-- notmatchpre[current] = true +-- end +-- if replace then +-- -- so far we never entered this branch +-- while replace do +-- if seq[n][getchar(replace)] then +-- n = n + 1 +-- if n > s then +-- break +-- end +-- replace = getnext(replace) +-- else +-- notmatchreplace[current] = true +-- -- different than others, needs checking if "not" is okay +-- if not notmatchpre[current] then +-- match = false +-- end +-- break +-- end +-- end +-- if not match then +-- break +-- end +-- else +-- -- skip 'm +-- end +-- current = getnext(current) +-- -- elseif id == glue_code and seq[n][32] and isspace(current,threshold,id) then +-- -- n = n + 1 +-- -- current = getnext(current) +-- elseif id == glue_code then +-- local sn = seq[n] +-- if (sn[32] and spaces[current]) or sn[0xFFFC] then +-- n = n + 1 +-- current = getnext(current) +-- else +-- match = false +-- break +-- end +-- elseif seq[n][0xFFFC] then +-- n = n + 1 +-- current = getnext(current) +-- else +-- match = false +-- break +-- end +-- else +-- match = false +-- break +-- end +-- end +-- else +-- match = false +-- end +-- end +-- end +-- if match then +-- if trace_contexts then +-- chaintrac(head,start,dataset,sequence,rlmode,ck,skipped,true) +-- end +-- if diskseen or sweepnode then +-- head, start, done = chaindisk(head,start,dataset,sequence,rlmode,ck,skipped) +-- else +-- head, start, done = chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped) +-- end +-- if done then +-- break +-- else +-- -- next context +-- end +-- -- elseif trace_chains then +-- -- chaintrac(head,start,dataset,sequence,rlmode,ck,skipped,match) +-- end +-- end +-- if diskseen then +-- notmatchpre = { } +-- notmatchpost = { } +-- notmatchreplace = { } +-- end +-- return head, start, done +-- end --- only a bit faster but probably also a bit cleaner ... so ... +-- Instead of a "match" boolean variable and check for that I decided to use a "goto" with +-- "labels" instead. This is one of the cases where it makes th ecode more readable and we might +-- even gain a bit performance. -local function optimized_handle_contextchain(head,start,dataset,sequence,contexts,rlmode) +local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) -- optimizing for rlmode gains nothing local sweepnode = sweepnode local sweeptype = sweeptype @@ -2871,19 +2801,10 @@ local function optimized_handle_contextchain(head,start,dataset,sequence,context checkdisc = getprev(head) end local currentfont = currentfont - local flags = sequence.flags or noflags - local skipsome = flags[5] - local skipmark - local skipligature - local skipbase - local markclass - if skipsome then - skipmark = flags[1] - skipligature = flags[2] - skipbase = flags[3] - markclass = sequence.markclass - end + local skipped -- = false + local skipsome = sequence.skipsome + local startprev, startnext = getboth(start) local done -- = false @@ -2921,30 +2842,12 @@ local function optimized_handle_contextchain(head,start,dataset,sequence,context if last then local char, id = ischar(last,currentfont) if char then - if skipsome then - local class = classes[char] - -- if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then - if class == skipmark or (markclass and class == "mark" and not markclass[char]) or class == skipligature or class == skipbase 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) - end - n = n + 1 - elseif discfound then - notmatchreplace[discfound] = true - if notmatchpre[discfound] then - goto next - else - break - end - else - goto next + if skipsome and skipsome[char] then + skipped = true + if trace_skips then + show_skip(dataset,sequence,char,ck,classes[char]) end + last = getnext(last) elseif seq[n][char] then if n < l then last = getnext(last) @@ -3046,30 +2949,12 @@ local function optimized_handle_contextchain(head,start,dataset,sequence,context if prev then local char, id = ischar(prev,currentfont) if char then - if skipsome then - local class = classes[char] - -- if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then - if class == skipmark or (markclass and class == "mark" and not markclass[char]) or class == skipligature or class == skipbase then - skipped = true - if trace_skips then - show_skip(dataset,sequence,char,ck,class) - end - prev = getprev(prev) - elseif seq[n][char] then - if n > 1 then - prev = getprev(prev) - end - n = n - 1 - elseif discfound then - notmatchreplace[discfound] = true - if notmatchpost[discfound] then - goto next - else - break - end - else - goto next + if skipsome and skipsome[char] then + skipped = true + if trace_skips then + show_skip(dataset,sequence,char,ck,classes[char]) end + prev = getprev(prev) elseif seq[n][char] then if n > 1 then prev = getprev(prev) @@ -3190,30 +3075,12 @@ local function optimized_handle_contextchain(head,start,dataset,sequence,context if current then local char, id = ischar(current,currentfont) if char then - if skipsome then - local class = classes[char] - -- if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then - if class == skipmark or (markclass and class == "mark" and not markclass[char]) or class == skipligature or class == skipbase then - skipped = true - if trace_skips then - show_skip(dataset,sequence,char,ck,class) - end - current = getnext(current) -- was absent - elseif seq[n][char] then - if n < s then -- new test - current = getnext(current) -- was absent - end - n = n + 1 - elseif discfound then - notmatchreplace[discfound] = true - if notmatchpre[discfound] then - break - else - goto next - end - else - goto next + if skipsome and skipsome[char] then + skipped = true + if trace_skips then + show_skip(dataset,sequence,char,ck,classes[char]) end + current = getnext(current) -- was absent elseif seq[n][char] then if n < s then -- new test current = getnext(current) -- was absent @@ -3346,26 +3213,6 @@ local function optimized_handle_contextchain(head,start,dataset,sequence,context return head, start, done end ------------------------------- - -local handle_contextchain = traditional_handle_contextchain - -directives.register("otf.optimizechains",function(v) - if v then - report_chain() - report_chain("using experimental optimized code") - report_chain() - end - handle_contextchain = v and optimized_handle_contextchain or traditional_handle_contextchain - handlers.gsub_context = handle_contextchain - handlers.gsub_contextchain = handle_contextchain - handlers.gsub_reversecontextchain = handle_contextchain - handlers.gpos_contextchain = handle_contextchain - handlers.gpos_context = handle_contextchain -end) - ------------------------------- - handlers.gsub_context = handle_contextchain handlers.gsub_contextchain = handle_contextchain handlers.gsub_reversecontextchain = handle_contextchain @@ -4567,6 +4414,8 @@ do local handler = handlers[typ] -- store in dataset local steps = sequence.steps local nofsteps = sequence.nofsteps + local skipsome = sequence.skipsome + if not steps then -- this permits injection, watch the different arguments local h, d, ok = handler(head,head,dataset,sequence,nil,nil,nil,0,font,attr) @@ -4633,30 +4482,34 @@ do while start do local char, id = ischar(start,font) if char then - local lookupmatch = lookupcache[char] - if lookupmatch then - local a -- happens often so no assignment is faster - if attr then - if getattr(start,0) == attr and (not attribute or getprop(start,a_state) == attribute) then + if skipsome and skipsome[char] then + start = getnext(start) + else + local lookupmatch = lookupcache[char] + if lookupmatch then + local a -- happens often so no assignment is faster + if attr then + if getattr(start,0) == attr and (not attribute or getprop(start,a_state) == attribute) then + a = true + end + elseif not attribute or getprop(start,a_state) == attribute then a = true end - elseif not attribute or getprop(start,a_state) == attribute then - a = true - end - if a then - local ok - head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1) - if ok then - done = true - end - if start then + if a then + local ok + head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1) + if ok then + done = true + end + if start then + start = getnext(start) + end + else start = getnext(start) end else - start = getnext(start) + start = getnext(start) end - else - start = getnext(start) end elseif char == false or id == glue_code then -- a different font|state or glue (happens often) @@ -4694,39 +4547,43 @@ do if char then local m = merged[char] if m then - local a -- happens often so no assignment is faster - if attr then - if getattr(start,0) == attr and (not attribute or getprop(start,a_state) == attribute) then + if skipsome and skipsome[char] then + start = getnext(start) + else + local a -- happens often so no assignment is faster + if attr then + if getattr(start,0) == attr and (not attribute or getprop(start,a_state) == attribute) then + a = true + end + elseif not attribute or getprop(start,a_state) == attribute then a = true end - elseif not attribute or getprop(start,a_state) == attribute then - a = true - end - if a then - for i=m[1],m[2] do - local step = steps[i] - -- for i=1,#m do - -- local step = m[i] - local lookupcache = step.coverage - 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 + if a then + for i=m[1],m[2] do + local step = steps[i] + -- for i=1,#m do + -- local step = m[i] + local lookupcache = step.coverage + 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 end - end - if start then + if start then + start = getnext(start) + end + else start = getnext(start) end - else - start = getnext(start) end else start = getnext(start) diff --git a/tex/context/base/mkiv/font-oup.lua b/tex/context/base/mkiv/font-oup.lua index ce1dca724..3b86cde72 100644 --- a/tex/context/base/mkiv/font-oup.lua +++ b/tex/context/base/mkiv/font-oup.lua @@ -2146,6 +2146,9 @@ local function mergesteps_1(lookup,strict) end local function mergesteps_2(lookup,strict) -- pairs + -- this can be tricky as we can have a match on a mark with no marks skip flag + -- in which case with multiple steps a hit can prevent a next step while in the + -- merged case we can hit differently (a messy font then anyway) local steps = lookup.steps local nofsteps = lookup.nofsteps local first = steps[1] @@ -2494,8 +2497,30 @@ local function mergesteps(t,k) end end +local function checkflags(sequence,resources) + if not sequence.skipsome then + local flags = sequence.flags + if flags then + local skipmark = flags[1] + local skipligature = flags[2] + local skipbase = flags[3] + local markclass = sequence.markclass + local skipsome = skipmark or skipligature or skipbase or markclass or false + if skipsome then + sequence.skipsome = setmetatableindex(function(t,k) + local c = resources.classes[k] -- delayed table + local v = c == skipmark or (markclass and c == "mark" and not markclass[k]) or c == skipligature or c == skipbase + t[k] = v or false + return v + end) + end + end + end +end + if fonts.helpers then fonts.helpers.mergesteps = mergesteps + fonts.helpers.checkflags = checkflags end function readers.expand(data) @@ -2565,14 +2590,9 @@ function readers.expand(data) sequence.markclass = markclasses[markclass] end end - local flags = sequence.flags - if flags then - flags[5] = flags[1] ~= false -- otherwise "mark" - or flags[2] ~= false -- otherwise "base" - or flags[3] ~= false -- otherwise "ligature" - or sequence.markclass - or false - end + + checkflags(sequence,resources) + for i=1,nofsteps do local step = steps[i] local baseclasses = step.baseclasses diff --git a/tex/context/base/mkiv/node-nut.lua b/tex/context/base/mkiv/node-nut.lua index bbb629cd9..651717c68 100644 --- a/tex/context/base/mkiv/node-nut.lua +++ b/tex/context/base/mkiv/node-nut.lua @@ -950,6 +950,7 @@ end if LUATEXFUNCTIONALITY < 6384 then local getfield = nuts.getfield + local setfield = nuts.setfield function nuts.getboxglue(n,glue_set,glue_order,glue_sign) return diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf Binary files differindex c210fae43..68c55f340 100644 --- a/tex/context/base/mkiv/status-files.pdf +++ b/tex/context/base/mkiv/status-files.pdf diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf Binary files differindex cebe52549..033f44b3d 100644 --- a/tex/context/base/mkiv/status-lua.pdf +++ b/tex/context/base/mkiv/status-lua.pdf diff --git a/tex/context/interface/mkiv/i-context.pdf b/tex/context/interface/mkiv/i-context.pdf Binary files differindex 23591e183..8bb1b96fa 100644 --- a/tex/context/interface/mkiv/i-context.pdf +++ b/tex/context/interface/mkiv/i-context.pdf diff --git a/tex/context/interface/mkiv/i-readme.pdf b/tex/context/interface/mkiv/i-readme.pdf Binary files differindex e3e3d744e..96dbf5240 100644 --- a/tex/context/interface/mkiv/i-readme.pdf +++ b/tex/context/interface/mkiv/i-readme.pdf diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index 73f68128e..7c929867f 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua -- parent file : c:/data/develop/context/sources/luatex-fonts.lua --- merge date : 08/02/17 18:59:29 +-- merge date : 08/02/17 23:00:11 do -- begin closure to overcome local limits and interference @@ -19160,7 +19160,7 @@ local function mergesteps_1(lookup,strict) lookup.steps={ first } return nofsteps-1 end -local function mergesteps_2(lookup,strict) +local function mergesteps_2(lookup,strict) local steps=lookup.steps local nofsteps=lookup.nofsteps local first=steps[1] @@ -19469,8 +19469,29 @@ local function mergesteps(t,k) return merged end end +local function checkflags(sequence,resources) + if not sequence.skipsome then + local flags=sequence.flags + if flags then + local skipmark=flags[1] + local skipligature=flags[2] + local skipbase=flags[3] + local markclass=sequence.markclass + local skipsome=skipmark or skipligature or skipbase or markclass or false + if skipsome then + sequence.skipsome=setmetatableindex(function(t,k) + local c=resources.classes[k] + local v=c==skipmark or (markclass and c=="mark" and not markclass[k]) or c==skipligature or c==skipbase + t[k]=v or false + return v + end) + end + end + end +end if fonts.helpers then fonts.helpers.mergesteps=mergesteps + fonts.helpers.checkflags=checkflags end function readers.expand(data) if not data or data.expanded then @@ -19528,14 +19549,7 @@ function readers.expand(data) sequence.markclass=markclasses[markclass] end end - local flags=sequence.flags - if flags then - flags[5]=flags[1]~=false - or flags[2]~=false - or flags[3]~=false - or sequence.markclass - or false - end + checkflags(sequence,resources) for i=1,nofsteps do local step=steps[i] local baseclasses=step.baseclasses @@ -21024,40 +21038,21 @@ function injections.setkern(current,factor,rlmode,x,injection) if not injection then injection="injections" end - if rlmode and rlmode<0 then - if p then - local i=rawget(p,injection) - if i then - i.leftkern=dx+(i.leftkern or 0) - else - p[injection]={ - leftkern=dx, - } - end + if p then + local i=rawget(p,injection) + if i then + i.leftkern=dx+(i.leftkern or 0) else - properties[current]={ - [injection]={ - leftkern=dx, - }, + p[injection]={ + leftkern=dx, } end else - if p then - local i=rawget(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 + properties[current]={ + [injection]={ + leftkern=dx, + }, + } end return dx,nofregisteredkerns else @@ -21072,40 +21067,21 @@ function injections.setmove(current,factor,rlmode,x,injection) if not injection then injection="injections" end - if rlmode and rlmode<0 then - if p then - local i=rawget(p,injection) - if i then - i.leftkern=dx+(i.leftkern or 0) - else - p[injection]={ - leftkern=dx, - } - end + if p then + local i=rawget(p,injection) + if i then + i.leftkern=dx+(i.leftkern or 0) else - properties[current]={ - [injection]={ - leftkern=dx, - }, + p[injection]={ + leftkern=dx, } end else - if p then - local i=rawget(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 + properties[current]={ + [injection]={ + leftkern=dx, + }, + } end return dx,nofregisteredkerns else @@ -24057,7 +24033,7 @@ local function setdiscchecked(d,pre,post,replace) setdisc(d,pre,post,replace) end local noflags={ false,false,false,false } -local function chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped) +local function chainrun(head,start,last,dataset,sequence,rlmode,ck,skipsome) local size=ck[5]-ck[4]+1 local chainlookups=ck[6] local done=false @@ -24079,32 +24055,19 @@ local function chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped) end end else - local skipmark - local skipligature - local skipbase - local markclass - if skipped then - local flags=sequence.flags or noflags - skipmark=flags[1] - skipligature=flags[2] - skipbase=flags[3] - markclass=sequence.markclass + if skipsome then + skipsome=sequence.skipsome end local i=1 local laststart=start local nofchainlookups=#chainlookups while start do - if skipped then + if skipsome then while start do - local char,id=ischar(start,currentfont) + local char=ischar(start,currentfont) if char then - local class=classes[char] - if class then - if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then - start=getnext(start) - else - break - end + if skipsome[char] then + start=getnext(start) else break end @@ -24125,7 +24088,7 @@ local function chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped) if ok then done=true if n and n>1 and i+n>nofchainlookups then -i=size + i=size break end end @@ -24474,472 +24437,7 @@ local function chaintrac(head,start,dataset,sequence,rlmode,ck,skipped,match) logwarning("%s: rule %s %s at char %s for (%s,%s,%s) chars, lookuptype %a", cref(dataset,sequence),rule,match and "matches" or "nomatch",gref(char),first-1,last-first+1,nofseq-last,lookuptype) end -local function traditional_handle_contextchain(head,start,dataset,sequence,contexts,rlmode) - local sweepnode=sweepnode - local sweeptype=sweeptype - local currentfont=currentfont - local diskseen=false - local checkdisc=sweeptype and getprev(head) - local flags=sequence.flags or noflags - local done=false - local markclass=sequence.markclass - local skipmark=flags[1] - local skipligature=flags[2] - local skipbase=flags[3] - local skipsome=flags[5] - local skipped=false - local startprev, - startnext=getboth(start) - for k=1,#contexts do - local match=true - local current=start - local last=start - local ck=contexts[k] - local seq=ck[3] - local s=#seq - if s==1 then - local char=ischar(current,currentfont) - if char and not seq[1][char] then - match=false - end - else - local f=ck[4] - local l=ck[5] - if l>f then - local discfound - local n=f+1 - last=startnext - 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 - if skipsome then - local class=classes[char] - 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) - end - n=n+1 - else - if discfound then - notmatchreplace[discfound]=true - if notmatchpre[discfound] then - match=false - end - else - match=false - end - break - end - else - if seq[n][char] then - if n<l then - last=getnext(last) - end - n=n+1 - else - if discfound then - notmatchreplace[discfound]=true - if notmatchpre[discfound] then - match=false - end - else - match=false - end - break - end - end - elseif char==false then - if discfound then - notmatchreplace[discfound]=true - if notmatchpre[discfound] then - match=false - end - 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 - if n>l then - break - end - pre=getnext(pre) - else - notmatchpre[last]=true - break - end - end - if n<=l then - notmatchpre[last]=true - end - else - notmatchpre[last]=true - end - if replace then - while replace do - if seq[n][getchar(replace)] then - n=n+1 - if n>l then - break - end - replace=getnext(replace) - else - notmatchreplace[last]=true - if notmatchpre[last] then - match=false - end - break - end - end - if notmatchpre[last] then - match=false - end - end - last=getnext(last) - else - match=false - break - end - else - match=false - break - end - end - end - if match and f>1 then - if startprev then - local prev=startprev - if prev==checkdisc and (sweeptype=="pre" or sweeptype=="replace") then - prev=getprev(sweepnode) - end - if prev then - local discfound - local n=f-1 - while n>=1 do - if prev then - local char,id=ischar(prev,currentfont) - if char then - if skipsome then - local class=classes[char] - 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 - prev=getprev(prev) - elseif seq[n][char] then - if n>1 then - prev=getprev(prev) - end - n=n-1 - else - if discfound then - notmatchreplace[discfound]=true - if notmatchpost[discfound] then - match=false - end - else - match=false - end - break - end - else - if seq[n][char] then - if n>1 then - prev=getprev(prev) - end - n=n-1 - else - if discfound then - notmatchreplace[discfound]=true - if notmatchpost[discfound] then - match=false - end - else - match=false - end - break - end - end - elseif char==false then - if discfound then - notmatchreplace[discfound]=true - if notmatchpost[discfound] then - match=false - end - else - match=false - end - break - elseif id==disc_code then - diskseen=true - discfound=prev - notmatchpre[prev]=true - notmatchpost[prev]=nil - notmatchreplace[prev]=nil - local pre,post,replace,pretail,posttail,replacetail=getdisc(prev,true) - if pre~=start and post~=start and replace~=start then - if post then - local n=n - while posttail do - if seq[n][getchar(posttail)] then - n=n-1 - if posttail==post then - break - else - if n<1 then - break - end - posttail=getprev(posttail) - end - else - notmatchpost[prev]=true - break - end - end - if n>=1 then - notmatchpost[prev]=true - end - else - notmatchpost[prev]=true - end - if replace then - while replacetail do - if seq[n][getchar(replacetail)] then - n=n-1 - if replacetail==replace then - break - else - if n<1 then - break - end - replacetail=getprev(replacetail) - end - else - notmatchreplace[prev]=true - if notmatchpost[prev] then - match=false - end - break - end - end - if not match then - break - end - end - end - prev=getprev(prev) - elseif id==glue_code then - local sn=seq[n] - if (sn[32] and spaces[prev]) or sn[0xFFFC] then - n=n-1 - prev=getprev(prev) - else - match=false - break - end - elseif seq[n][0xFFFC] then - n=n-1 - prev=getprev(prev) - else - match=false - break - end - else - match=false - break - end - end - else - match=false - end - else - match=false - end - end - if match and s>l then - local current=last and getnext(last) - if not current and (sweeptype=="post" or sweeptype=="replace") then - current=getnext(sweepnode) - end - if current then - local discfound - local n=l+1 - while n<=s do - if current then - local char,id=ischar(current,currentfont) - if char then - if skipsome then - local class=classes[char] - 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 - current=getnext(current) - elseif seq[n][char] then - if n<s then - current=getnext(current) - end - n=n+1 - else - if discfound then - notmatchreplace[discfound]=true - if notmatchpre[discfound] then - match=false - end - else - match=false - end - break - end - else - if seq[n][char] then - if n<s then - current=getnext(current) - end - n=n+1 - else - if discfound then - notmatchreplace[discfound]=true - if notmatchpre[discfound] then - match=false - end - else - match=false - end - break - end - end - elseif char==false then - if discfound then - notmatchreplace[discfound]=true - if notmatchpre[discfound] then - match=false - end - else - match=false - end - break - elseif id==disc_code then - diskseen=true - discfound=current - notmatchpre[current]=nil - notmatchpost[current]=true - notmatchreplace[current]=nil - local pre,post,replace=getdisc(current) - if pre then - local n=n - while pre do - if seq[n][getchar(pre)] then - n=n+1 - if n>s then - break - end - pre=getnext(pre) - else - notmatchpre[current]=true - break - end - end - if n<=s then - notmatchpre[current]=true - end - else - notmatchpre[current]=true - end - if replace then - while replace do - if seq[n][getchar(replace)] then - n=n+1 - if n>s then - break - end - replace=getnext(replace) - else - notmatchreplace[current]=true - if not notmatchpre[current] then - match=false - end - break - end - end - if not match then - break - end - else - end - current=getnext(current) - elseif id==glue_code then - local sn=seq[n] - if (sn[32] and spaces[current]) or sn[0xFFFC] then - n=n+1 - current=getnext(current) - else - match=false - break - end - elseif seq[n][0xFFFC] then - n=n+1 - current=getnext(current) - else - match=false - break - end - else - match=false - break - end - end - else - match=false - end - end - end - if match then - if trace_contexts then - chaintrac(head,start,dataset,sequence,rlmode,ck,skipped,true) - end - if diskseen or sweepnode then - head,start,done=chaindisk(head,start,dataset,sequence,rlmode,ck,skipped) - else - head,start,done=chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped) - end - if done then - break - else - end - end - end - if diskseen then - notmatchpre={} - notmatchpost={} - notmatchreplace={} - end - return head,start,done -end -local function optimized_handle_contextchain(head,start,dataset,sequence,contexts,rlmode) +local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) local sweepnode=sweepnode local sweeptype=sweeptype local postreplace @@ -24957,19 +24455,8 @@ local function optimized_handle_contextchain(head,start,dataset,sequence,context checkdisc=getprev(head) end local currentfont=currentfont - local flags=sequence.flags or noflags - local skipsome=flags[5] - local skipmark - local skipligature - local skipbase - local markclass - if skipsome then - skipmark=flags[1] - skipligature=flags[2] - skipbase=flags[3] - markclass=sequence.markclass - end local skipped + local skipsome=sequence.skipsome local startprev, startnext=getboth(start) local done @@ -24999,29 +24486,12 @@ local function optimized_handle_contextchain(head,start,dataset,sequence,context if last then local char,id=ischar(last,currentfont) if char then - if skipsome then - local class=classes[char] - if class==skipmark or (markclass and class=="mark" and not markclass[char]) or class==skipligature or class==skipbase 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) - end - n=n+1 - elseif discfound then - notmatchreplace[discfound]=true - if notmatchpre[discfound] then - goto next - else - break - end - else - goto next + if skipsome and skipsome[char] then + skipped=true + if trace_skips then + show_skip(dataset,sequence,char,ck,classes[char]) end + last=getnext(last) elseif seq[n][char] then if n<l then last=getnext(last) @@ -25118,29 +24588,12 @@ local function optimized_handle_contextchain(head,start,dataset,sequence,context if prev then local char,id=ischar(prev,currentfont) if char then - if skipsome then - local class=classes[char] - if class==skipmark or (markclass and class=="mark" and not markclass[char]) or class==skipligature or class==skipbase then - skipped=true - if trace_skips then - show_skip(dataset,sequence,char,ck,class) - end - prev=getprev(prev) - elseif seq[n][char] then - if n>1 then - prev=getprev(prev) - end - n=n-1 - elseif discfound then - notmatchreplace[discfound]=true - if notmatchpost[discfound] then - goto next - else - break - end - else - goto next + if skipsome and skipsome[char] then + skipped=true + if trace_skips then + show_skip(dataset,sequence,char,ck,classes[char]) end + prev=getprev(prev) elseif seq[n][char] then if n>1 then prev=getprev(prev) @@ -25253,29 +24706,12 @@ local function optimized_handle_contextchain(head,start,dataset,sequence,context if current then local char,id=ischar(current,currentfont) if char then - if skipsome then - local class=classes[char] - if class==skipmark or (markclass and class=="mark" and not markclass[char]) or class==skipligature or class==skipbase then - skipped=true - if trace_skips then - show_skip(dataset,sequence,char,ck,class) - end - current=getnext(current) - elseif seq[n][char] then - if n<s then - current=getnext(current) - end - n=n+1 - elseif discfound then - notmatchreplace[discfound]=true - if notmatchpre[discfound] then - break - else - goto next - end - else - goto next + if skipsome and skipsome[char] then + skipped=true + if trace_skips then + show_skip(dataset,sequence,char,ck,classes[char]) end + current=getnext(current) elseif seq[n][char] then if n<s then current=getnext(current) @@ -25394,20 +24830,6 @@ local function optimized_handle_contextchain(head,start,dataset,sequence,context end return head,start,done end -local handle_contextchain=traditional_handle_contextchain -directives.register("otf.optimizechains",function(v) - if v then - report_chain() - report_chain("using experimental optimized code") - report_chain() - end - handle_contextchain=v and optimized_handle_contextchain or traditional_handle_contextchain - handlers.gsub_context=handle_contextchain - handlers.gsub_contextchain=handle_contextchain - handlers.gsub_reversecontextchain=handle_contextchain - handlers.gpos_contextchain=handle_contextchain - handlers.gpos_context=handle_contextchain -end) handlers.gsub_context=handle_contextchain handlers.gsub_contextchain=handle_contextchain handlers.gsub_reversecontextchain=handle_contextchain @@ -26125,6 +25547,7 @@ do local handler=handlers[typ] local steps=sequence.steps local nofsteps=sequence.nofsteps + local skipsome=sequence.skipsome if not steps then local h,d,ok=handler(head,head,dataset,sequence,nil,nil,nil,0,font,attr) if ok then @@ -26182,30 +25605,34 @@ do while start do local char,id=ischar(start,font) if char then - local lookupmatch=lookupcache[char] - if lookupmatch then - local a - if attr then - if getattr(start,0)==attr and (not attribute or getprop(start,a_state)==attribute) then + if skipsome and skipsome[char] then + start=getnext(start) + else + local lookupmatch=lookupcache[char] + if lookupmatch then + local a + if attr then + if getattr(start,0)==attr and (not attribute or getprop(start,a_state)==attribute) then + a=true + end + elseif not attribute or getprop(start,a_state)==attribute then a=true end - elseif not attribute or getprop(start,a_state)==attribute then - a=true - end - if a then - local ok - head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1) - if ok then - done=true - end - if start then + if a then + local ok + head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1) + if ok then + done=true + end + if start then + start=getnext(start) + end + else start=getnext(start) end else start=getnext(start) end - else - start=getnext(start) end elseif char==false or id==glue_code then start=getnext(start) @@ -26242,35 +25669,39 @@ do if char then local m=merged[char] if m then - local a - if attr then - if getattr(start,0)==attr and (not attribute or getprop(start,a_state)==attribute) then + if skipsome and skipsome[char] then + start=getnext(start) + else + local a + if attr then + if getattr(start,0)==attr and (not attribute or getprop(start,a_state)==attribute) then + a=true + end + elseif not attribute or getprop(start,a_state)==attribute then a=true end - elseif not attribute or getprop(start,a_state)==attribute then - a=true - end - if a then - for i=m[1],m[2] do - local step=steps[i] - local lookupcache=step.coverage - local lookupmatch=lookupcache[char] - if lookupmatch then - local ok - head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i) - if ok then - done=true - break - elseif not start then - break + if a then + for i=m[1],m[2] do + local step=steps[i] + local lookupcache=step.coverage + local lookupmatch=lookupcache[char] + if lookupmatch then + local ok + head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i) + if ok then + done=true + break + elseif not start then + break + end end end - end - if start then + if start then + start=getnext(start) + end + else start=getnext(start) end - else - start=getnext(start) end else start=getnext(start) @@ -29028,6 +28459,8 @@ local fonts=fonts local otf=fonts.handlers.otf local registerotffeature=otf.features.register local setmetatableindex=table.setmetatableindex +local mergesteps=fonts.helpers.mergesteps +local checkflags=fonts.helpers.checkflags local normalized={ substitution="substitution", single="substitution", @@ -29566,6 +28999,7 @@ local function addfeature(data,feature,specifications) local steps={} local sublookups=specification.lookups local category=nil + checkflags(specification,resources) if sublookups then local s={} for i=1,#sublookups do @@ -29602,7 +29036,7 @@ local function addfeature(data,feature,specifications) steps[nofsteps]=register(coverage,featuretype,format,feature,nofsteps,descriptions,resources) end end - setmetatableindex(steps,fonts.helpers.mergesteps) + setmetatableindex(steps,mergesteps) s[i]={ [stepkey]=steps, nofsteps=nofsteps, @@ -29661,7 +29095,7 @@ local function addfeature(data,feature,specifications) askedfeatures[k]=tohash(v) end end - setmetatableindex(steps,fonts.helpers.mergesteps) + setmetatableindex(steps,mergesteps) if featureflags[1] then featureflags[1]="mark" end if featureflags[2] then featureflags[2]="ligature" end if featureflags[3] then featureflags[3]="base" end @@ -29676,6 +29110,7 @@ local function addfeature(data,feature,specifications) nofsteps=nofsteps, type=steptype, } + checkflags(sequence,resources) local first,last=getrange(sequences,category) inject(specification,sequences,sequence,first,last,category,feature) local features=fontfeatures[category] |