From 87d82131e6359a9bb3fb4e85e2f26f6864de8ac9 Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Fri, 30 Jun 2017 20:42:23 +0200 Subject: 2017-06-30 19:51:00 --- tex/context/base/mkii/cont-new.mkii | 2 +- tex/context/base/mkii/context.mkii | 2 +- tex/context/base/mkii/mult-nl.mkii | 1 + tex/context/base/mkiv/buff-ini.lua | 2 +- tex/context/base/mkiv/char-utf.lua | 6 +- tex/context/base/mkiv/cont-new.mkiv | 2 +- tex/context/base/mkiv/context.mkiv | 2 +- tex/context/base/mkiv/font-con.lua | 32 +- tex/context/base/mkiv/font-onr.lua | 2 +- tex/context/base/mkiv/font-otd.lua | 8 +- tex/context/base/mkiv/font-ots.lua | 1085 +++++++++++++++++--- tex/context/base/mkiv/font-oup.lua | 38 +- tex/context/base/mkiv/l-string.lua | 2 +- tex/context/base/mkiv/math-fbk.lua | 8 +- tex/context/base/mkiv/status-files.pdf | Bin 25704 -> 25684 bytes tex/context/base/mkiv/status-lua.pdf | Bin 425160 -> 425157 bytes tex/context/base/mkiv/util-deb.lua | 25 +- tex/context/interface/mkii/keys-nl.xml | 1 + tex/context/interface/mkiv/i-context.pdf | Bin 847900 -> 847911 bytes tex/context/interface/mkiv/i-readme.pdf | Bin 60775 -> 60774 bytes tex/context/modules/mkiv/x-asciimath.lua | 2 +- tex/context/modules/mkiv/x-ldx.lua | 2 +- tex/generic/context/luatex/luatex-fonts-merged.lua | 298 +++--- 23 files changed, 1203 insertions(+), 317 deletions(-) (limited to 'tex') diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index 5a0456528..7bfcf8614 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.06.29 09:34} +\newcontextversion{2017.06.30 19:45} %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 5b82f4d36..48ef7f4cd 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.06.29 09:34} +\edef\contextversion{2017.06.30 19:45} %D For those who want to use this: diff --git a/tex/context/base/mkii/mult-nl.mkii b/tex/context/base/mkii/mult-nl.mkii index 30703e4a6..8e5add4dc 100644 --- a/tex/context/base/mkii/mult-nl.mkii +++ b/tex/context/base/mkii/mult-nl.mkii @@ -687,6 +687,7 @@ \setinterfaceconstant{bottomoffset}{onderoffset} \setinterfaceconstant{bottomspace}{bodemwit} \setinterfaceconstant{bottomstate}{onderstatus} +\setinterfaceconstant{break}{break} \setinterfaceconstant{buffer}{buffer} \setinterfaceconstant{cache}{cache} \setinterfaceconstant{calculate}{bereken} diff --git a/tex/context/base/mkiv/buff-ini.lua b/tex/context/base/mkiv/buff-ini.lua index fd5b047af..e2f0be0dc 100644 --- a/tex/context/base/mkiv/buff-ini.lua +++ b/tex/context/base/mkiv/buff-ini.lua @@ -286,7 +286,7 @@ local getmargin = (emptyline + normalline)^1 local function undent(str) -- new version, needs testing: todo: not always needed, like in xtables nofspaces = #str local margin = lpegmatch(getmargin,str) - if nofspaces == #str or nofspaces ==0 then + if nofspaces == #str or nofspaces == 0 then return str end local stripper = strippers[nofspaces] diff --git a/tex/context/base/mkiv/char-utf.lua b/tex/context/base/mkiv/char-utf.lua index 5b677dbac..901beef6d 100644 --- a/tex/context/base/mkiv/char-utf.lua +++ b/tex/context/base/mkiv/char-utf.lua @@ -191,7 +191,7 @@ function utffilters.collapse(str,filename) if not p_collapse then prepare() end - if not str or #str == "" or #str == 1 then + if not str or str == "" or #str == 1 then return str elseif filename and skippable[filesuffix(filename)] then -- we could hash the collapsables or do a quicker test return str @@ -214,7 +214,7 @@ function utffilters.decompose(str,filename) -- 3 to 4 times faster than the abov if str and str ~= "" and #str > 1 then return lpegmatch(p_decompose,str) end - if not str or #str == "" or #str < 2 then + if not str or str == "" or #str < 2 then return str elseif filename and skippable[filesuffix(filename)] then return str @@ -339,7 +339,7 @@ function utffilters.reorder(str,filename) if not p_reorder then prepare() end - if not str or #str == "" or #str < 2 then + if not str or str == "" or #str < 2 then return str elseif filename and skippable[filesuffix(filename)] then return str diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index af97f8b50..82888546f 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.06.29 09:34} +\newcontextversion{2017.06.30 19:45} %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 7a2a20e46..73069d51a 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.06.29 09:34} +\edef\contextversion{2017.06.30 19:45} \edef\contextkind {beta} %D For those who want to use this: diff --git a/tex/context/base/mkiv/font-con.lua b/tex/context/base/mkiv/font-con.lua index 16dc3c05e..fd3b28612 100644 --- a/tex/context/base/mkiv/font-con.lua +++ b/tex/context/base/mkiv/font-con.lua @@ -555,22 +555,22 @@ function constructors.scale(tfmdata,specification) if changed then local c = changed[unicode] if c and c ~= unicode then - while true do - local cc = changed[c] - if not cc then - -- we're done, no (futher) chain - break - elseif cc == unicode then - -- we probably have a bidi swap - break - elseif cc == c then - -- we have a self reference, shouldn't happen - c = nil - break - else - c = cc - end - end +-- while true do +-- local cc = changed[c] +-- if not cc then +-- -- we're done, no (futher) chain +-- break +-- elseif cc == unicode then +-- -- we probably have a bidi swap +-- break +-- elseif cc == c then +-- -- we have a self reference, shouldn't happen +-- c = nil +-- break +-- else +-- c = cc +-- end +-- end if c then description = descriptions[c] or descriptions[unicode] or character character = characters[c] or character diff --git a/tex/context/base/mkiv/font-onr.lua b/tex/context/base/mkiv/font-onr.lua index 9a45d4b73..f1cdefa1b 100644 --- a/tex/context/base/mkiv/font-onr.lua +++ b/tex/context/base/mkiv/font-onr.lua @@ -41,7 +41,7 @@ handlers.afm = afm local readers = afm.readers or { } afm.readers = readers -afm.version = 1.512 -- incrementing this number one up will force a re-cache +afm.version = 1.513 -- incrementing this number one up will force a re-cache --[[ldx--

We start with the basic reader which we give a name similar to the built in diff --git a/tex/context/base/mkiv/font-otd.lua b/tex/context/base/mkiv/font-otd.lua index 412aad528..c45278826 100644 --- a/tex/context/base/mkiv/font-otd.lua +++ b/tex/context/base/mkiv/font-otd.lua @@ -192,15 +192,15 @@ local function initialize(sequence,script,language,s_enabled,a_enabled,font,attr elseif lookupdone then if trace_applied then report_process( - "font %s, dynamic %a (%a), feature %a, script %a, language %a, lookup %a, value %a, lookup already set by %a", - font,attr or 0,dynamic,kind,usedscript,usedlanguage,sequence.name,valid,ra[#ra][4]) + "font %s, dynamic %a (%a), feature %a, script %a, language %a, lookup %a, value %a, nofsteps %a, lookup already set by %a", + font,attr or 0,dynamic,kind,usedscript,usedlanguage,sequence.name,valid,sequence.nofsteps,ra[#ra][4]) end else ra[#ra+1] = usedlookup if trace_applied then report_process( - "font %s, dynamic %a (%a), feature %a, script %a, language %a, lookup %a, value %a", - font,attr or 0,dynamic,kind,usedscript,usedlanguage,sequence.name,valid) + "font %s, dynamic %a (%a), feature %a, script %a, language %a, lookup %a, value %a, nofsteps %a", + font,attr or 0,dynamic,kind,usedscript,usedlanguage,sequence.name,valid,sequence.nofsteps) else return -- no need to look further end diff --git a/tex/context/base/mkiv/font-ots.lua b/tex/context/base/mkiv/font-ots.lua index de296e408..c5fa13abe 100644 --- a/tex/context/base/mkiv/font-ots.lua +++ b/tex/context/base/mkiv/font-ots.lua @@ -267,13 +267,11 @@ local threshold = 0 local checkmarks = false local sweepnode = nil -local sweepprev = nil -local sweepnext = nil -local sweephead = { } +local sweephead = { } -- we don't nil entries but false them (no collection and such) -local notmatchpre = { } -local notmatchpost = { } -local notmatchreplace = { } +local notmatchpre = { } -- to be checked: can we use false instead of nil / what if a == b tests +local notmatchpost = { } -- to be checked: can we use false instead of nil / what if a == b tests +local notmatchreplace = { } -- to be checked: can we use false instead of nil / what if a == b tests local handlers = { } @@ -1756,12 +1754,12 @@ end -- but it takes a bit of work to figure out an efficient way (this is what the sweep* -- names refer to). I might look into that variant one day again as it can replace -- some other code too. In that approach we can have a special version for gub and pos --- which gains some speed. This method does the test and passes info to the handlers --- (sweepnode, sweepmode, sweepprev, sweepnext, etc). Here collapsing is handled in the --- main loop which also makes code elsewhere simpler (i.e. no need for the other special --- runners and disc code in ligature building). I also experimented with pushing preceding --- glyphs sequences in the replace/pre fields beforehand which saves checking afterwards --- but at the cost of duplicate glyphs (memory) but it's too much overhead (runtime). +-- which gains some speed. This method does the test and passes info to the handlers. +-- Here collapsing is handled in the main loop which also makes code elsewhere simpler +-- (i.e. no need for the other special runners and disc code in ligature building). I +-- also experimented with pushing preceding glyphs sequences in the replace/pre fields +-- beforehand which saves checking afterwards but at the cost of duplicate glyphs +-- (memory) but it's too much overhead (runtime). -- -- In the meantime Kai had moved the code from the single chain into a more general handler -- and this one (renamed to chaindisk) is used now. I optimized the code a bit and brought @@ -2189,8 +2187,8 @@ local function chaindisk(head,start,dataset,sequence,rlmode,ck,skipped) setdisc(lookaheaddisc,cf,post,new) end start = getprev(lookaheaddisc) - sweephead[cf] = getnext(clast) - sweephead[new] = getnext(cl) + sweephead[cf] = getnext(clast) or false + sweephead[new] = getnext(cl) or false elseif backtrackdisc then @@ -2255,8 +2253,8 @@ local function chaindisk(head,start,dataset,sequence,rlmode,ck,skipped) setdisc(backtrackdisc,pre,post,replace) end start = getprev(backtrackdisc) - sweephead[post] = getnext(clast) - sweephead[replace] = getnext(last) + sweephead[post] = getnext(clast) or false + sweephead[replace] = getnext(last) or false else @@ -2282,6 +2280,471 @@ local function chaintrac(head,start,dataset,sequence,rlmode,ck,skipped,match) cref(dataset,sequence),rule,match and "matches" or "nomatch",gref(char),first-1,last-first+1,nofseq-last,lookuptype) 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 skipmark = flags[1] +-- local skipligature = flags[2] +-- local skipbase = flags[3] +-- local markclass = sequence.markclass +-- 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 +-- local size = 1 +-- -- 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 then +-- if not seq[1][char] then +-- match = false +-- end +-- 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 +-- 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) +-- 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 +-- 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 +-- 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 +-- -- can this happen +-- if discfound then +-- notmatchreplace[discfound] = true +-- if notmatchpre[discfound] then +-- match = false +-- end +-- else +-- match = false +-- end +-- break +-- 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 +-- pre = getnext(pre) +-- if n > l then +-- break +-- end +-- 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 +-- replace = getnext(replace) +-- if n > l then +-- break +-- end +-- 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 +-- -- local prev = getprev(start) +-- -- if prev then +-- if startprev then +-- local prev = startprev +-- if prev == checkdisc and (sweeptype == "pre" or sweeptype == "replace") then +-- prev = getprev(sweepnode) +-- -- sweeptype = nil +-- 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 +-- 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 +-- 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 +-- -- can this happen +-- if discfound then +-- notmatchreplace[discfound] = true +-- if notmatchpost[discfound] then +-- match = false +-- end +-- else +-- match = false +-- end +-- break +-- 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 +-- posttail = getprev(posttail) +-- if n < 1 then +-- break +-- end +-- 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 +-- replacetail = getprev(replacetail) +-- if n < 1 then +-- break +-- end +-- 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) +-- 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) +-- -- sweeptype = nil +-- 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 +-- 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 +-- 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 +-- -- can this happen +-- if discfound then +-- notmatchreplace[discfound] = true +-- if notmatchpre[discfound] then +-- match = false +-- end +-- else +-- match = false +-- end +-- break +-- 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 +-- pre = getnext(pre) +-- if n > s then +-- break +-- end +-- 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 +-- replace = getnext(replace) +-- if n > s then +-- break +-- end +-- 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) +-- 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 + +-- a bit optimized but still somewhat slow, fonts like ebgaramong are real torture tests because they +-- have many steps with one context (having multiple contexts makes more sense) also because we (can) +-- reduce them + local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) local sweepnode = sweepnode local sweeptype = sweeptype @@ -2294,6 +2757,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) local skipligature = flags[2] local skipbase = flags[3] local markclass = sequence.markclass + local skipsome = skipmark ~= false or skipligature ~= false or skipbase ~= false or markclass local skipped = false local startprev, startnext = getboth(start) @@ -2310,10 +2774,8 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) if s == 1 then -- this seldom happens as it makes no sense (bril, ebgaramond, husayni, minion) local char = ischar(current,currentfont) - if char then - if not seq[1][char] then - match = false - end + 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) @@ -2337,8 +2799,8 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) if last then local char, id = ischar(last,currentfont) if char then - local class = classes[char] - if class 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 @@ -2362,15 +2824,22 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) break end else - if discfound then - notmatchreplace[discfound] = true - if notmatchpre[discfound] then - match = false + if seq[n][char] then + if n < l then + last = getnext(last) end + n = n + 1 else - match = false + if discfound then + notmatchreplace[discfound] = true + if notmatchpre[discfound] then + match = false + end + else + match = false + end + break end - break end elseif char == false then if discfound then @@ -2394,10 +2863,10 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) while pre do if seq[n][getchar(pre)] then n = n + 1 - pre = getnext(pre) if n > l then break end + pre = getnext(pre) else notmatchpre[last] = true break @@ -2414,10 +2883,10 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) while replace do if seq[n][getchar(replace)] then n = n + 1 - replace = getnext(replace) if n > l then break end + replace = getnext(replace) else notmatchreplace[last] = true if notmatchpre[last] then @@ -2460,8 +2929,8 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) if prev then local char, id = ischar(prev,currentfont) if char then - local class = classes[char] - if class 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 @@ -2485,15 +2954,22 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) break end else - if discfound then - notmatchreplace[discfound] = true - if notmatchpost[discfound] then - match = false + if seq[n][char] then + if n > 1 then + prev = getprev(prev) end + n = n - 1 else - match = false + if discfound then + notmatchreplace[discfound] = true + if notmatchpost[discfound] then + match = false + end + else + match = false + end + break end - break end elseif char == false then if discfound then @@ -2522,10 +2998,10 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) if posttail == post then break else - posttail = getprev(posttail) if n < 1 then break end + posttail = getprev(posttail) end else notmatchpost[prev] = true @@ -2546,10 +3022,10 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) if replacetail == replace then break else - replacetail = getprev(replacetail) if n < 1 then break end + replacetail = getprev(replacetail) end else notmatchreplace[prev] = true @@ -2600,8 +3076,8 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) if current then local char, id = ischar(current,currentfont) if char then - local class = classes[char] - if class 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 @@ -2625,15 +3101,22 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) break end else - if discfound then - notmatchreplace[discfound] = true - if notmatchpre[discfound] then - match = false + if seq[n][char] then + if n < s then -- new test + current = getnext(current) -- was absent end + n = n + 1 else - match = false + if discfound then + notmatchreplace[discfound] = true + if notmatchpre[discfound] then + match = false + end + else + match = false + end + break end - break end elseif char == false then if discfound then @@ -2657,10 +3140,10 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) while pre do if seq[n][getchar(pre)] then n = n + 1 - pre = getnext(pre) if n > s then break end + pre = getnext(pre) else notmatchpre[current] = true break @@ -2677,10 +3160,10 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) while replace do if seq[n][getchar(replace)] then n = n + 1 - replace = getnext(replace) if n > s then break end + replace = getnext(replace) else notmatchreplace[current] = true -- different than others, needs checking if "not" is okay @@ -2696,7 +3179,6 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) else -- skip 'm end - -- maybe only if match current = getnext(current) elseif id == glue_code and seq[n][32] and isspace(current,threshold,id) then n = n + 1 @@ -2725,7 +3207,9 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) head, start, done = chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped) end if done then - break -- out of contexts (new, needs checking) + break + else + -- next context end -- elseif trace_chains then -- chaintrac(head,start,dataset,sequence,rlmode,ck,skipped,match) @@ -2739,6 +3223,8 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) return head, start, done end +------------------------------ + handlers.gsub_context = handle_contextchain handlers.gsub_contextchain = handle_contextchain handlers.gsub_reversecontextchain = handle_contextchain @@ -2952,13 +3438,15 @@ local function kernrun(disc,k_run,font,attr,...) done = true end if prev then - local nest = getprev(pre) +-- local nest = getprev(pre) setlink(prev,pre) if k_run(prevmarks,"preinjections",pre,font,attr,...) then -- or prev? done = true end - setprev(pre,nest) - setnext(prev,disc) +-- setprev(pre,nest) +-- setnext(prev,disc) + setprev(pre) + setlink(prev,disc) end end -- @@ -2972,7 +3460,8 @@ local function kernrun(disc,k_run,font,attr,...) done = true end setnext(posttail) - setprev(next,disc) +-- setprev(next,disc) + setlink(disc,next) end end -- @@ -2981,13 +3470,15 @@ local function kernrun(disc,k_run,font,attr,...) done = true end if prev then - local nest = getprev(replace) +-- local nest = getprev(replace) setlink(prev,replace) if k_run(prevmarks,"replaceinjections",replace,font,attr,...) then -- getnext(replace)) done = true end - setprev(replace,nest) - setnext(prev,disc) +-- setprev(replace,nest) +-- setnext(prev,disc) + setprev(replace) + setlink(prev,disc) end if next then setlink(replacetail,next) @@ -2995,7 +3486,8 @@ local function kernrun(disc,k_run,font,attr,...) done = true end setnext(replacetail) - setprev(next,disc) +-- setprev(next,disc) + setlink(disc,next) end elseif prev and next then setlink(prev,next) @@ -3203,7 +3695,8 @@ local function c_run_single(head,font,attr,lookupcache,step,dataset,sequence,rlm local sweep = sweephead[head] if sweep then start = sweep - sweephead[head] = nil + -- sweephead[head] = nil + sweephead[head] = false else start = head end @@ -3347,7 +3840,8 @@ local function c_run_multiple(head,font,attr,steps,nofsteps,dataset,sequence,rlm local sweep = sweephead[head] if sweep then start = sweep - sweephead[head] = nil + -- sweephead[head] = nil + sweephead[head] = false else start = head end @@ -3502,7 +3996,7 @@ local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,datase if lookupcache then local lookupmatch = lookupcache[char] if lookupmatch then - local h, d, ok = handler(head,n,dataset,sequence,lookupmatch,step,rlmode,i,injection) + local h, d, ok = handler(head,n,dataset,sequence,lookupmatch,rlmode,step,i,injection) if ok then return true end @@ -3578,6 +4072,306 @@ do directives.register("otf.fastdisc",function(v) fastdisc = v end) + -- we keep this as reference because the optimization below is sort of nasty + + -- function otf.featuresprocessor(head,font,attr,direction,n) + -- + -- local sequences = sequencelists[font] -- temp hack + -- + -- if not sequencelists then + -- return head, false + -- end + -- + -- nesting = nesting + 1 + -- + -- if nesting == 1 then + -- currentfont = font + -- tfmdata = fontdata[font] + -- descriptions = tfmdata.descriptions -- only needed in gref so we could pass node there instead + -- characters = tfmdata.characters -- but this branch is not entered that often anyway + -- local resources = tfmdata.resources + -- marks = resources.marks + -- classes = resources.classes + -- threshold, + -- factor = getthreshold(font) + -- checkmarks = tfmdata.properties.checkmarks + -- + -- elseif currentfont ~= font then + -- + -- report_warning("nested call with a different font, level %s, quitting",nesting) + -- nesting = nesting - 1 + -- return head, false + -- + -- 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 + -- checkstep(head) + -- end + -- + -- local initialrl = direction == "TRT" and -1 or 0 + -- + -- local done = false + -- local datasets = otf.dataset(tfmdata,font,attr) + -- local dirstack = { } -- could move outside function but we can have local runs + -- sweephead = { } + -- + -- -- Keeping track of the headnode is needed for devanagari. (I generalized it a bit + -- -- so that multiple cases are also covered.) We could prepend a temp node. + -- + -- -- We don't goto the next node when a disc node is created so that we can then treat + -- -- the pre, post and replace. It's a bit of a hack but works out ok for most cases. + -- + -- local discs = fastdisc and n and n > 1 and setmetatableindex(function(t,k) + -- local v = usesfont(k,font) + -- t[k] = v + -- return v + -- end) + -- + -- for s=1,#datasets do + -- local dataset = datasets[s] + -- ----- featurevalue = dataset[1] -- todo: pass to function instead of using a global + -- local attribute = dataset[2] + -- local sequence = dataset[3] -- sequences[s] -- also dataset[5] + -- local rlparmode = initialrl + -- local topstack = 0 + -- local typ = sequence.type + -- local gpossing = typ == "gpos_single" or typ == "gpos_pair" -- store in dataset + -- local handler = handlers[typ] + -- local steps = sequence.steps + -- local nofsteps = sequence.nofsteps + -- 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) + -- if ok then + -- done = true + -- if h then + -- head = h + -- end + -- end + -- elseif typ == "gsub_reversecontextchain" then + -- -- This might need a check: if we have #before or #after > 0 then we might need to reverse + -- -- the before and after lists in the loader. But first I need to see a font that uses multiple + -- -- matches. + -- local start = find_node_tail(head) + -- local rlmode = 0 -- how important is this .. do we need to check for dir? + -- while start do + -- local char = ischar(start,font) + -- if char then + -- local a -- happens often so no assignment is faster + -- if attr then + -- a = getattr(start,0) + -- end + -- 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 + -- -- todo: disc? + -- local ok + -- head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i) + -- if ok then + -- done = true + -- break + -- end + -- end + -- else + -- report_missing_coverage(dataset,sequence) + -- end + -- end + -- if start then + -- start = getprev(start) + -- end + -- else + -- start = getprev(start) + -- end + -- else + -- start = getprev(start) + -- end + -- end + -- else + -- local start = head + -- local rlmode = initialrl + -- if nofsteps == 1 then -- happens often + -- local step = steps[1] + -- local lookupcache = step.coverage + -- if not lookupcache then + -- report_missing_coverage(dataset,sequence) + -- else + -- while start do + -- local char, id = ischar(start,font) + -- if char then + -- -- local a = attr and 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 + -- 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 + -- if a then + -- local lookupmatch = lookupcache[char] + -- if lookupmatch then + -- 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 + -- elseif char == false then + -- -- whatever glyph + -- start = getnext(start) + -- elseif id == glue_code then + -- -- happens often + -- start = getnext(start) + -- elseif id == disc_code then + -- if not discs or discs[start] == true then + -- local ok + -- if gpossing then + -- start, ok = kernrun(start,k_run_single, font,attr,lookupcache,step,dataset,sequence,rlmode,handler) + -- elseif typ == "gsub_ligature" then + -- start, ok = testrun(start,t_run_single,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler) + -- else + -- start, ok = comprun(start,c_run_single, font,attr,lookupcache,step,dataset,sequence,rlmode,handler) + -- end + -- if ok then + -- done = true + -- end + -- else + -- start = getnext(start) + -- end + -- elseif id == math_code then + -- start = getnext(end_of_math(start)) + -- elseif id == dir_code then + -- start, topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode) + -- elseif id == localpar_code then + -- start, rlparmode, rlmode = pardirstate(start) + -- else + -- start = getnext(start) + -- end + -- end + -- end + -- + -- else + -- while start do + -- local char, id = ischar(start,font) + -- if char then + -- -- local a = attr and 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 + -- 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 + -- if a 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_coverage(dataset,sequence) + -- end + -- end + -- if start then + -- start = getnext(start) + -- end + -- else + -- start = getnext(start) + -- end + -- elseif char == false then + -- -- whatever glyph + -- start = getnext(start) + -- elseif id == glue_code then + -- -- happens often + -- start = getnext(start) + -- elseif id == disc_code then + -- if not discs or discs[start] == true then + -- local ok + -- if gpossing then + -- start, ok = kernrun(start,k_run_multiple, font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) + -- elseif typ == "gsub_ligature" then + -- start, ok = testrun(start,t_run_multiple,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) + -- else + -- start, ok = comprun(start,c_run_multiple, font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) + -- end + -- if ok then + -- done = true + -- end + -- else + -- start = getnext(start) + -- end + -- elseif id == math_code then + -- start = getnext(end_of_math(start)) + -- elseif id == dir_code then + -- start, topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode) + -- elseif id == localpar_code then + -- start, rlparmode, rlmode = pardirstate(start) + -- else + -- start = getnext(start) + -- end + -- end + -- end + -- end + -- + -- if trace_steps then -- ? + -- registerstep(head) + -- end + -- + -- end + -- + -- nesting = nesting - 1 + -- head = tonode(head) + -- + -- return head, done + -- end + + -- using a merged combined hash as first test saves some 30% on ebgaramond and + -- about 15% on arabtype .. then moving the a test also saves a bit (even when + -- often a is not set at all so that one is a bit debatable + function otf.featuresprocessor(head,font,attr,direction,n) local sequences = sequencelists[font] -- temp hack @@ -3663,38 +4457,48 @@ do end end elseif typ == "gsub_reversecontextchain" then + -- -- This might need a check: if we have #before or #after > 0 then we might need to reverse -- the before and after lists in the loader. But first I need to see a font that uses multiple -- matches. + -- local start = find_node_tail(head) local rlmode = 0 -- how important is this .. do we need to check for dir? + local merged = steps.merged while start do local char = ischar(start,font) if char then - local a -- happens often so no assignment is faster - if attr then - a = getattr(start,0) - end - 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 - -- todo: disc? - local ok - head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i) - if ok then - done = true - break + local m = merged[char] + if m then + local a -- happens often so no assignment is faster + if attr then + a = getattr(start,0) + end + if not a or (a == attr) 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 + if lookupcache then + local lookupmatch = lookupcache[char] + if lookupmatch then + -- todo: disc? + local ok + head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i) + if ok then + done = true + break + end end + else + report_missing_coverage(dataset,sequence) end - else - report_missing_coverage(dataset,sequence) end - end - if start then + if start then + start = getprev(start) + end + else start = getprev(start) end else @@ -3716,30 +4520,32 @@ do while start do local char, id = ischar(start,font) if char then - -- local a = attr and 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 - 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 + local lookupmatch = lookupcache[char] + if lookupmatch then + -- local a = attr and 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 + 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 lookupmatch = lookupcache[char] - if lookupmatch then + if a then local ok head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1) if ok then done = true end - end - if start then + if start then + start = getnext(start) + end + else start = getnext(start) end else @@ -3778,48 +4584,55 @@ do end end end - else + local merged = steps.merged while start do local char, id = ischar(start,font) if char then - -- local a = attr and 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 - 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 + local m = merged[char] + if m then + -- local a = attr and 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 + 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=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 + 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 + 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_coverage(dataset,sequence) end - else - report_missing_coverage(dataset,sequence) end - end - if start then + if start then + start = getnext(start) + end + else start = getnext(start) end else @@ -3891,14 +4704,14 @@ function otf.plugininitializer(tfmdata,value) end end -function otf.pluginprocessor(head,font) +function otf.pluginprocessor(head,font,attr,direction) -- n local s = fontdata[font].shared local p = s and s.plugin if p then if trace_plugins then report_process("applying plugin %a",p[1]) end - return p[2](head,font) + return p[2](head,font,attr,direction) else return head, false end diff --git a/tex/context/base/mkiv/font-oup.lua b/tex/context/base/mkiv/font-oup.lua index 54ca690d1..5ee6df505 100644 --- a/tex/context/base/mkiv/font-oup.lua +++ b/tex/context/base/mkiv/font-oup.lua @@ -15,6 +15,7 @@ local formatters = string.formatters local sortedkeys = table.sortedkeys local sortedhash = table.sortedhash local tohash = table.tohash +local setmetatableindex = table.setmetatableindex local report = logs.reporter("otf reader") @@ -2256,6 +2257,33 @@ function readers.expand(data) end end end + + -- using a merged combined hash as first test saves some 30% on ebgaramond and + -- about 15% on arabtype .. then moving the a test also saves a bit (even when + -- often a is not set at all so that one is a bit debatable + + local function mergesteps(t,k) + if k == "merged" then + local merged = { } + for i=1,#t do + local step = t[i] + local coverage = step.coverage + for k, v in next, coverage do + local m = merged[k] + if m then + m[2] = i + -- m[#m+1] = step + else + merged[k] = { i, i } + -- merged[k] = { step } + end + end + end + t.merged = merged + return merged + end + end + local function expandlookups(sequences) if sequences then -- we also need to do sublookups @@ -2263,10 +2291,10 @@ function readers.expand(data) local sequence = sequences[i] local steps = sequence.steps if steps then + + setmetatableindex(steps,mergesteps) + local kind = sequence.type --- if kind == "gsub_reversecontextchain" then --- inspect(sequence) --- end local markclass = sequence.markclass if markclass then if not markclasses then @@ -2276,7 +2304,8 @@ function readers.expand(data) sequence.markclass = markclasses[markclass] end end - for i=1,sequence.nofsteps do + local nofsteps = sequence.nofsteps + for i=1,nofsteps do local step = steps[i] local baseclasses = step.baseclasses if baseclasses then @@ -2371,6 +2400,7 @@ function readers.expand(data) end end end + expandlookups(sequences) expandlookups(sublookups) end diff --git a/tex/context/base/mkiv/l-string.lua b/tex/context/base/mkiv/l-string.lua index e0fb28445..cda837615 100644 --- a/tex/context/base/mkiv/l-string.lua +++ b/tex/context/base/mkiv/l-string.lua @@ -18,7 +18,7 @@ local P, S, C, Ct, Cc, Cs = lpeg.P, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cs -- -- function string.split(str,pattern) -- local t = { } --- if #str > 0 then +-- if str ~= "" then -- local n = 1 -- for s in gmatch(str..pattern,"(.-)"..pattern) do -- t[n] = s diff --git a/tex/context/base/mkiv/math-fbk.lua b/tex/context/base/mkiv/math-fbk.lua index c883d57a7..2ce292a19 100644 --- a/tex/context/base/mkiv/math-fbk.lua +++ b/tex/context/base/mkiv/math-fbk.lua @@ -423,7 +423,7 @@ end virtualcharacters[0xFE33E] = virtualcharacters[0x203E] -- convenient virtualcharacters[0xFE33F] = virtualcharacters[0x203E] -- convenient --- spacing +-- spacing (no need for a cache of widths) local c_zero = byte('0') local c_period = byte('.') @@ -432,7 +432,7 @@ local function spacefraction(data,fraction) local width = fraction * data.target.parameters.space return { width = width, - commands = { right = width } + commands = { { "right", width } } } end @@ -440,7 +440,7 @@ local function charfraction(data,char) local width = data.target.characters[char].width return { width = width, - commands = { right = width } + commands = { { "right", width } } } end @@ -448,7 +448,7 @@ local function quadfraction(data,fraction) local width = fraction * data.target.parameters.quad return { width = width, - commands = { right = width } + commands = { { "right", width } } } end diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf index 4a7516ffe..933402892 100644 Binary files a/tex/context/base/mkiv/status-files.pdf and b/tex/context/base/mkiv/status-files.pdf differ diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf index c99f701e7..3334c4ae9 100644 Binary files a/tex/context/base/mkiv/status-lua.pdf and b/tex/context/base/mkiv/status-lua.pdf differ diff --git a/tex/context/base/mkiv/util-deb.lua b/tex/context/base/mkiv/util-deb.lua index 57e015386..b8db0c583 100644 --- a/tex/context/base/mkiv/util-deb.lua +++ b/tex/context/base/mkiv/util-deb.lua @@ -145,7 +145,8 @@ function debugger.showstats(printer,threshold) local functions = 0 local dataset = { } local length = 0 - local wholetime = 0 + local realtime = 0 + local totaltime = 0 local threshold = threshold or 0 for name, sources in next, names do for source, lines in next, sources do @@ -162,8 +163,9 @@ function debugger.showstats(printer,threshold) if real < 0 then real = 0 end - wholetime = wholetime + real + realtime = realtime + real end + totaltime = totaltime + total if line < 0 then line = 0 end @@ -201,23 +203,22 @@ function debugger.showstats(printer,threshold) if length > 50 then length = 50 end - local fmt = string.formatters["%4.9k %4.9k %3.3k %8i %-" .. length .. "s %4i %s"] + local fmt = string.formatters["%4.9k s %3.3k %% %4.9k s %3.3k %% %8i # %-" .. length .. "s %4i %s"] for i=1,#dataset do - local data = dataset[i] - local real = data[1] - local total = data[2] - local count = data[3] - local name = data[4] - local source = data[5] - local line = data[6] - local percent = real / wholetime + local data = dataset[i] + local real = data[1] + local total = data[2] + local count = data[3] + local name = data[4] + local source = data[5] + local line = data[6] calls = calls + count functions = functions + 1 name = gsub(name,"%s+"," ") if #name > length then name = sub(name,1,length) end - printer(fmt(seconds(total),seconds(real),percent,count,name,line,source)) + printer(fmt(seconds(total),100*total/totaltime,seconds(real),100*real/realtime,count,name,line,source)) end printer("") printer(format("functions : %i", functions)) diff --git a/tex/context/interface/mkii/keys-nl.xml b/tex/context/interface/mkii/keys-nl.xml index 1c6077d1e..e99911bde 100644 --- a/tex/context/interface/mkii/keys-nl.xml +++ b/tex/context/interface/mkii/keys-nl.xml @@ -693,6 +693,7 @@ + diff --git a/tex/context/interface/mkiv/i-context.pdf b/tex/context/interface/mkiv/i-context.pdf index 03a1906e2..365dc0f01 100644 Binary files a/tex/context/interface/mkiv/i-context.pdf and b/tex/context/interface/mkiv/i-context.pdf differ diff --git a/tex/context/interface/mkiv/i-readme.pdf b/tex/context/interface/mkiv/i-readme.pdf index 13cb46287..f656c5953 100644 Binary files a/tex/context/interface/mkiv/i-readme.pdf and b/tex/context/interface/mkiv/i-readme.pdf differ diff --git a/tex/context/modules/mkiv/x-asciimath.lua b/tex/context/modules/mkiv/x-asciimath.lua index 75f4b06fd..07cf12306 100644 --- a/tex/context/modules/mkiv/x-asciimath.lua +++ b/tex/context/modules/mkiv/x-asciimath.lua @@ -1934,7 +1934,7 @@ local uncrapped = { } local function convert(str,nowrap) - if #str > 0 then + if str ~= "" then local unicoded = lpegmatch(u_parser,str) or str if lpegmatch(p_onechar,unicoded) then ctx_mathematics(uncrapped[unicoded] or unicoded) diff --git a/tex/context/modules/mkiv/x-ldx.lua b/tex/context/modules/mkiv/x-ldx.lua index e88c4c797..775c9a16d 100644 --- a/tex/context/modules/mkiv/x-ldx.lua +++ b/tex/context/modules/mkiv/x-ldx.lua @@ -80,7 +80,7 @@ function ldx.load(filename) end local str = sub(data, i, #data) str = gsub(str, "^%s*(.-)%s*$", "%1") - if #str > 0 then + if str ~= "" then t[#t+1] = { code = str } end return t diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index d793cdf04..ed9c29f78 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 : 06/29/17 09:34:20 +-- merge date : 06/30/17 19:45:43 do -- begin closure to overcome local limits and interference @@ -7928,19 +7928,6 @@ function constructors.scale(tfmdata,specification) if changed then local c=changed[unicode] if c and c~=unicode then - while true do - local cc=changed[c] - if not cc then - break - elseif cc==unicode then - break - elseif cc==c then - c=nil - break - else - c=cc - end - end if c then description=descriptions[c] or descriptions[unicode] or character character=characters[c] or character @@ -17325,6 +17312,7 @@ local formatters=string.formatters local sortedkeys=table.sortedkeys local sortedhash=table.sortedhash local tohash=table.tohash +local setmetatableindex=table.setmetatableindex local report=logs.reporter("otf reader") local trace_markwidth=false trackers.register("otf.markwidth",function(v) trace_markwidth=v end) local readers=fonts.handlers.otf.readers @@ -19332,12 +19320,32 @@ function readers.expand(data) end end end + local function mergesteps(t,k) + if k=="merged" then + local merged={} + for i=1,#t do + local step=t[i] + local coverage=step.coverage + for k,v in next,coverage do + local m=merged[k] + if m then + m[2]=i + else + merged[k]={ i,i } + end + end + end + t.merged=merged + return merged + end + end local function expandlookups(sequences) if sequences then for i=1,#sequences do local sequence=sequences[i] local steps=sequence.steps if steps then + setmetatableindex(steps,mergesteps) local kind=sequence.type local markclass=sequence.markclass if markclass then @@ -19348,7 +19356,8 @@ function readers.expand(data) sequence.markclass=markclasses[markclass] end end - for i=1,sequence.nofsteps do + local nofsteps=sequence.nofsteps + for i=1,nofsteps do local step=steps[i] local baseclasses=step.baseclasses if baseclasses then @@ -22389,12 +22398,10 @@ local factor=0 local threshold=0 local checkmarks=false local sweepnode=nil -local sweepprev=nil -local sweepnext=nil -local sweephead={} -local notmatchpre={} -local notmatchpost={} -local notmatchreplace={} +local sweephead={} +local notmatchpre={} +local notmatchpost={} +local notmatchreplace={} local handlers={} local isspace=injections.isspace local getthreshold=injections.getthreshold @@ -24039,8 +24046,8 @@ local function chaindisk(head,start,dataset,sequence,rlmode,ck,skipped) setdisc(lookaheaddisc,cf,post,new) end start=getprev(lookaheaddisc) - sweephead[cf]=getnext(clast) - sweephead[new]=getnext(cl) + sweephead[cf]=getnext(clast) or false + sweephead[new]=getnext(cl) or false elseif backtrackdisc then local cf=getnext(backtrackdisc) local cl=start @@ -24102,8 +24109,8 @@ local function chaindisk(head,start,dataset,sequence,rlmode,ck,skipped) setdisc(backtrackdisc,pre,post,replace) end start=getprev(backtrackdisc) - sweephead[post]=getnext(clast) - sweephead[replace]=getnext(last) + sweephead[post]=getnext(clast) or false + sweephead[replace]=getnext(last) or false else local ok=false head,start,ok=chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped) @@ -24135,6 +24142,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) local skipligature=flags[2] local skipbase=flags[3] local markclass=sequence.markclass + local skipsome=skipmark~=false or skipligature~=false or skipbase~=false or markclass local skipped=false local startprev, startnext=getboth(start) @@ -24148,10 +24156,8 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) local size=1 if s==1 then local char=ischar(current,currentfont) - if char then - if not seq[1][char] then - match=false - end + if char and not seq[1][char] then + match=false end else local f=ck[4] @@ -24169,8 +24175,8 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) if last then local char,id=ischar(last,currentfont) if char then - local class=classes[char] - if class 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 @@ -24194,15 +24200,22 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) break end else - if discfound then - notmatchreplace[discfound]=true - if notmatchpre[discfound] then - match=false + if seq[n][char] then + if nl then break end + pre=getnext(pre) else notmatchpre[last]=true break @@ -24245,10 +24258,10 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) while replace do if seq[n][getchar(replace)] then n=n+1 - replace=getnext(replace) if n>l then break end + replace=getnext(replace) else notmatchreplace[last]=true if notmatchpre[last] then @@ -24285,8 +24298,8 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) if prev then local char,id=ischar(prev,currentfont) if char then - local class=classes[char] - if class 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 @@ -24310,15 +24323,22 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) break end else - if discfound then - notmatchreplace[discfound]=true - if notmatchpost[discfound] then - match=false + if seq[n][char] then + if n>1 then + prev=getprev(prev) end + n=n-1 else - match=false + if discfound then + notmatchreplace[discfound]=true + if notmatchpost[discfound] then + match=false + end + else + match=false + end + break end - break end elseif char==false then if discfound then @@ -24346,10 +24366,10 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) if posttail==post then break else - posttail=getprev(posttail) if n<1 then break end + posttail=getprev(posttail) end else notmatchpost[prev]=true @@ -24369,10 +24389,10 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) if replacetail==replace then break else - replacetail=getprev(replacetail) if n<1 then break end + replacetail=getprev(replacetail) end else notmatchreplace[prev]=true @@ -24419,8 +24439,8 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) if current then local char,id=ischar(current,currentfont) if char then - local class=classes[char] - if class 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 @@ -24444,15 +24464,22 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) break end else - if discfound then - notmatchreplace[discfound]=true - if notmatchpre[discfound] then - match=false + if seq[n][char] then + if ns then break end + pre=getnext(pre) else notmatchpre[current]=true break @@ -24495,10 +24522,10 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) while replace do if seq[n][getchar(replace)] then n=n+1 - replace=getnext(replace) if n>s then break end + replace=getnext(replace) else notmatchreplace[current]=true if not notmatchpre[current] then @@ -24540,7 +24567,8 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) head,start,done=chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped) end if done then - break + break + else end end end @@ -24699,13 +24727,12 @@ local function kernrun(disc,k_run,font,attr,...) done=true end if prev then - local nest=getprev(pre) setlink(prev,pre) if k_run(prevmarks,"preinjections",pre,font,attr,...) then done=true end - setprev(pre,nest) - setnext(prev,disc) + setprev(pre) + setlink(prev,disc) end end if post then @@ -24718,7 +24745,7 @@ local function kernrun(disc,k_run,font,attr,...) done=true end setnext(posttail) - setprev(next,disc) + setlink(disc,next) end end if replace then @@ -24726,13 +24753,12 @@ local function kernrun(disc,k_run,font,attr,...) done=true end if prev then - local nest=getprev(replace) setlink(prev,replace) if k_run(prevmarks,"replaceinjections",replace,font,attr,...) then done=true end - setprev(replace,nest) - setnext(prev,disc) + setprev(replace) + setlink(prev,disc) end if next then setlink(replacetail,next) @@ -24740,7 +24766,7 @@ local function kernrun(disc,k_run,font,attr,...) done=true end setnext(replacetail) - setprev(next,disc) + setlink(disc,next) end elseif prev and next then setlink(prev,next) @@ -24899,7 +24925,7 @@ local function c_run_single(head,font,attr,lookupcache,step,dataset,sequence,rlm local sweep=sweephead[head] if sweep then start=sweep - sweephead[head]=nil + sweephead[head]=false else start=head end @@ -25035,7 +25061,7 @@ local function c_run_multiple(head,font,attr,steps,nofsteps,dataset,sequence,rlm local sweep=sweephead[head] if sweep then start=sweep - sweephead[head]=nil + sweephead[head]=false else start=head end @@ -25180,7 +25206,7 @@ local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,datase if lookupcache then local lookupmatch=lookupcache[char] if lookupmatch then - local h,d,ok=handler(head,n,dataset,sequence,lookupmatch,step,rlmode,i,injection) + local h,d,ok=handler(head,n,dataset,sequence,lookupmatch,rlmode,step,i,injection) if ok then return true end @@ -25293,32 +25319,38 @@ do elseif typ=="gsub_reversecontextchain" then local start=find_node_tail(head) local rlmode=0 + local merged=steps.merged while start do local char=ischar(start,font) if char then - local a - if attr then - a=getattr(start,0) - end - 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 - local ok - head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i) - if ok then - done=true - break + local m=merged[char] + if m then + local a + if attr then + a=getattr(start,0) + end + if not a or (a==attr) then + for i=m[1],m[2] do + local step=steps[i] + local lookupcache=step.coverage + if lookupcache then + 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 + end end + else + report_missing_coverage(dataset,sequence) end - else - report_missing_coverage(dataset,sequence) end - end - if start then + if start then + start=getprev(start) + end + else start=getprev(start) end else @@ -25340,24 +25372,26 @@ do while start do local char,id=ischar(start,font) if char then - local a - if attr then - if getattr(start,0)==attr and (not attribute or getprop(start,a_state)==attribute) 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 + 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 lookupmatch=lookupcache[char] - if lookupmatch then + if a then local ok head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1) if ok then done=true end - end - if start then + if start then + start=getnext(start) + end + else start=getnext(start) end else @@ -25395,38 +25429,44 @@ do end end else + local merged=steps.merged while start do local char,id=ischar(start,font) if char then - local a - if attr then - if getattr(start,0)==attr and (not attribute or getprop(start,a_state)==attribute) 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 + 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=1,nofsteps do - local step=steps[i] - local lookupcache=step.coverage - if lookupcache then - 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 + if lookupcache then + 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 + else + report_missing_coverage(dataset,sequence) end - else - report_missing_coverage(dataset,sequence) end - end - if start then + if start then + start=getnext(start) + end + else start=getnext(start) end else @@ -25485,14 +25525,14 @@ function otf.plugininitializer(tfmdata,value) tfmdata.shared.plugin=plugins[value] end end -function otf.pluginprocessor(head,font) +function otf.pluginprocessor(head,font,attr,direction) local s=fontdata[font].shared local p=s and s.plugin if p then if trace_plugins then report_process("applying plugin %a",p[1]) end - return p[2](head,font) + return p[2](head,font,attr,direction) else return head,false end @@ -29020,7 +29060,7 @@ local afm=handlers.afm or {} handlers.afm=afm local readers=afm.readers or {} afm.readers=readers -afm.version=1.512 +afm.version=1.513 local get_indexes,get_shapes do local decrypt -- cgit v1.2.3