From d9a4319a4f92ebac0b92663691cb73354f3a8e85 Mon Sep 17 00:00:00 2001 From: Marius Date: Mon, 10 Jun 2013 14:00:23 +0300 Subject: beta 2013.06.10 12:24 --- tex/context/base/char-def.lua | 11 +- tex/context/base/cont-new.mkii | 2 +- tex/context/base/cont-new.mkiv | 2 +- tex/context/base/context-version.pdf | Bin 4134 -> 4131 bytes tex/context/base/context.mkii | 2 +- tex/context/base/context.mkiv | 2 +- tex/context/base/font-chk.lua | 51 +- tex/context/base/font-ctx.lua | 30 +- tex/context/base/font-otd.lua | 26 +- tex/context/base/font-otn.lua | 2 - tex/context/base/l-table.lua | 380 +---------- tex/context/base/lpdf-ano.lua | 32 +- tex/context/base/math-act.lua | 76 ++- tex/context/base/math-ini.lua | 27 +- tex/context/base/math-ini.mkiv | 6 + tex/context/base/math-stc.mkvi | 18 +- tex/context/base/node-fin.lua | 716 +-------------------- tex/context/base/node-pro.lua | 3 + tex/context/base/node-rul.mkiv | 44 +- tex/context/base/spac-ver.mkiv | 6 +- tex/context/base/status-files.pdf | Bin 24681 -> 24645 bytes tex/context/base/status-lua.pdf | Bin 212042 -> 213142 bytes tex/context/base/strc-ref.lua | 2 +- tex/context/base/trac-vis.lua | 24 +- tex/context/base/util-str.lua | 14 +- tex/context/base/util-tab.lua | 416 +++++++++--- tex/context/base/util-tpl.lua | 22 +- tex/context/base/x-mathml.mkiv | 100 +-- tex/context/fonts/lm.lfg | 5 +- tex/generic/context/luatex/luatex-fonts-merged.lua | 69 +- 30 files changed, 761 insertions(+), 1327 deletions(-) (limited to 'tex') diff --git a/tex/context/base/char-def.lua b/tex/context/base/char-def.lua index 7d2df5d41..f64efa5c3 100644 --- a/tex/context/base/char-def.lua +++ b/tex/context/base/char-def.lua @@ -57678,16 +57678,19 @@ characters.data={ description="OVERLINE", direction="on", linebreak="al", + mathextensible="l", + comment=[[mathspec={ { class="topaccent", name="overbar" }, { class="botaccent", name="underbar" } }"]], mathspec={ { - class="topaccent", - name="overbar", + class="under", + name="underbar", }, { - class="botaccent", - name="underbar", + class="over", + name="overbar", }, }, + mathstretch="h", specials={ "compat", 0x0020, 0x0305 }, unicodeslot=0x203E, }, diff --git a/tex/context/base/cont-new.mkii b/tex/context/base/cont-new.mkii index 544e5e537..f0385c065 100644 --- a/tex/context/base/cont-new.mkii +++ b/tex/context/base/cont-new.mkii @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2013.04.09 10:38} +\newcontextversion{2013.06.07 17:34} %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/cont-new.mkiv b/tex/context/base/cont-new.mkiv index 60a4e45f8..7b585b38a 100644 --- a/tex/context/base/cont-new.mkiv +++ b/tex/context/base/cont-new.mkiv @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2013.06.07 12:25} +\newcontextversion{2013.06.10 12:24} %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/context-version.pdf b/tex/context/base/context-version.pdf index c5561b93e..8aed0b0df 100644 Binary files a/tex/context/base/context-version.pdf and b/tex/context/base/context-version.pdf differ diff --git a/tex/context/base/context.mkii b/tex/context/base/context.mkii index 97afd33df..990c8bd11 100644 --- a/tex/context/base/context.mkii +++ b/tex/context/base/context.mkii @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2013.04.09 10:38} +\edef\contextversion{2013.06.07 17:34} %D For those who want to use this: diff --git a/tex/context/base/context.mkiv b/tex/context/base/context.mkiv index 3eb8c9a76..0e48ae1c4 100644 --- a/tex/context/base/context.mkiv +++ b/tex/context/base/context.mkiv @@ -25,7 +25,7 @@ %D up and the dependencies are more consistent. \edef\contextformat {\jobname} -\edef\contextversion{2013.06.07 12:25} +\edef\contextversion{2013.06.10 12:24} \edef\contextkind {beta} %D For those who want to use this: diff --git a/tex/context/base/font-chk.lua b/tex/context/base/font-chk.lua index 1b89366fd..467afae9b 100644 --- a/tex/context/base/font-chk.lua +++ b/tex/context/base/font-chk.lua @@ -9,8 +9,9 @@ if not modules then modules = { } end modules ['font-chk'] = { -- possible optimization: delayed initialization of vectors -- move to the nodes namespace -local format = string.format +local formatters = string.formatters local bpfactor = number.dimenfactors.bp +local fastcopy = table.fastcopy local report_fonts = logs.reporter("fonts","checking") @@ -23,9 +24,11 @@ local fonthashes = fonts.hashes local fontdata = fonthashes.identifiers local fontcharacters = fonthashes.characters -local addprivate = fonts.helpers.addprivate -local hasprivate = fonts.helpers.hasprivate -local getprivatenode = fonts.helpers.getprivatenode +local helpers = fonts.helpers + +local addprivate = helpers.addprivate +local hasprivate = helpers.hasprivate +local getprivatenode = helpers.getprivatenode local otffeatures = fonts.constructors.newfeatures("otf") local registerotffeature = otffeatures.register @@ -147,7 +150,7 @@ local variants = { { tag = "yellow", r = .6, g = .6, b = 0 }, } -local package = "q %0.6f 0 0 %0.6f 0 0 cm %s %s %s rg %s %s %s RG 10 M 1 j 1 J 0.05 w %s Q" +local pdf_blob = "pdf: q %0.6f 0 0 %0.6f 0 0 cm %s %s %s rg %s %s %s RG 10 M 1 j 1 J 0.05 w %s Q" local cache = { } -- saves some tables but not that impressive @@ -162,9 +165,9 @@ local function addmissingsymbols(tfmdata) -- we can have an alternative with rul for i =1, #fakes do local fake = fakes[i] local name = fake.name - local privatename = format("placeholder %s %s",name,tag) + local privatename = formatters["placeholder %s %s"](name,tag) if not hasprivate(tfmdata,privatename) then - local hash = format("%s_%s_%s_%s_%s_%s",name,tag,r,g,b,size) + local hash = formatters["%s_%s_%s_%s_%s_%s"](name,tag,r,g,b,size) local char = cache[hash] if not char then char = { @@ -172,7 +175,7 @@ local function addmissingsymbols(tfmdata) -- we can have an alternative with rul height = size*fake.height, depth = size*fake.depth, -- bah .. low level pdf ... should be a rule or plugged in - commands = { { "special", "pdf: " .. format(package,scale,scale,r,g,b,r,g,b,fake.code) } } + commands = { { "special", formatters[pdf_blob](scale,scale,r,g,b,r,g,b,fake.code) } } } cache[hash] = char end @@ -197,7 +200,7 @@ fonts.loggers.category_to_placeholder = mapping function commands.getplaceholderchar(name) local id = font.current() addmissingsymbols(fontdata[id]) - context(fonts.helpers.getprivatenode(fontdata[id],name)) + context(helpers.getprivatenode(fontdata[id],name)) end function checkers.missing(head) @@ -357,3 +360,33 @@ luatex.registerstopactions(function() end end end) + +-- for the moment here + +function helpers.expandglyph(characters,index,done) + done = done or { } + if not done[index] then + local data = characters[index] + if data then + done[index] = true + local d = fastcopy(data) + local n = d.next + if n then + d.next = expandglyph(characters,n,done) + end + local h = d.horiz_variants + if h then + for i=1,#h do + h[i].glyph = expandglyph(characters,h[i].glyph,done) + end + end + local v = d.vert_variants + if v then + for i=1,#v do + v[i].glyph = expandglyph(characters,v[i].glyph,done) + end + end + return d + end + end +end diff --git a/tex/context/base/font-ctx.lua b/tex/context/base/font-ctx.lua index 63d10d007..31de74578 100644 --- a/tex/context/base/font-ctx.lua +++ b/tex/context/base/font-ctx.lua @@ -617,19 +617,39 @@ specifiers.definecontext = definecontext -- we extend the hasher: +-- constructors.hashmethods.virtual = function(list) +-- local s = { } +-- local n = 0 +-- for k, v in next, list do +-- n = n + 1 +-- s[n] = k -- no checking on k +-- end +-- if n > 0 then +-- sort(s) +-- for i=1,n do +-- local k = s[i] +-- s[i] = k .. '=' .. tostring(list[k]) +-- end +-- return concat(s,"+") +-- end +-- end + constructors.hashmethods.virtual = function(list) local s = { } local n = 0 for k, v in next, list do n = n + 1 - s[n] = k -- no checking on k + -- if v == true then + -- s[n] = k .. '=true' + -- elseif v == false then + -- s[n] = k .. '=false' + -- else + -- s[n] = k .. "=" .. v + -- end + s[n] = k .. "=" .. tostring(v) end if n > 0 then sort(s) - for i=1,n do - local k = s[i] - s[i] = k .. '=' .. tostring(list[k]) - end return concat(s,"+") end end diff --git a/tex/context/base/font-otd.lua b/tex/context/base/font-otd.lua index a9d093d6d..919da2379 100644 --- a/tex/context/base/font-otd.lua +++ b/tex/context/base/font-otd.lua @@ -242,19 +242,19 @@ function otf.dataset(tfmdata,font,attr) -- attr only when explicit (as in specia } rl[attr] = ra local sequences = tfmdata.resources.sequences --- setmetatableindex(ra, function(t,k) --- if type(k) == "number" then --- local v = initialize(sequences[k],script,language,s_enabled,a_enabled,font,attr,dynamic) --- t[k] = v or false --- return v --- end --- end) -for s=1,#sequences do - local v = initialize(sequences[s],script,language,s_enabled,a_enabled,font,attr,dynamic) - if v then - ra[#ra+1] = v - end -end + -- setmetatableindex(ra, function(t,k) + -- if type(k) == "number" then + -- local v = initialize(sequences[k],script,language,s_enabled,a_enabled,font,attr,dynamic) + -- t[k] = v or false + -- return v + -- end + -- end) + for s=1,#sequences do + local v = initialize(sequences[s],script,language,s_enabled,a_enabled,font,attr,dynamic) + if v then + ra[#ra+1] = v + end + end end return ra diff --git a/tex/context/base/font-otn.lua b/tex/context/base/font-otn.lua index f462c0db4..e0cb9acbc 100644 --- a/tex/context/base/font-otn.lua +++ b/tex/context/base/font-otn.lua @@ -2209,8 +2209,6 @@ local function featuresprocessor(head,font,attr) else start = start.next end - elseif id == math_code then - start = end_of_math(start).next else start = start.next end diff --git a/tex/context/base/l-table.lua b/tex/context/base/l-table.lua index 493a82084..4f6b9b4ed 100644 --- a/tex/context/base/l-table.lua +++ b/tex/context/base/l-table.lua @@ -366,12 +366,12 @@ local function simple_table(t) else tt[nt] = tostring(v) -- tostring not needed end - elseif tv == "boolean" then - nt = nt + 1 - tt[nt] = tostring(v) elseif tv == "string" then nt = nt + 1 tt[nt] = format("%q",v) + elseif tv == "boolean" then + nt = nt + 1 + tt[nt] = v and "true" or "false" else tt = nil break @@ -397,7 +397,8 @@ end -- todo: %g faster on numbers than %s --- we can speed this up with repeaters and formatters (is indeed faster) +-- we can speed this up with repeaters and formatters but we haven't defined them +-- yet local propername = patterns.propername -- was find(name,"^%a[%w%_]*$") @@ -423,7 +424,7 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s[%q]={",depth,name)) end elseif tn == "boolean" then - handle(format("%s[%s]={",depth,tostring(name))) + handle(format("%s[%s]={",depth,name and "true" or "false")) else handle(format("%s{",depth)) end @@ -459,21 +460,21 @@ local function do_serialize(root,name,depth,level,indexed) --~ if v == root then -- circular --~ else - local t, tk = type(v), type(k) + local tv, tk = type(v), type(k) if compact and first and tk == "number" and k >= first and k <= last then - if t == "number" then + if tv == "number" then if hexify then handle(format("%s 0x%04X,",depth,v)) else handle(format("%s %s,",depth,v)) -- %.99g end - elseif t == "string" then + elseif tv == "string" then if reduce and tonumber(v) then handle(format("%s %s,",depth,v)) else handle(format("%s %q,",depth,v)) end - elseif t == "table" then + elseif tv == "table" then if not next(v) then handle(format("%s {},",depth)) elseif inline then -- and #t > 0 @@ -486,9 +487,9 @@ local function do_serialize(root,name,depth,level,indexed) else do_serialize(v,k,depth,level+1,true) end - elseif t == "boolean" then - handle(format("%s %s,",depth,tostring(v))) - elseif t == "function" then + elseif tv == "boolean" then + handle(format("%s %s,",depth,v and "true" or "false")) + elseif tv == "function" then if functions then handle(format('%s load(%q),',depth,dump(v))) -- maybe strip else @@ -501,7 +502,7 @@ local function do_serialize(root,name,depth,level,indexed) if false then handle(format("%s __p__=nil,",depth)) end - elseif t == "number" then + elseif tv == "number" then if tk == "number" then if hexify then handle(format("%s [0x%04X]=0x%04X,",depth,k,v)) @@ -510,9 +511,9 @@ local function do_serialize(root,name,depth,level,indexed) end elseif tk == "boolean" then if hexify then - handle(format("%s [%s]=0x%04X,",depth,tostring(k),v)) + handle(format("%s [%s]=0x%04X,",depth,k and "true" or "false",v)) else - handle(format("%s [%s]=%s,",depth,tostring(k),v)) -- %.99g + handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) -- %.99g end elseif noquotes and not reserved[k] and lpegmatch(propername,k) then if hexify then @@ -527,7 +528,7 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s [%q]=%s,",depth,k,v)) -- %.99g end end - elseif t == "string" then + elseif tv == "string" then if reduce and tonumber(v) then if tk == "number" then if hexify then @@ -536,7 +537,7 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s [%s]=%s,",depth,k,v)) end elseif tk == "boolean" then - handle(format("%s [%s]=%s,",depth,tostring(k),v)) + handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) elseif noquotes and not reserved[k] and lpegmatch(propername,k) then handle(format("%s %s=%s,",depth,k,v)) else @@ -550,14 +551,14 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s [%s]=%q,",depth,k,v)) end elseif tk == "boolean" then - handle(format("%s [%s]=%q,",depth,tostring(k),v)) + handle(format("%s [%s]=%q,",depth,k and "true" or "false",v)) elseif noquotes and not reserved[k] and lpegmatch(propername,k) then handle(format("%s %s=%q,",depth,k,v)) else handle(format("%s [%q]=%q,",depth,k,v)) end end - elseif t == "table" then + elseif tv == "table" then if not next(v) then if tk == "number" then if hexify then @@ -566,7 +567,7 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s [%s]={},",depth,k)) end elseif tk == "boolean" then - handle(format("%s [%s]={},",depth,tostring(k))) + handle(format("%s [%s]={},",depth,k and "true" or "false")) elseif noquotes and not reserved[k] and lpegmatch(propername,k) then handle(format("%s %s={},",depth,k)) else @@ -582,7 +583,7 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s [%s]={ %s },",depth,k,concat(st,", "))) end elseif tk == "boolean" then - handle(format("%s [%s]={ %s },",depth,tostring(k),concat(st,", "))) + handle(format("%s [%s]={ %s },",depth,k and "true" or "false",concat(st,", "))) elseif noquotes and not reserved[k] and lpegmatch(propername,k) then handle(format("%s %s={ %s },",depth,k,concat(st,", "))) else @@ -594,21 +595,21 @@ local function do_serialize(root,name,depth,level,indexed) else do_serialize(v,k,depth,level+1) end - elseif t == "boolean" then + elseif tv == "boolean" then if tk == "number" then if hexify then - handle(format("%s [0x%04X]=%s,",depth,k,tostring(v))) + handle(format("%s [0x%04X]=%s,",depth,k,v and "true" or "false")) else - handle(format("%s [%s]=%s,",depth,k,tostring(v))) + handle(format("%s [%s]=%s,",depth,k,v and "true" or "false")) end elseif tk == "boolean" then - handle(format("%s [%s]=%s,",depth,tostring(k),tostring(v))) + handle(format("%s [%s]=%s,",depth,tostring(k),v and "true" or "false")) elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=%s,",depth,k,tostring(v))) + handle(format("%s %s=%s,",depth,k,v and "true" or "false")) else - handle(format("%s [%q]=%s,",depth,k,tostring(v))) + handle(format("%s [%q]=%s,",depth,k,v and "true" or "false")) end - elseif t == "function" then + elseif tv == "function" then if functions then local f = getinfo(v).what == "C" and dump(dummy) or dump(v) -- maybe strip -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v) -- maybe strip @@ -619,7 +620,7 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s [%s]=load(%q),",depth,k,f)) end elseif tk == "boolean" then - handle(format("%s [%s]=load(%q),",depth,tostring(k),f)) + handle(format("%s [%s]=load(%q),",depth,k and "true" or "false",f)) elseif noquotes and not reserved[k] and lpegmatch(propername,k) then handle(format("%s %s=load(%q),",depth,k,f)) else @@ -634,7 +635,7 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s [%s]=%q,",depth,k,tostring(v))) end elseif tk == "boolean" then - handle(format("%s [%s]=%q,",depth,tostring(k),tostring(v))) + handle(format("%s [%s]=%q,",depth,k and "true" or "false",tostring(v))) elseif noquotes and not reserved[k] and lpegmatch(propername,k) then handle(format("%s %s=%q,",depth,k,tostring(v))) else @@ -716,321 +717,10 @@ local function serialize(_handle,root,name,specification) -- handle wins handle("}") end --- -- This is some 20% faster than using format (because formatters are much faster) but --- -- of course, inlining the format using .. is then again faster .. anyway, as we do --- -- some pretty printing as well there is not that much to gain unless we make a 'fast' --- -- ugly variant as well. But, we would have to move the formatter to l-string then. - --- local formatters = string.formatters - --- local function do_serialize(root,name,level,indexed) --- if level > 0 then --- if indexed then --- handle(formatters["%w{"](level)) --- else --- local tn = type(name) --- if tn == "number" then --- if hexify then --- handle(formatters["%w[%04H]={"](level,name)) --- else --- handle(formatters["%w[%s]={"](level,name)) --- end --- elseif tn == "string" then --- if noquotes and not reserved[name] and lpegmatch(propername,name) then --- handle(formatters["%w%s={"](level,name)) --- else --- handle(formatters["%w[%q]={"](level,name)) --- end --- elseif tn == "boolean" then --- handle(formatters["%w[%S]={"](level,name)) --- else --- handle(formatters["%w{"](level)) --- end --- end --- end --- -- we could check for k (index) being number (cardinal) --- if root and next(root) then --- -- local first, last = nil, 0 -- #root cannot be trusted here (will be ok in 5.2 when ipairs is gone) --- -- if compact then --- -- -- NOT: for k=1,#root do (we need to quit at nil) --- -- for k,v in ipairs(root) do -- can we use next? --- -- if not first then first = k end --- -- last = last + 1 --- -- end --- -- end --- local first, last = nil, 0 --- if compact then --- last = #root --- for k=1,last do --- if root[k] == nil then --- last = k - 1 --- break --- end --- end --- if last > 0 then --- first = 1 --- end --- end --- local sk = sortedkeys(root) --- for i=1,#sk do --- local k = sk[i] --- local v = root[k] --- --~ if v == root then --- -- circular --- --~ else --- local t, tk = type(v), type(k) --- if compact and first and tk == "number" and k >= first and k <= last then --- if t == "number" then --- if hexify then --- handle(formatters["%w %04H,"](level,v)) --- else --- handle(formatters["%w %s,"](level,v)) -- %.99g --- end --- elseif t == "string" then --- if reduce and tonumber(v) then --- handle(formatters["%w %s,"](level,v)) --- else --- handle(formatters["%w %q,"](level,v)) --- end --- elseif t == "table" then --- if not next(v) then --- handle(formatters["%w {},"](level)) --- elseif inline then -- and #t > 0 --- local st = simple_table(v) --- if st then --- handle(formatters["%w { %, t },"](level,st)) --- else --- do_serialize(v,k,level+1,true) --- end --- else --- do_serialize(v,k,level+1,true) --- end --- elseif t == "boolean" then --- handle(formatters["%w %S,"](level,v)) --- elseif t == "function" then --- if functions then --- handle(formatters['%w load(%q),'](level,dump(v))) -- maybe strip --- else --- handle(formatters['%w "function",'](level)) --- end --- else --- handle(formatters["%w %Q,"](level,v)) --- end --- elseif k == "__p__" then -- parent --- if false then --- handle(formatters["%w __p__=nil,"](level)) --- end --- elseif t == "number" then --- if tk == "number" then --- if hexify then --- handle(formatters["%w [%04H]=%04H,"](level,k,v)) --- else --- handle(formatters["%w [%s]=%s,"](level,k,v)) -- %.99g --- end --- elseif tk == "boolean" then --- if hexify then --- handle(formatters["%w [%S]=%04H,"](level,k,v)) --- else --- handle(formatters["%w [%S]=%s,"](level,k,v)) -- %.99g --- end --- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then --- if hexify then --- handle(formatters["%w %s=%04H,"](level,k,v)) --- else --- handle(formatters["%w %s=%s,"](level,k,v)) -- %.99g --- end --- else --- if hexify then --- handle(formatters["%w [%q]=%04H,"](level,k,v)) --- else --- handle(formatters["%w [%q]=%s,"](level,k,v)) -- %.99g --- end --- end --- elseif t == "string" then --- if reduce and tonumber(v) then --- if tk == "number" then --- if hexify then --- handle(formatters["%w [%04H]=%s,"](level,k,v)) --- else --- handle(formatters["%w [%s]=%s,"](level,k,v)) --- end --- elseif tk == "boolean" then --- handle(formatters["%w [%S]=%s,"](level,k,v)) --- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then --- handle(formatters["%w %s=%s,"](level,k,v)) --- else --- handle(formatters["%w [%q]=%s,"](level,k,v)) --- end --- else --- if tk == "number" then --- if hexify then --- handle(formatters["%w [%04H]=%q,"](level,k,v)) --- else --- handle(formatters["%w [%s]=%q,"](level,k,v)) --- end --- elseif tk == "boolean" then --- handle(formatters["%w [%S]=%q,"](level,k,v)) --- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then --- handle(formatters["%w %s=%q,"](level,k,v)) --- else --- handle(formatters["%w [%q]=%q,"](level,k,v)) --- end --- end --- elseif t == "table" then --- if not next(v) then --- if tk == "number" then --- if hexify then --- handle(formatters["%w [%04H]={},"](level,k)) --- else --- handle(formatters["%w [%s]={},"](level,k)) --- end --- elseif tk == "boolean" then --- handle(formatters["%w [%S]={},"](level,k)) --- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then --- handle(formatters["%w %s={},"](level,k)) --- else --- handle(formatters["%w [%q]={},"](level,k)) --- end --- elseif inline then --- local st = simple_table(v) --- if st then --- if tk == "number" then --- if hexify then --- handle(formatters["%w [%04H]={ %, t },"](level,k,st)) --- else --- handle(formatters["%w [%s]={ %, t },"](level,k,st)) --- end --- elseif tk == "boolean" then --- handle(formatters["%w [%S]={ %, t },"](level,k,st)) --- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then --- handle(formatters["%w %s={ %, t },"](level,k,st)) --- else --- handle(formatters["%w [%q]={ %, t },"](level,k,st)) --- end --- else --- do_serialize(v,k,level+1) --- end --- else --- do_serialize(v,k,level+1) --- end --- elseif t == "boolean" then --- if tk == "number" then --- if hexify then --- handle(formatters["%w [%04H]=%S,"](level,k,v)) --- else --- handle(formatters["%w [%s]=%S,"](level,k,v)) --- end --- elseif tk == "boolean" then --- handle(formatters["%w [%S]=%S,"](level,k,v)) --- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then --- handle(formatters["%w %s=%S,"](level,k,v)) --- else --- handle(formatters["%w [%q]=%S,"](level,k,v)) --- end --- elseif t == "function" then --- if functions then --- local f = getinfo(v).what == "C" and dump(dummy) or dump(v) -- maybe strip --- -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v) -- maybe strip --- if tk == "number" then --- if hexify then --- handle(formatters["%w [%04H]=load(%q),"](level,k,f)) --- else --- handle(formatters["%w [%s]=load(%q),"](level,k,f)) --- end --- elseif tk == "boolean" then --- handle(formatters["%w [%S]=load(%q),"](level,k,f)) --- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then --- handle(formatters["%w %s=load(%q),"](level,k,f)) --- else --- handle(formatters["%w [%q]=load(%q),"](level,k,f)) --- end --- end --- else --- if tk == "number" then --- if hexify then --- handle(formatters["%w [%04H]=%Q,"](level,k,v)) --- else --- handle(formatters["%w [%s]=%Q,"](level,k,v)) --- end --- elseif tk == "boolean" then --- handle(formatters["%w [%S]=%Q,"](level,k,v)) --- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then --- handle(formatters["%w %s=%Q,"](level,k,v)) --- else --- handle(formatters["%w [%q]=%Q,"](level,k,v)) --- end --- end --- --~ end --- end --- end --- if level > 0 then --- handle(formatters["%w}"](level)) --- end --- end - --- local function serialize(_handle,root,name,specification) -- handle wins --- local tname = type(name) --- if type(specification) == "table" then --- noquotes = specification.noquotes --- hexify = specification.hexify --- handle = _handle or specification.handle or print --- reduce = specification.reduce or false --- functions = specification.functions --- compact = specification.compact --- inline = specification.inline and compact --- if functions == nil then --- functions = true --- end --- if compact == nil then --- compact = true --- end --- if inline == nil then --- inline = compact --- end --- else --- noquotes = false --- hexify = false --- handle = _handle or print --- reduce = false --- compact = true --- inline = true --- functions = true --- end --- if tname == "string" then --- if name == "return" then --- handle("return {") --- else --- handle(name .. "={") --- end --- elseif tname == "number" then --- if hexify then --- handle(format("[0x%04X]={",name)) --- else --- handle("[" .. name .. "]={") --- end --- elseif tname == "boolean" then --- if name then --- handle("return {") --- else --- handle("{") --- end --- else --- handle("t={") --- end --- if root then --- -- The dummy access will initialize a table that has a delayed initialization --- -- using a metatable. (maybe explicitly test for metatable) --- if getmetatable(root) then -- todo: make this an option, maybe even per subtable --- local dummy = root._w_h_a_t_e_v_e_r_ --- root._w_h_a_t_e_v_e_r_ = nil --- end --- -- Let's forget about empty tables. --- if next(root) then --- do_serialize(root,name,0) --- end --- end --- handle("}") --- end +-- A version with formatters is some 20% faster than using format (because formatters are +-- much faster) but of course, inlining the format using .. is then again faster .. anyway, +-- as we do some pretty printing as well there is not that much to gain unless we make a +-- 'fast' ugly variant as well. But, we would have to move the formatter to l-string then. -- name: -- diff --git a/tex/context/base/lpdf-ano.lua b/tex/context/base/lpdf-ano.lua index adfea3812..990e87abd 100644 --- a/tex/context/base/lpdf-ano.lua +++ b/tex/context/base/lpdf-ano.lua @@ -334,13 +334,38 @@ end -- runners and specials +-- runners["inner"] = function(var,actions) +-- if getinnermethod() == "names" then +-- local vi = var.i +-- if vi then +-- local vir = vi.references +-- if vir then +-- local internal = vir.internal +-- if internal then +-- var.inner = "aut:" .. internal +-- end +-- end +-- end +-- else +-- var.inner = nil +-- end +-- local prefix = var.p +-- local inner = var.inner +-- if inner and prefix and prefix ~= "" then +-- inner = prefix .. ":" .. inner -- might not always be ok +-- end +-- return link(nil,nil,inner,var.r,actions) +-- end + runners["inner"] = function(var,actions) + local internal = false if getinnermethod() == "names" then local vi = var.i if vi then local vir = vi.references if vir then - local internal = vir.internal + -- todo: no need for it when we have a real reference + internal = vir.internal if internal then var.inner = "aut:" .. internal end @@ -351,8 +376,9 @@ runners["inner"] = function(var,actions) end local prefix = var.p local inner = var.inner - if inner and prefix and prefix ~= "" then - inner = prefix .. ":" .. inner -- might not always be ok + if not internal and inner and prefix and prefix ~= "" then + -- no prefix with e.g. components + inner = prefix .. ":" .. inner end return link(nil,nil,inner,var.r,actions) end diff --git a/tex/context/base/math-act.lua b/tex/context/base/math-act.lua index 4f9b3b7e8..ddc4de179 100644 --- a/tex/context/base/math-act.lua +++ b/tex/context/base/math-act.lua @@ -10,6 +10,7 @@ if not modules then modules = { } end modules ['math-act'] = { local type, next = type, next local fastcopy = table.fastcopy +local formatters = string.formatters local trace_defining = false trackers.register("math.defining", function(v) trace_defining = v end) local report_math = logs.reporter("mathematics","initializing") @@ -286,7 +287,7 @@ end sequencers.appendaction("aftercopyingcharacters", "system","mathematics.overloaddimensions") --- a couple of predefined tewaks: +-- a couple of predefined tweaks: local tweaks = { } mathematics.tweaks = tweaks @@ -295,6 +296,79 @@ function tweaks.fixbadprime(target,original) target.characters[0xFE325] = target.characters[0x2032] end +local function accent_to_extensible(target,newchr,original,oldchr,height,depth) + local characters = target.characters +-- if not characters[newchr] then + local olddata = characters[oldchr] + if olddata then + height = height or 0 + depth = depth or 0 + local addprivate = fonts.helpers.addprivate + local correction = { "down", olddata.height } + local newdata = { + commands = { correction, { "slot", 1, oldchr } }, + width = olddata.width, + height = height, + depth = depth, + } + characters[newchr] = newdata + local nextglyph = olddata.next + while nextglyph do + local oldnextdata = characters[nextglyph] + local newnextdata = { + commands = { correction, { "slot", 1, nextglyph } }, + width = oldnextdata.width, + height = height, + depth = depth, + } + local newnextglyph = addprivate(target,formatters["overline-%H"](nextglyph),newnextdata) + newdata.next = newnextglyph + local nextnextglyph = oldnextdata.next + if nextnextglyph == nextglyph then + break + else + olddata = oldnextdata + newdata = newnextdata + nextglyph = nextnextglyph + end + end + local hv = olddata.horiz_variants + if hv then + hv = fastcopy(hv) + newdata.horiz_variants = hv + for i=1,#hv do + local hvi = hv[i] + local oldglyph = hvi.glyph + local olddata = characters[oldglyph] + local newdata = { + commands = { correction, { "slot", 1, oldglyph } }, + width = olddata.width, + height = height, + depth = depth, + } + hvi.glyph = addprivate(target,formatters["overline-%H"](oldglyph),newdata) + end + end + end +-- end +end + +function tweaks.fixoverline(target,original) + local height, depth = 0, 0 + local mathparameters = target.mathparameters + if mathparameters then + height = mathparameters.OverbarVerticalGap + depth = mathparameters.UnderbarVerticalGap + else + height = target.parameters.xheight/4 + depth = height + end + accent_to_extensible(target,0x203E,original,0x0305,height,depth) +-- inspect(fonts.helpers.expandglyph(target.characters,0x203E)) +end + +sequencers.appendaction("aftercopyingcharacters", "system","mathematics.tweaks.fixoverline") -- for the moment always + -- helpers local setmetatableindex = table.setmetatableindex diff --git a/tex/context/base/math-ini.lua b/tex/context/base/math-ini.lua index 076a56184..6e667d083 100644 --- a/tex/context/base/math-ini.lua +++ b/tex/context/base/math-ini.lua @@ -322,14 +322,14 @@ local function utfmathclass(chr, default) return cd and cd.mathclass or default or "unknown" end -local function utfmathaccent(chr,default,asked) +local function utfmathaccent(chr,default,asked1,asked2) local cd = chardata[utfbyte(chr)] if not cd then return default or false end - if asked then + if asked1 and asked1 ~= "" then local mc = cd.mathclass - if mc and mc == asked then + if mc and (mc == asked1 or mc == asked2) then return true end local ms = cd.mathspec @@ -337,7 +337,7 @@ local function utfmathaccent(chr,default,asked) for i=1,#ms do local msi = ms[i] local mc = msi.class - if mc and mc == asked then + if mc and (mc == asked1 or mc == asked2) then return true end end @@ -366,7 +366,7 @@ local function utfmathstretch(chr, default) -- "h", "v", "b", "" return cd and cd.mathstretch or default or "" end -local function utfmathcommand(chr,default,asked) +local function utfmathcommand(chr,default,asked1,asked2) -- local cd = chardata[utfbyte(chr)] -- local cmd = cd and cd.mathname -- return cmd or default or "" @@ -374,10 +374,10 @@ local function utfmathcommand(chr,default,asked) if not cd then return default or "" end - if asked then + if asked1 then local mn = cd.mathname local mc = cd.mathclass - if mn and mc and mc == asked then + if mn and mc and (mc == asked1 or mc == asked2) then return mn end local ms = cd.mathspec @@ -385,7 +385,7 @@ local function utfmathcommand(chr,default,asked) for i=1,#ms do local msi = ms[i] local mn = msi.name - if mn and msi.class == asked then + if mn and (msi.class == asked1 or msi.class == asked2) then return mn end end @@ -431,6 +431,17 @@ function commands.doifelseutfmathaccent(chr,asked) commands.doifelse(utfmathaccent(chr,nil,asked)) end +function commands.utfmathcommandabove(asked) context(utfmathcommand(asked,nil,"topaccent","over" )) end +function commands.utfmathcommandbelow(asked) context(utfmathcommand(asked,nil,"botaccent","under")) end + +function commands.doifelseutfmathabove(chr) + commands.doifelse(utfmathaccent(chr,nil,asked,"topaccent","over")) +end + +function commands.doifelseutfmathbelow(chr) + commands.doifelse(utfmathaccent(chr,nil,asked,"botaccent","under")) +end + -- helpers function mathematics.big(tfmdata,unicode,n) diff --git a/tex/context/base/math-ini.mkiv b/tex/context/base/math-ini.mkiv index 81ec339d6..d777bb018 100644 --- a/tex/context/base/math-ini.mkiv +++ b/tex/context/base/math-ini.mkiv @@ -277,9 +277,15 @@ \def\utfmathclassfiltered #1#2{\ctxcommand{utfmathclass (\!!bs#1\!!es,nil,"#2")}} \def\utfmathcommandfiltered#1#2{\ctxcommand{utfmathcommand(\!!bs#1\!!es,nil,"#2")}} +\def\utfmathcommandabove#1{\ctxcommand{utfmathcommandabove(\!!bs#1\!!es)}} +\def\utfmathcommandbelow#1{\ctxcommand{utfmathcommandbelow(\!!bs#1\!!es)}} + \unexpanded\def\doifelseutfmathaccent #1{\ctxcommand{doifelseutfmathaccent(\!!bs#1\!!es)}} \unexpanded\def\doifelseutfmathaccentfiltered#1#2{\ctxcommand{doifelseutfmathaccent(\!!bs#1\!!es,"#2")}} +\unexpanded\def\doifelseutfmathabove #1{\ctxcommand{doifelseutfmathabove(\!!bs#1\!!es)}} +\unexpanded\def\doifelseutfmathbelow #1{\ctxcommand{doifelseutfmathbelow(\!!bs#1\!!es)}} + %D Not used that much: \installcorenamespace{mathcodecommand} diff --git a/tex/context/base/math-stc.mkvi b/tex/context/base/math-stc.mkvi index 2dc2b2c22..8d5b1d18f 100644 --- a/tex/context/base/math-stc.mkvi +++ b/tex/context/base/math-stc.mkvi @@ -568,7 +568,7 @@ \definemathstackers [\v!bottom] [\v!mathematics] - [\c!location=\v!top, + [\c!location=\v!top, % ? \c!strut=\v!no, \c!middlecommand=\mathematics, \c!hoffset=\zeropoint] @@ -667,6 +667,22 @@ \definemathunderextensible [\v!bottom] [undertwoheadleftarrow] ["27F8] \definemathunderextensible [\v!bottom] [undertwoheadrightarrow] ["27F9] +% We don't use overline and underline. This is one of the overlooked aspects of +% unicode cq. opentype math: why treat rules different than e.g. arrows and +% accents. It is a bit unfortunate that the opportunity to move math to new +% technologies happened outside the tex domain (and/or some aspects were kept +% while in fact they were side effects of limitations of traditional fonts). +% From the unicode aware tex engines' implementation point of view things +% could have been done a bit nicer but then: the community didn't seem to care +% too much and just has to follow now. +% +% Anyhow, we use a character based approach so that at least we get unicode +% stuff in the backend (okay, we still need to deal with some cut and paste +% issues but at least we now know what we deal with. + +\definemathunderextensible [\v!bottom] [underbar] ["203E] +\definemathoverextensible [\v!top] [overbar] ["203E] + %D Some bonus ones (for the moment here): \definemathstackers diff --git a/tex/context/base/node-fin.lua b/tex/context/base/node-fin.lua index 2e62ebcb5..63a5ef83e 100644 --- a/tex/context/base/node-fin.lua +++ b/tex/context/base/node-fin.lua @@ -41,93 +41,13 @@ local unsetvalue = attributes.unsetvalue -- these two will be like trackers -function states.enabletriggering() - triggering = true -end -function states.disabletriggering() - triggering = false -end - --- the following code is no longer needed due to the new backend --- but we keep it around for a while as an example --- --- states.collected = states.collected or { } --- --- storage.register("states/collected", states.collected, "states.collected") --- --- local collected = states.collected --- --- function states.collect(str) --- collected[#collected+1] = str --- end --- --- function states.flush() --- if #collected > 0 then --- for i=1,#collected do --- context(collected[i]) -- we're in context mode anyway --- end --- collected = { } --- states.collected = collected --- end --- end --- --- function states.check() --- logs.report("states",concat(collected,"\n")) --- end - --- we used to do the main processor loop here and call processor for each node --- but eventually this was too much a slow down (1 sec on 23 for 120 pages mk) --- so that we moved looping to the processor itself; this may lead to a bit of --- duplicate code once that we have more state handlers - --- local function process_attribute(head,plugin) -- head,attribute,enabled,initializer,resolver,processor,finalizer --- local namespace = plugin.namespace --- if namespace.enabled ~= false then -- this test will go away --- starttiming(attributes) -- in principle we could delegate this to the main caller --- local done, used, ok = false, nil, false --- local attribute = namespace.attribute or numbers[plugin.name] -- todo: plugin.attribute --- local processor = plugin.processor --- if processor then --- local initializer = plugin.initializer --- local resolver = plugin.resolver --- local inheritance = (resolver and resolver()) or nil -- -0x7FFFFFFF -- we can best use nil and skip ! --- if initializer then --- initializer(namespace,attribute,head) --- end --- head, ok = processor(namespace,attribute,head,inheritance) --- if ok then --- local finalizer = plugin.finalizer --- if finalizer then --- head, ok, used = finalizer(namespace,attribute,head) --- if used then --- local flusher = plugin.flusher --- if flusher then --- head = flusher(namespace,attribute,head,used) --- end --- end --- end --- done = true --- end --- end --- stoptiming(attributes) --- return head, done --- else --- return head, false --- end --- end --- --- function nodes.installattributehandler(plugin) -- we need to avoid this nested function --- return function(head) --- return process_attribute(head,plugin) --- end --- end - --- An experiment: lean and mean functions. It is not really faster but --- with upcoming functionality it might make a difference, e.g. features --- like 'casing' and 'italics' can be called a lot so there it makes sense. +function states.enabletriggering () triggering = true end +function states.disabletriggering() triggering = false end nodes.plugindata = nil +-- inheritance: -0x7FFFFFFF -- we can best use nil and skip ! + local template = [[ local plugin = nodes.plugindata local starttiming = statistics.starttiming @@ -146,8 +66,10 @@ if not processor then elseif initializer or finalizer or resolver then return function(head) starttiming(attributes) - local done, used, ok = false, nil, false - local inheritance = (resolver and resolver()) or nil -- -0x7FFFFFFF -- we can best use nil and skip ! + local done, used, ok, inheritance = false, nil, false, nil + if resolver then + inheritance = resolver() + end if initializer then initializer(namespace,attribute,head) end @@ -228,309 +150,6 @@ end -- we need to deal with literals too (reset as well as oval) -- if id == glyph_code or (id == whatsit_code and stack.subtype == pdfliteral_code) or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then --- local function process(namespace,attribute,head,inheritance,default) -- one attribute --- local stack, done = head, false --- while stack do --- local id = stack.id --- if id == glyph_code or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code --- local c = stack[attribute] --- if c then --- if default and c == inheritance then --- if current ~= default then --- head = insert_node_before(head,stack,copy_node(nsdata[default])) --- current = default --- done = true --- end --- elseif current ~= c then --- head = insert_node_before(head,stack,copy_node(nsdata[c])) --- current = c --- done = true --- end --- -- here ? compare selective --- if id == glue_code then --leader --- -- same as *list --- local content = stack.leader --- if content then --- local savedcurrent = current --- local ci = content.id --- if ci == hlist_code or ci == vlist_code then --- -- else we reset inside a box unneeded, okay, the downside is --- -- that we trigger color in each repeated box, so there is room --- -- for improvement here --- current = 0 --- end --- local ok = false --- if nstrigger and stack[nstrigger] then --- local outer = stack[attribute] --- if outer ~= inheritance then --- stack.leader, ok = process(namespace,attribute,content,inheritance,outer) --- else --- stack.leader, ok = process(namespace,attribute,content,inheritance,default) --- end --- else --- stack.leader, ok = process(namespace,attribute,content,inheritance,default) --- end --- current = savedcurrent --- done = done or ok --- end --- end --- elseif default and inheritance then --- if current ~= default then --- head = insert_node_before(head,stack,copy_node(nsdata[default])) --- current = default --- done = true --- end --- elseif current > 0 then --- head = insert_node_before(head,stack,copy_node(nsnone)) --- current = 0 --- done = true --- end --- elseif id == hlist_code or id == vlist_code then --- local content = stack.list --- if content then --- local ok = false --- if nstrigger and stack[nstrigger] then --- local outer = stack[attribute] --- if outer ~= inheritance then --- stack.list, ok = process(namespace,attribute,content,inheritance,outer) --- else --- stack.list, ok = process(namespace,attribute,content,inheritance,default) --- end --- else --- stack.list, ok = process(namespace,attribute,content,inheritance,default) --- end --- done = done or ok --- end --- end --- stack = stack.next --- end --- return head, done --- end - --- local function process(namespace,attribute,head,inheritance,default) -- one attribute --- local stack, done = head, false - --- local function check() --- local c = stack[attribute] --- if c then --- if default and c == inheritance then --- if current ~= default then --- head = insert_node_before(head,stack,copy_node(nsdata[default])) --- current = default --- done = true --- end --- elseif current ~= c then --- head = insert_node_before(head,stack,copy_node(nsdata[c])) --- current = c --- done = true --- end --- elseif default and inheritance then --- if current ~= default then --- head = insert_node_before(head,stack,copy_node(nsdata[default])) --- current = default --- done = true --- end --- elseif current > 0 then --- head = insert_node_before(head,stack,copy_node(nsnone)) --- current = 0 --- done = true --- end --- return c --- end - --- local function nested(content) --- if nstrigger and stack[nstrigger] then --- local outer = stack[attribute] --- if outer ~= inheritance then --- return process(namespace,attribute,content,inheritance,outer) --- else --- return process(namespace,attribute,content,inheritance,default) --- end --- else --- return process(namespace,attribute,content,inheritance,default) --- end --- end - --- while stack do --- local id = stack.id --- if id == glyph_code then --- check() --- elseif id == glue_code then --- local content = stack.leader --- if content and check() then --- local savedcurrent = current --- local ci = content.id --- if ci == hlist_code or ci == vlist_code then --- -- else we reset inside a box unneeded, okay, the downside is --- -- that we trigger color in each repeated box, so there is room --- -- for improvement here --- current = 0 --- end - --- local ok = false --- stack.leader, ok = nested(content) --- done = done or ok - --- current = savedcurrent --- end --- elseif id == hlist_code or id == vlist_code then --- local content = stack.list --- if content then - --- local ok = false --- stack.list, ok = nested(content) --- done = done or ok - --- end --- elseif id == rule_code then --- if stack.width ~= 0 then --- check() --- end --- end --- stack = stack.next --- end --- return head, done --- end - --- local function process(namespace,attribute,head,inheritance,default) -- one attribute --- local stack, done = head, false --- while stack do --- local id = stack.id --- if id == glyph_code then --- -- begin of check --- local c = stack[attribute] --- if c then --- if default and c == inheritance then --- if current ~= default then --- head = insert_node_before(head,stack,copy_node(nsdata[default])) --- current = default --- done = true --- end --- elseif current ~= c then --- head = insert_node_before(head,stack,copy_node(nsdata[c])) --- current = c --- done = true --- end --- elseif default and inheritance then --- if current ~= default then --- head = insert_node_before(head,stack,copy_node(nsdata[default])) --- current = default --- done = true --- end --- elseif current > 0 then --- head = insert_node_before(head,stack,copy_node(nsnone)) --- current = 0 --- done = true --- end --- -- end of check --- elseif id == glue_code then --- local content = stack.leader --- if content then --- -- begin of check --- local c = stack[attribute] --- if c then --- if default and c == inheritance then --- if current ~= default then --- head = insert_node_before(head,stack,copy_node(nsdata[default])) --- current = default --- done = true --- end --- elseif current ~= c then --- head = insert_node_before(head,stack,copy_node(nsdata[c])) --- current = c --- done = true --- end --- -- begin special to this check --- local savedcurrent = current --- local ci = content.id --- if ci == hlist_code or ci == vlist_code then --- -- else we reset inside a box unneeded, okay, the downside is --- -- that we trigger color in each repeated box, so there is room --- -- for improvement here --- current = 0 --- end --- -- begin nested -- --- local ok = false --- if nstrigger and stack[nstrigger] then --- local outer = stack[attribute] --- if outer ~= inheritance then --- stack.leader, ok = process(namespace,attribute,content,inheritance,outer) --- else --- stack.leader, ok = process(namespace,attribute,content,inheritance,default) --- end --- else --- stack.leader, ok = process(namespace,attribute,content,inheritance,default) --- end --- -- end nested -- --- done = done or ok --- current = savedcurrent --- -- end special to this check --- elseif default and inheritance then --- if current ~= default then --- head = insert_node_before(head,stack,copy_node(nsdata[default])) --- current = default --- done = true --- end --- elseif current > 0 then --- head = insert_node_before(head,stack,copy_node(nsnone)) --- current = 0 --- done = true --- end --- -- end of check --- end --- elseif id == hlist_code or id == vlist_code then --- local content = stack.list --- if content then --- -- begin nested -- --- local ok --- if nstrigger and stack[nstrigger] then --- local outer = stack[attribute] --- if outer ~= inheritance then --- stack.list, ok = process(namespace,attribute,content,inheritance,outer) --- else --- stack.list, ok = process(namespace,attribute,content,inheritance,default) --- end --- else --- stack.list, ok = process(namespace,attribute,content,inheritance,default) --- end --- -- end nested -- --- done = done or ok --- end --- elseif id == rule_code then --- if stack.width ~= 0 then --- -- begin of check --- local c = stack[attribute] --- if c then --- if default and c == inheritance then --- if current ~= default then --- head = insert_node_before(head,stack,copy_node(nsdata[default])) --- current = default --- done = true --- end --- elseif current ~= c then --- head = insert_node_before(head,stack,copy_node(nsdata[c])) --- current = c --- done = true --- end --- elseif default and inheritance then --- if current ~= default then --- head = insert_node_before(head,stack,copy_node(nsdata[default])) --- current = default --- done = true --- end --- elseif current > 0 then --- head = insert_node_before(head,stack,copy_node(nsnone)) --- current = 0 --- done = true --- end --- -- end of check --- end --- end --- stack = stack.next --- end --- return head, done --- end - local function process(namespace,attribute,head,inheritance,default) -- one attribute local stack = head local done = false @@ -633,184 +252,6 @@ states.process = process -- state changes while the main state stays the same (like two glyphs following -- each other with the same color but different color spaces e.g. \showcolor) --- local function selective(namespace,attribute,head,inheritance,default) -- two attributes --- local stack, done = head, false --- while stack do --- local id = stack.id --- -- we need to deal with literals too (reset as well as oval) --- -- if id == glyph_code or (id == whatsit_code and stack.subtype == pdfliteral_code) or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code --- if id == glyph_code -- or id == disc_code --- or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code --- local c = stack[attribute] --- if c then --- if default and c == inheritance then --- if current ~= default then --- local data = nsdata[default] --- head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector])) --- current = default --- done = true --- end --- else --- local s = stack[nsselector] --- if current ~= c or current_selector ~= s then --- local data = nsdata[c] --- head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector])) --- current = c --- current_selector = s --- done = true --- end --- end --- elseif default and inheritance then --- if current ~= default then --- local data = nsdata[default] --- head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector])) --- current = default --- done = true --- end --- elseif current > 0 then --- head = insert_node_before(head,stack,copy_node(nsnone)) --- current, current_selector, done = 0, 0, true --- end --- if id == glue_code then -- leader --- -- same as *list --- local content = stack.leader --- if content then --- local savedcurrent = current --- local ci = content.id --- if ci == hlist_code or ci == vlist_code then --- -- else we reset inside a box unneeded, okay, the downside is --- -- that we trigger color in each repeated box, so there is room --- -- for improvement here --- current = 0 --- end --- local ok = false --- if nstrigger and stack[nstrigger] then --- local outer = stack[attribute] --- if outer ~= inheritance then --- stack.leader, ok = selective(namespace,attribute,content,inheritance,outer) --- else --- stack.leader, ok = selective(namespace,attribute,content,inheritance,default) --- end --- else --- stack.leader, ok = selective(namespace,attribute,content,inheritance,default) --- end --- current = savedcurrent --- done = done or ok --- end --- end --- elseif id == hlist_code or id == vlist_code then --- local content = stack.list --- if content then --- local ok = false --- if nstrigger and stack[nstrigger] then --- local outer = stack[attribute] --- if outer ~= inheritance then --- stack.list, ok = selective(namespace,attribute,content,inheritance,outer) --- else --- stack.list, ok = selective(namespace,attribute,content,inheritance,default) --- end --- else --- stack.list, ok = selective(namespace,attribute,content,inheritance,default) --- end --- done = done or ok --- end --- end --- stack = stack.next --- end --- return head, done --- end - --- local function selective(namespace,attribute,head,inheritance,default) -- two attributes --- local stack, done = head, false - --- local function check() --- local c = stack[attribute] --- if c then --- if default and c == inheritance then --- if current ~= default then --- local data = nsdata[default] --- head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector])) --- current = default --- done = true --- end --- else --- local s = stack[nsselector] --- if current ~= c or current_selector ~= s then --- local data = nsdata[c] --- head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector])) --- current = c --- current_selector = s --- done = true --- end --- end --- elseif default and inheritance then --- if current ~= default then --- local data = nsdata[default] --- head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector])) --- current = default --- done = true --- end --- elseif current > 0 then --- head = insert_node_before(head,stack,copy_node(nsnone)) --- current, current_selector, done = 0, 0, true --- end --- return c --- end - --- local function nested(content) --- if nstrigger and stack[nstrigger] then --- local outer = stack[attribute] --- if outer ~= inheritance then --- return selective(namespace,attribute,content,inheritance,outer) --- else --- return selective(namespace,attribute,content,inheritance,default) --- end --- else --- return selective(namespace,attribute,content,inheritance,default) --- end --- end - --- while stack do --- local id = stack.id --- if id == glyph_code then --- check() --- elseif id == glue_code then --- local content = stack.leader --- if content and check() then --- -- local savedcurrent = current --- -- local ci = content.id --- -- if ci == hlist_code or ci == vlist_code then --- -- -- else we reset inside a box unneeded, okay, the downside is --- -- -- that we trigger color in each repeated box, so there is room --- -- -- for improvement here --- -- current = 0 --- -- end - --- local ok = false --- stack.leader, ok = nested(content) --- done = done or ok - --- -- current = savedcurrent --- end --- elseif id == hlist_code or id == vlist_code then --- local content = stack.list --- if content then - --- local ok = false --- stack.list, ok = nested(content) --- done = done or ok - --- end --- elseif id == rule_code then --- if stack.width ~= 0 then --- check() --- end --- end --- stack = stack.next --- end --- return head, done --- end - local function selective(namespace,attribute,head,inheritance,default) -- two attributes local stack = head local done = false @@ -914,77 +355,6 @@ states.selective = selective -- Todo: make a better stacker. Keep track (in attribute) about nesting level. Not -- entirely trivial and a generic solution is nicer (compares to the exporter). --- local function stacked(namespace,attribute,head,default) -- no triggering, no inheritance, but list-wise --- local stack, done = head, false --- local current, depth = default or 0, 0 --- --- local function check() --- local a = stack[attribute] --- if a then --- if current ~= a then --- head = insert_node_before(head,stack,copy_node(nsdata[a])) --- depth = depth + 1 --- current, done = a, true --- end --- elseif default > 0 then --- -- --- elseif current > 0 then --- head = insert_node_before(head,stack,copy_node(nsnone)) --- depth = depth - 1 --- current, done = 0, true --- end --- return a --- end --- --- while stack do --- local id = stack.id --- if id == glyph_code then --- check() --- elseif id == glue_code then --- local content = stack.leader --- if content and check() then --- local ok = false --- stack.leader, ok = stacked(namespace,attribute,content,current) --- done = done or ok --- end --- elseif id == hlist_code or id == vlist_code then --- local content = stack.list --- if content then --- -- the problem is that broken lines gets the attribute which can be a later one --- if nslistwise then --- local a = stack[attribute] --- if a and current ~= a and nslistwise[a] then -- viewerlayer / needs checking, see below --- local p = current --- current, done = a, true --- head = insert_node_before(head,stack,copy_node(nsdata[a])) --- stack.list = stacked(namespace,attribute,content,current) --- head, stack = insert_node_after(head,stack,copy_node(nsnone)) --- current = p --- else --- local ok = false --- stack.list, ok = stacked(namespace,attribute,content,current) --- done = done or ok --- end --- else --- local ok = false --- stack.list, ok = stacked(namespace,attribute,content,current) --- done = done or ok --- end --- end --- elseif id == rule_code then --- if stack.width ~= 0 then --- check() --- end --- end --- stack = stack.next --- end --- while depth > 0 do --- head = insert_node_after(head,stack,copy_node(nsnone)) --- depth = depth - 1 --- end --- return head, done --- end - local function stacked(namespace,attribute,head,default) -- no triggering, no inheritance, but list-wise local stack = head local done = false @@ -1066,76 +436,6 @@ states.stacked = stacked -- experimental --- local function stacker(namespace,attribute,head,default) -- no triggering, no inheritance, but list-wise --- nsbegin() --- local current, previous, done, okay = head, head, false, false --- local attrib = default or unsetvalue --- --- local function check() --- local a = current[attribute] or unsetvalue --- if a ~= attrib then --- local n = nsstep(a) --- if n then --- -- !!!! TEST CODE !!!! --- -- head = insert_node_before(head,current,copy_node(nsdata[tonumber(n)])) -- a --- head = insert_node_before(head,current,n) -- a --- end --- attrib, done, okay = a, true, true --- end --- return a --- end --- --- while current do --- local id = current.id --- if id == glyph_code then --- check() --- elseif id == glue_code then --- local content = current.leader --- if content and check() then --- -- tricky as a leader has to be a list so we cannot inject before --- local _, ok = stacker(namespace,attribute,content,attrib) --- done = done or ok --- end --- elseif id == hlist_code or id == vlist_code then --- local content = current.list --- if not content then --- -- skip --- elseif nslistwise then --- local a = current[attribute] --- if a and attrib ~= a and nslistwise[a] then -- viewerlayer --- done = true --- head = insert_node_before(head,current,copy_node(nsdata[a])) --- current.list = stacker(namespace,attribute,content,a) --- head, current = insert_node_after(head,current,copy_node(nsnone)) --- else --- local ok = false --- current.list, ok = stacker(namespace,attribute,content,attrib) --- done = done or ok --- end --- else --- local ok = false --- current.list, ok = stacker(namespace,attribute,content,default) --- done = done or ok --- end --- elseif id == rule_code then --- if current.width ~= 0 then --- check() --- end --- end --- previous = current --- current = current.next --- end --- if okay then --- local n = nsend() --- if n then --- -- !!!! TEST CODE !!!! --- -- head = insert_node_after(head,previous,copy_node(nsdata[tostring(n)])) --- head = insert_node_after(head,previous,n) --- end --- end --- return head, done --- end - local function stacker(namespace,attribute,head,default) -- no triggering, no inheritance, but list-wise nsbegin() local current = head diff --git a/tex/context/base/node-pro.lua b/tex/context/base/node-pro.lua index 7bfcf6d4a..b98292abb 100644 --- a/tex/context/base/node-pro.lua +++ b/tex/context/base/node-pro.lua @@ -118,6 +118,9 @@ local enabled = true function processors.hpack_filter(head,groupcode,size,packtype,direction) if enabled then + -- if not head.next and head.id ~= glyph_code then -- happens often but not faster + -- return true + -- end local first, found = first_glyph(head) -- they really need to be glyphs if found then if trace_callbacks then diff --git a/tex/context/base/node-rul.mkiv b/tex/context/base/node-rul.mkiv index 640cc54fe..2d2e61134 100644 --- a/tex/context/base/node-rul.mkiv +++ b/tex/context/base/node-rul.mkiv @@ -185,9 +185,14 @@ % \definebar[touchbar] [\c!method=0,\c!dy=-0.4,\c!offset=-0.0] % \definebar[touchbars] [touchbar] [\c!continue=\v!yes] -\definebar[\v!overstrike][\c!method=0,\c!dy=0.4,\c!offset=0.5,\c!continue=\v!yes] -\definebar[\v!underbar] [\c!method=1,\c!dy=-0.4,\c!offset=-0.3,\c!continue=\v!yes] +\let\normalmathoverbar \overbar +\let\normalmathunderbar \underbar +\let\normalmathoverstrike \overstrike +\let\normalmathunderstrike\understrike + \definebar[\v!overbar] [\c!method=1,\c!dy=0.4,\c!offset=1.8,\c!continue=\v!yes] +\definebar[\v!underbar] [\c!method=1,\c!dy=-0.4,\c!offset=-0.3,\c!continue=\v!yes] +\definebar[\v!overstrike][\c!method=0,\c!dy=0.4,\c!offset=0.5,\c!continue=\v!yes] \definebar [\v!understrike] @@ -198,16 +203,41 @@ \c!order=\v!background, \c!color=lightgray] -\definebar[\v!overstrikes] [\v!overstrike] [\c!continue=\v!no] -\definebar[\v!underbars] [\v!underbar] [\c!continue=\v!no] \definebar[\v!overbars] [\v!overbar] [\c!continue=\v!no] +\definebar[\v!underbars] [\v!underbar] [\c!continue=\v!no] +\definebar[\v!overstrikes] [\v!overstrike] [\c!continue=\v!no] \definebar[\v!understrikes][\v!understrike][\c!continue=\v!no] % we want these always so ... -\expandafter\let\expandafter\overstrike \csname\v!overstrike \endcsname -\expandafter\let\expandafter\underbar \csname\v!underbar \endcsname -\expandafter\let\expandafter\overbar \csname\v!overbar \endcsname +\ifdefined\normalmathunderbar + \expandafter\let\expandafter\normaltextunderbar\csname\v!underbar\endcsname + \unexpanded\def\underbar{\mathortext\normalmathunderbar\normaltextunderbar} +\else + \expandafter\let\expandafter\underbar\csname\v!underbar\endcsname +\fi + +\ifdefined\normalmathoverbar + \expandafter\let\expandafter\normaltextoverbar\csname\v!overbar\endcsname + \unexpanded\def\overbar{\mathortext\normalmathoverbar\normaltextoverbar} +\else + \expandafter\let\expandafter\overbar\csname\v!overbar\endcsname +\fi + +\ifdefined\normalmathunderstrike + \expandafter\let\expandafter\normaltextunderstrike\csname\v!understrike\endcsname + \unexpanded\def\understrike{\mathortext\normalmathunderstrike\normaltextunderstrike} +\else + \expandafter\let\expandafter\understrike\csname\v!understrike\endcsname +\fi + +\ifdefined\normalmathoverstrike + \expandafter\let\expandafter\normaltextoverstrike\csname\v!overstrike\endcsname + \unexpanded\def\overstrike{\mathortext\normalmathoverstrike \normaltextoverstrike} +\else + \expandafter\let\expandafter\overstrike\csname\v!overstrike\endcsname +\fi + \expandafter\let\expandafter\overstrikes\csname\v!overstrikes\endcsname \expandafter\let\expandafter\underbars \csname\v!underbars \endcsname \expandafter\let\expandafter\overbars \csname\v!overbars \endcsname diff --git a/tex/context/base/spac-ver.mkiv b/tex/context/base/spac-ver.mkiv index ee78d8964..9b74b273a 100644 --- a/tex/context/base/spac-ver.mkiv +++ b/tex/context/base/spac-ver.mkiv @@ -913,7 +913,7 @@ \s!depth \strutdp}} \def\spac_struts_set_vide - {\setbox\strutbox\hbox + {\setbox\strutbox\hbox % at some time this extra wrapping was needed {\spac_struts_vide_hbox to \zeropoint {% \hss % new, will be option \vrule @@ -939,8 +939,8 @@ \unexpanded\def\strut % still callbacks for \hbox{\strut} {\relax - \dontleavehmode - \copy\strutbox} + \dontleavehmode + \copy\strutbox} \let\normalstrut\strut diff --git a/tex/context/base/status-files.pdf b/tex/context/base/status-files.pdf index c4de827c9..022b6158e 100644 Binary files a/tex/context/base/status-files.pdf and b/tex/context/base/status-files.pdf differ diff --git a/tex/context/base/status-lua.pdf b/tex/context/base/status-lua.pdf index 1c9fabde3..8c4c25ffa 100644 Binary files a/tex/context/base/status-lua.pdf and b/tex/context/base/status-lua.pdf differ diff --git a/tex/context/base/strc-ref.lua b/tex/context/base/strc-ref.lua index 03ae94823..8e65a6b19 100644 --- a/tex/context/base/strc-ref.lua +++ b/tex/context/base/strc-ref.lua @@ -1799,7 +1799,7 @@ function filters.generic.number(data,what,prefixspec) -- todo: spec and then no sections.typesetnumber(numberdata,"number",numberdata) else local useddata = data.useddata - if useddata and useddsta.number then + if useddata and useddata.number then context(useddata.number) end end diff --git a/tex/context/base/trac-vis.lua b/tex/context/base/trac-vis.lua index df4909c3e..762c71ab5 100644 --- a/tex/context/base/trac-vis.lua +++ b/tex/context/base/trac-vis.lua @@ -158,7 +158,7 @@ local preset_all = preset_makeup + modes.fontkern + modes.whatsit + modes.gly function visualizers.setfont(id) usedfont = id or current_font() exheight = exheights[usedfont] - emwidth = emwidths[usedfont] + emwidth = emwidths[usedfont] end -- we can preset a bunch of bits @@ -204,18 +204,12 @@ local function setvisual(n,a,what) -- this will become more efficient when we ha a = preset_makeup else a = setbit(a,preset_makeup) - -- for i=1,#modes_makeup do - -- a = setvisual(modes_makeup[i],a) - -- end end elseif n == "boxes" then if not a or a == 0 or a == unsetvalue then a = preset_boxes else a = setbit(a,preset_boxes) - -- for i=1,#modes_boxes do - -- a = setvisual(modes_boxes[i],a) - -- end end elseif n == "all" then if what == false then @@ -224,9 +218,6 @@ local function setvisual(n,a,what) -- this will become more efficient when we ha a = preset_all else a = setbit(a,preset_all) - -- for i=1,#modes_all do - -- a = setvisual(modes_all[i],a) - -- end end else local m = modes[n] @@ -522,12 +513,12 @@ local function ruledbox(head,current,vertical,layer,what,simple) next.prev = info end if prev then -if prev.id == gluespec_code then - -- weird, how can this happen, an inline glue-spec -else - info.prev = prev - prev.next = info -end + if prev.id == gluespec_code then + -- weird, how can this happen, an inline glue-spec + else + info.prev = prev + prev.next = info + end end if head == current then return info, info @@ -552,6 +543,7 @@ local function ruledglyph(head,current) end local doublelinewidth = 2*linewidth local info = concat_nodes { + -- could be a pdf rule new_rule(linewidth,ht,dp), new_rule(wd-doublelinewidth,-dp+linewidth,dp), new_rule(linewidth,ht,dp), diff --git a/tex/context/base/util-str.lua b/tex/context/base/util-str.lua index 10456a729..0c8c0e2d2 100644 --- a/tex/context/base/util-str.lua +++ b/tex/context/base/util-str.lua @@ -735,11 +735,17 @@ strings.formatters.add = add -- registered in the default instance (should we fall back on this one?) -lpeg.patterns.xmlescape = Cs((P("<")/"<" + P(">")/">" + P("&")/"&" + P('"')/""" + P(1))^0) -lpeg.patterns.texescape = Cs((C(S("#$%\\{}"))/"\\%1" + P(1))^0) +patterns.xmlescape = Cs((P("<")/"<" + P(">")/">" + P("&")/"&" + P('"')/""" + P(1))^0) +patterns.texescape = Cs((C(S("#$%\\{}"))/"\\%1" + P(1))^0) +patterns.luaescape = Cs(((1-S('"\n'))^1 + P('"')/'\\"' + P('\n')/'\\n"')^0) -- maybe also \0 +patterns.luaquoted = Cs(Cc('"') * ((1-S('"\n'))^1 + P('"')/'\\"' + P('\n')/'\\n"')^0 * Cc('"')) -add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],[[local xmlescape = lpeg.patterns.xmlescape]]) -add(formatters,"tex",[[lpegmatch(texescape,%s)]],[[local texescape = lpeg.patterns.texescape]]) +-- escaping by lpeg is faster for strings without quotes, slower on a string with quotes, but +-- faster again when other q-escapables are found (the ones we don't need to escape) + +add(formatters,"xml", [[lpegmatch(xmlescape,%s)]],[[local xmlescape = lpeg.patterns.xmlescape]]) +add(formatters,"tex", [[lpegmatch(texescape,%s)]],[[local texescape = lpeg.patterns.texescape]]) +add(formatters,"lua", [[lpegmatch(luaescape,%s)]],[[local luaescape = lpeg.patterns.luaescape]]) -- -- yes or no: -- diff --git a/tex/context/base/util-tab.lua b/tex/context/base/util-tab.lua index a47c0cb77..b7db4fa84 100644 --- a/tex/context/base/util-tab.lua +++ b/tex/context/base/util-tab.lua @@ -15,7 +15,7 @@ local concat, insert, remove = table.concat, table.insert, table.remove local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring local type, next, rawset, tonumber, tostring, load, select = type, next, rawset, tonumber, tostring, load, select local lpegmatch, P, Cs, Cc = lpeg.match, lpeg.P, lpeg.Cs, lpeg.Cc -local serialize, sortedkeys, sortedpairs = table.serialize, table.sortedkeys, table.sortedpairs +local sortedkeys, sortedpairs = table.sortedkeys, table.sortedpairs local formatters = string.formatters local splitter = lpeg.tsplitat(".") @@ -293,100 +293,66 @@ function tables.encapsulate(core,capsule,protect) end end -local function fastserialize(t,r,outer) -- no mixes - r[#r+1] = "{" - local n = #t - if n > 0 then - for i=1,n do - local v = t[i] - local tv = type(v) - if tv == "string" then - r[#r+1] = formatters["%q,"](v) - elseif tv == "number" then - r[#r+1] = formatters["%s,"](v) - elseif tv == "table" then - fastserialize(v,r) - elseif tv == "boolean" then - r[#r+1] = formatters["%S,"](v) +-- we no longer have %q in keys as for this kind of tables we can +-- assume sane keys + +local f_hashed_string = formatters["[%s]=%q,"] +local f_hashed_number = formatters["[%s]=%s,"] +local f_hashed_boolean = formatters["[%s]=%l,"] +local f_hashed_table = formatters["[%s]="] + +local f_indexed_string = formatters["%q,"] +local f_indexed_number = formatters["%s,"] +local f_indexed_boolean = formatters["%l,"] + +function table.fastserialize(t,prefix) -- so prefix should contain the = | not sorted + + local r = { prefix or "return" } + local m = 1 + + local function fastserialize(t,outer) -- no mixes + local n = #t + m = m + 1 + r[m] = "{" + if n > 0 then + for i=1,n do + local v = t[i] + local tv = type(v) + if tv == "string" then + m = m + 1 r[m] = f_indexed_string(v) + elseif tv == "number" then + m = m + 1 r[m] = f_indexed_number(v) + elseif tv == "table" then + fastserialize(v) + elseif tv == "boolean" then + m = m + 1 r[m] = f_indexed_boolean(v) + end end - end - else - for k, v in next, t do - local tv = type(v) - if tv == "string" then - r[#r+1] = formatters["[%q]=%q,"](k,v) - elseif tv == "number" then - r[#r+1] = formatters["[%q]=%s,"](k,v) - elseif tv == "table" then - r[#r+1] = formatters["[%q]="](k) - fastserialize(v,r) - elseif tv == "boolean" then - r[#r+1] = formatters["[%q]=%S,"](k,v) + else + for k, v in next, t do + local tv = type(v) + if tv == "string" then + m = m + 1 r[m] = f_hashed_string(k,v) + elseif tv == "number" then + m = m + 1 r[m] = f_hashed_number(k,v) + elseif tv == "table" then + m = m + 1 r[m] = f_hashed_table(k) + fastserialize(v) + elseif tv == "boolean" then + m = m + 1 r[m] = f_hashed_boolean(k,v) + end end end + m = m + 1 + if outer then + r[m] = "}" + else + r[m] = "}," + end + return r end - if outer then - r[#r+1] = "}" - else - r[#r+1] = "}," - end - return r -end - --- local f_hashed_string = formatters["[%q]=%q,"] --- local f_hashed_number = formatters["[%q]=%s,"] --- local f_hashed_table = formatters["[%q]="] --- local f_hashed_true = formatters["[%q]=true,"] --- local f_hashed_false = formatters["[%q]=false,"] --- --- local f_indexed_string = formatters["%q,"] --- local f_indexed_number = formatters["%s,"] --- ----- f_indexed_true = formatters["true,"] --- ----- f_indexed_false = formatters["false,"] --- --- local function fastserialize(t,r,outer) -- no mixes --- r[#r+1] = "{" --- local n = #t --- if n > 0 then --- for i=1,n do --- local v = t[i] --- local tv = type(v) --- if tv == "string" then --- r[#r+1] = f_indexed_string(v) --- elseif tv == "number" then --- r[#r+1] = f_indexed_number(v) --- elseif tv == "table" then --- fastserialize(v,r) --- elseif tv == "boolean" then --- -- r[#r+1] = v and f_indexed_true(k) or f_indexed_false(k) --- r[#r+1] = v and "true," or "false," --- end --- end --- else --- for k, v in next, t do --- local tv = type(v) --- if tv == "string" then --- r[#r+1] = f_hashed_string(k,v) --- elseif tv == "number" then --- r[#r+1] = f_hashed_number(k,v) --- elseif tv == "table" then --- r[#r+1] = f_hashed_table(k) --- fastserialize(v,r) --- elseif tv == "boolean" then --- r[#r+1] = v and f_hashed_true(k) or f_hashed_false(k) --- end --- end --- end --- if outer then --- r[#r+1] = "}" --- else --- r[#r+1] = "}," --- end --- return r --- end -function table.fastserialize(t,prefix) -- so prefix should contain the = - return concat(fastserialize(t,{ prefix or "return" },true)) + return concat(fastserialize(t,true)) end function table.deserialize(str) @@ -422,10 +388,14 @@ function table.load(filename,loader) end function table.save(filename,t,n,...) - io.savedata(filename,serialize(t,n == nil and true or n,...)) + io.savedata(filename,table.serialize(t,n == nil and true or n,...)) -- no frozen table.serialize end -local function slowdrop(t) +local f_key_value = formatters["%s=%q"] +local f_add_table = formatters[" {%t},\n"] +local f_return_table = formatters["return {\n%t}"] + +local function slowdrop(t) -- maybe less memory (intermediate concat) local r = { } local l = { } for i=1,#t do @@ -433,28 +403,30 @@ local function slowdrop(t) local j = 0 for k, v in next, ti do j = j + 1 - l[j] = formatters["%s=%q"](k,v) + l[j] = f_key_value(k,v) end - r[i] = formatters[" {%t},\n"](l) + r[i] = f_add_table(l) end - return formatters["return {\n%st}"](r) + return f_return_table(r) end local function fastdrop(t) local r = { "return {\n" } + local m = 1 for i=1,#t do local ti = t[i] - r[#r+1] = " {" + m = m + 1 r[m] = " {" for k, v in next, ti do - r[#r+1] = formatters["%s=%q"](k,v) + m = m + 1 r[m] = f_key_value(k,v) end - r[#r+1] = "},\n" + m = m + 1 r[m] = "},\n" end - r[#r+1] = "}" + m = m + 1 + r[m] = "}" return concat(r) end -function table.drop(t,slow) -- only { { a=2 }, {a=3} } +function table.drop(t,slow) -- only { { a=2 }, {a=3} } -- for special cases if #t == 0 then return "return { }" elseif slow == true then @@ -464,6 +436,9 @@ function table.drop(t,slow) -- only { { a=2 }, {a=3} } end end +-- inspect(table.drop({ { a=2 }, {a=3} })) +-- inspect(table.drop({ { a=2 }, {a=3} },true)) + function table.autokey(t,k) local v = { } t[k] = v @@ -491,3 +466,244 @@ function table.twowaymapper(t) return t end +-- The next version is somewhat faster, although in practice one will seldom +-- serialize a lot using this one. Often the above variants are more efficient. +-- If we would really need this a lot, we could hash q keys. + +-- char-def.lua : 0.53 -> 0.38 +-- husayni.tma : 0.28 -> 0.19 + +local f_start_key_idx = formatters["%w{"] +local f_start_key_num = formatters["%w[%s]={"] +local f_start_key_str = formatters["%w[%q]={"] +local f_start_key_boo = formatters["%w[%l]={"] +local f_start_key_nop = formatters["%w{"] + +local f_stop = formatters["%w},"] + +local f_key_num_value_num = formatters["%w[%s]=%s,"] +local f_key_str_value_num = formatters["%w[%q]=%s,"] +local f_key_boo_value_num = formatters["%w[%l]=%s,"] + +local f_key_num_value_str = formatters["%w[%s]=%q,"] +local f_key_str_value_str = formatters["%w[%q]=%q,"] +local f_key_boo_value_str = formatters["%w[%l]=%q,"] + +local f_key_num_value_boo = formatters["%w[%s]=%l,"] +local f_key_str_value_boo = formatters["%w[%q]=%l,"] +local f_key_boo_value_boo = formatters["%w[%l]=%l,"] + +local f_key_num_value_not = formatters["%w[%s]={},"] +local f_key_str_value_not = formatters["%w[%q]={},"] +local f_key_boo_value_not = formatters["%w[%l]={},"] + +local f_key_num_value_seq = formatters["%w[%s]={ %, t },"] +local f_key_str_value_seq = formatters["%w[%q]={ %, t },"] +local f_key_boo_value_seq = formatters["%w[%l]={ %, t },"] + +local f_val_num = formatters["%w%s,"] +local f_val_str = formatters["%w%q,"] +local f_val_boo = formatters["%w%l,"] +local f_val_not = formatters["%w{},"] +local f_val_seq = formatters["%w{ %, t },"] + +local f_table_return = formatters["return {"] +local f_table_name = formatters["%s={"] +local f_table_direct = formatters["{"] +local f_table_entry = formatters["[%q]={"] +local f_table_finish = formatters["}"] + +----- f_string = formatters["%q"] + +local spaces = utilities.strings.newrepeater(" ") + +local serialize = table.serialize -- the extensive one, the one we started with + +function table.serialize(root,name,specification) + + if specification then + return serialize(root,name,specification) -- the original one + end + + local t -- = { } + local n = 1 + + local function simple_table(t) + if #t > 0 then + local n = 0 + for _, v in next, t do + n = n + 1 + if type(v) == "table" then + return nil + end + end + if n == #t then + local tt = { } + local nt = 0 + for i=1,#t do + local v = t[i] + local tv = type(v) + nt = nt + 1 + if tv == "number" then + tt[nt] = v + elseif tv == "string" then + tt[nt] = format("%q",v) -- f_string(v) + elseif tv == "boolean" then + tt[nt] = v and "true" or "false" + else + return nil + end + end + return tt + end + end + return nil + end + + local function do_serialize(root,name,depth,level,indexed) + if level > 0 then + n = n + 1 + if indexed then + t[n] = f_start_key_idx(depth) + else + local tn = type(name) + if tn == "number" then + t[n] = f_start_key_num(depth,name) + elseif tn == "string" then + t[n] = f_start_key_str(depth,name) + elseif tn == "boolean" then + t[n] = f_start_key_boo(depth,name) + else + t[n] = f_start_key_nop(depth) + end + end + depth = depth + 1 + end + -- we could check for k (index) being number (cardinal) + if root and next(root) then + local first = nil + local last = 0 + last = #root + for k=1,last do + if root[k] == nil then + last = k - 1 + break + end + end + if last > 0 then + first = 1 + end + local sk = sortedkeys(root) -- inline fast version? + for i=1,#sk do + local k = sk[i] + local v = root[k] + local tv = type(v) + local tk = type(k) + if first and tk == "number" and k >= first and k <= last then + if tv == "number" then + n = n + 1 t[n] = f_val_num(depth,v) + elseif tv == "string" then + n = n + 1 t[n] = f_val_str(depth,v) + elseif tv == "table" then + if not next(v) then + n = n + 1 t[n] = f_val_not(depth) + else + local st = simple_table(v) + if st then + n = n + 1 t[n] = f_val_seq(depth,st) + else + do_serialize(v,k,depth,level+1,true) + end + end + elseif tv == "boolean" then + n = n + 1 t[n] = f_val_boo(depth,v) + end + elseif tv == "number" then + if tk == "number" then + n = n + 1 t[n] = f_key_num_value_num(depth,k,v) + elseif tk == "string" then + n = n + 1 t[n] = f_key_str_value_num(depth,k,v) + elseif tk == "boolean" then + n = n + 1 t[n] = f_key_boo_value_num(depth,k,v) + end + elseif tv == "string" then + if tk == "number" then + n = n + 1 t[n] = f_key_num_value_str(depth,k,v) + elseif tk == "string" then + n = n + 1 t[n] = f_key_str_value_str(depth,k,v) + elseif tk == "boolean" then + n = n + 1 t[n] = f_key_boo_value_str(depth,k,v) + end + elseif tv == "table" then + if not next(v) then + if tk == "number" then + n = n + 1 t[n] = f_key_num_value_not(depth,k,v) + elseif tk == "string" then + n = n + 1 t[n] = f_key_str_value_not(depth,k,v) + elseif tk == "boolean" then + n = n + 1 t[n] = f_key_boo_value_not(depth,k,v) + end + else + local st = simple_table(v) + if not st then + do_serialize(v,k,depth,level+1) + elseif tk == "number" then + n = n + 1 t[n] = f_key_num_value_seq(depth,k,st) + elseif tk == "string" then + n = n + 1 t[n] = f_key_str_value_seq(depth,k,st) + elseif tk == "boolean" then + n = n + 1 t[n] = f_key_boo_value_seq(depth,k,st) + end + end + elseif tv == "boolean" then + if tk == "number" then + n = n + 1 t[n] = f_key_num_value_boo(depth,k,v) + elseif tk == "string" then + n = n + 1 t[n] = f_key_str_value_boo(depth,k,v) + elseif tk == "boolean" then + n = n + 1 t[n] = f_key_boo_value_boo(depth,k,v) + end + end + end + end + if level > 0 then + n = n + 1 t[n] = f_stop(depth-1) + end + end + + local tname = type(name) + + if tname == "string" then + if name == "return" then + t = { f_table_return() } + else + t = { f_table_name(name) } + end + elseif tname == "number" then + t = { f_table_entry(name) } + elseif tname == "boolean" then + if name then + t = { f_table_return() } + else + t = { f_table_direct() } + end + else + t = { f_table_name("t") } + end + + if root then + -- The dummy access will initialize a table that has a delayed initialization + -- using a metatable. (maybe explicitly test for metatable) + if getmetatable(root) then -- todo: make this an option, maybe even per subtable + local dummy = root._w_h_a_t_e_v_e_r_ + root._w_h_a_t_e_v_e_r_ = nil + end + -- Let's forget about empty tables. + if next(root) then + do_serialize(root,name,1,0) + end + end + n = n + 1 + t[n] = f_table_finish() + return concat(t,"\n") +end diff --git a/tex/context/base/util-tpl.lua b/tex/context/base/util-tpl.lua index 511076b8d..dcc4c1216 100644 --- a/tex/context/base/util-tpl.lua +++ b/tex/context/base/util-tpl.lua @@ -18,7 +18,7 @@ local report_template = logs.reporter("template") local tostring = tostring local format, sub = string.format, string.sub -local P, C, Cs, Carg, lpegmatch = lpeg.P, lpeg.C, lpeg.Cs, lpeg.Carg, lpeg.match +local P, C, Cs, Carg, lpegmatch, lpegpatterns = lpeg.P, lpeg.C, lpeg.Cs, lpeg.Carg, lpeg.match, lpeg.patterns -- todo: make installable template.new @@ -52,7 +52,10 @@ local sqlescape = lpeg.replacer { -- { "\t", "\\t" }, } -local sqlquotedescape = lpeg.Cs(lpeg.Cc("'") * sqlescape * lpeg.Cc("'")) +local sqlquoted = lpeg.Cs(lpeg.Cc("'") * sqlescape * lpeg.Cc("'")) + +lpegpatterns.sqlescape = sqlescape +lpegpatterns.sqlquoted = sqlquoted -- escapeset : \0\1\2\3\4\5\6\7\8\9\10\11\12\13\14\15\16\17\18\19\20\21\22\23\24\25\26\27\28\29\30\31\"\\\127 -- test string: [[1\0\31test23"\\]] .. string.char(19) .. "23" @@ -78,9 +81,16 @@ local sqlquotedescape = lpeg.Cs(lpeg.Cc("'") * sqlescape * lpeg.Cc("'")) -- P(1) -- )^0) +-- local xmlescape = lpegpatterns.xmlescape +-- local texescape = lpegpatterns.texescape +-- local luaescape = lpegpatterns.luaescape +-- local sqlquoted = lpegpatterns.sqlquoted +-- local luaquoted = lpegpatterns.luaquoted + local escapers = { lua = function(s) - return sub(format("%q",s),2,-2) + -- return sub(format("%q",s),2,-2) + return lpegmatch(luaescape,s) end, sql = function(s) return lpegmatch(sqlescape,s) @@ -89,16 +99,14 @@ local escapers = { local quotedescapers = { lua = function(s) + -- return lpegmatch(luaquoted,s) return format("%q",s) end, sql = function(s) - return lpegmatch(sqlquotedescape,s) + return lpegmatch(sqlquoted,s) end, } -lpeg.patterns.sqlescape = sqlescape -lpeg.patterns.sqlquotedescape = sqlquotedescape - local luaescaper = escapers.lua local quotedluaescaper = quotedescapers.lua diff --git a/tex/context/base/x-mathml.mkiv b/tex/context/base/x-mathml.mkiv index a4eb09467..5d70d8d3f 100644 --- a/tex/context/base/x-mathml.mkiv +++ b/tex/context/base/x-mathml.mkiv @@ -1,4 +1,4 @@ -%D \module +%D \modul %D [ file=x-mathml, %D version=2008.05.29, %D title=\CONTEXT\ XML Modules, @@ -1785,25 +1785,23 @@ \stopxmlsetups % PRESENTATION MATHML -% -% there are some rough edges that need to be sorted out - -% helpers - -\xmlmapvalue {mml} {normal} {\tf} -\xmlmapvalue {mml} {double-struck} {\bf} -\xmlmapvalue {mml} {italic} {\it} -\xmlmapvalue {mml} {fraktur} {\bf} -\xmlmapvalue {mml} {script} {\tf} -\xmlmapvalue {mml} {bold} {\bf} -\xmlmapvalue {mml} {bold-italic} {\bi} -\xmlmapvalue {mml} {bold-fraktur} {\bf} -\xmlmapvalue {mml} {bold-script} {\bf} -\xmlmapvalue {mml} {sans-serif} {\ss} -\xmlmapvalue {mml} {bold-sans-serif} {\ss\bf} -\xmlmapvalue {mml} {sans-serif-italic} {\ss\it} -\xmlmapvalue {mml} {sans-serif-bold-italic} {\ss\bi} -\xmlmapvalue {mml} {monospace} {\tt} + +% helpers: maybe we can need a setting for the uprights + +\xmlmapvalue {mml} {normal} {\mathupright} % {\mathtf} +\xmlmapvalue {mml} {double-struck} {\mathblackboard} +\xmlmapvalue {mml} {italic} {\mathit} +\xmlmapvalue {mml} {fraktur} {\mathfraktur} +\xmlmapvalue {mml} {script} {\mathscript} +\xmlmapvalue {mml} {bold} {\mb} % {\mathbf} +\xmlmapvalue {mml} {bold-italic} {\mathbi} +\xmlmapvalue {mml} {bold-fraktur} {\mathfraktur\mathbf} +\xmlmapvalue {mml} {bold-script} {\mathscript\mathbf} +\xmlmapvalue {mml} {sans-serif} {\mathss} +\xmlmapvalue {mml} {bold-sans-serif} {\mathss\mathbf} +\xmlmapvalue {mml} {sans-serif-italic} {\mathss\mathit} +\xmlmapvalue {mml} {sans-serif-bold-italic} {\mathss\mathbi} +\xmlmapvalue {mml} {monospace} {\mathtt} % todo: displaystyle=true/false (or whatever else shows up) @@ -1863,15 +1861,15 @@ % setups -\startxmlsetups mml:mi % todo: mathvariant mathsize mathcolor mathbackground - \ctxmodulemathml{mi("#1")} +\startxmlsetups mml:mi % todo: mathsize (unlikely) mathcolor (easy) mathbackground (easy) + \begingroup + \setmmlmathstyle{#1} + \ctxmodulemathml{mi("#1")} + \endgroup \stopxmlsetups -\startxmlsetups mml:mn % todo: mathvariant mathsize mathcolor mathbackground -% \begingroup -% \mr - \ctxmodulemathml{mn("#1")}% no \hbox, would be ok for . , but spoils rest -% \endgroup +\startxmlsetups mml:mn + \ctxmodulemathml{mn("#1")}% no \hbox, would be ok for . , but spoils rest \stopxmlsetups % -2 and 1-2 @@ -2134,6 +2132,8 @@ % brrr no { } when limop .. todo: better in lua % speed up with ifx and setups or just in lua +\let\mmlnucleus\relax + \startxmlsetups mml:msub \edef\mmlnucleus{\xmlraw{#1}{/mml:*[1]}} \doifelse {\utfmathclass\mmlnucleus} {limop} { @@ -2183,10 +2183,12 @@ \fi\fi {\csname#1\endcsname}} +% todo: combine topaccent/over/bottomaccent/under check + \startxmlsetups mml:mover \edef\mmlovertoken{\xmlraw{#1}{/mml:*[2]}} - \doifelseutfmathaccentfiltered\mmlovertoken{topaccent} {% not ok - \edef\mmlovercommand{\utfmathcommandfiltered\mmlovertoken{topaccent}} + \doifelseutfmathabove\mmlovertoken {% not ok + \edef\mmlovercommand{\utfmathcommandabove\mmlovertoken} \mmlexecuteifdefined\mmlovercommand\mathematics{\mmlfirst{#1}} } { \edef\mmlbasetoken{\xmlraw{#1}{/mml:*[1]}} @@ -2212,29 +2214,27 @@ % messy: (_ \startxmlsetups mml:munder -% \mathop { - \edef\mmlundertoken{\xmlraw{#1}{/mml:*[2]}} - \doifelseutfmathaccentfiltered\mmlundertoken{botaccent} { - \edef\mmlundercommand{\utfmathcommandfiltered\mmlundertoken{botaccent}} - \mmlexecuteifdefined\mmlundercommand\mathematics{\mmlfirst{#1}} - } { - \edef\mmlbasetoken {\xmlraw{#1}{/mml:*[1]}} - \edef\mmlbasecommand {\utfmathfiller\mmlbasetoken} - \edef\mmlundercommand{\utfmathfiller\mmlundertoken} - \vtop { - \mathsurround\zeropoint \ialign { - \hss$##$\hss - \crcr - \mmlexecuteifdefined\mmlbasecommand {\mmlfirst{#1}} - \crcr - \noalign{\kern3\onepoint\nointerlineskip}% - \mmlexecuteifdefined\mmlundercommand{\mmlsecond{#1}} - \crcr - \noalign{\kern3\onepoint} - } + \edef\mmlundertoken{\xmlraw{#1}{/mml:*[2]}} + \doifelseutfmathbelow\mmlundertoken { + \edef\mmlundercommand{\utfmathcommandbelow\mmlundertoken} + \mmlexecuteifdefined\mmlundercommand\mathematics{\mmlfirst{#1}} + } { + \edef\mmlbasetoken {\xmlraw{#1}{/mml:*[1]}} + \edef\mmlbasecommand {\utfmathfiller\mmlbasetoken} + \edef\mmlundercommand{\utfmathfiller\mmlundertoken} + \vtop { + \mathsurround\zeropoint \ialign { + \hss$##$\hss + \crcr + \mmlexecuteifdefined\mmlbasecommand {\mmlfirst{#1}} + \crcr + \noalign{\kern3\onepoint\nointerlineskip}% + \mmlexecuteifdefined\mmlundercommand{\mmlsecond{#1}} + \crcr + \noalign{\kern3\onepoint} } } -% } + } % \limits % spoils spacing \stopxmlsetups diff --git a/tex/context/fonts/lm.lfg b/tex/context/fonts/lm.lfg index 792e723e8..7fad13afd 100644 --- a/tex/context/fonts/lm.lfg +++ b/tex/context/fonts/lm.lfg @@ -11,12 +11,13 @@ return { tweaks = { aftercopying = { mathematics.tweaks.fixbadprime, -- prime is too low + -- mathematics.tweaks.fixoverline, }, }, dimensions = { -- always applied --- default = { --- }, + -- default = { + -- }, -- driven by 'mathdimensions' feature signs = { -- set dimensions diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index 3f3294c4a..81e3fec30 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 : luatex-fonts-merged.lua -- parent file : luatex-fonts.lua --- merge date : 06/07/13 12:25:27 +-- merge date : 06/10/13 12:24:08 do -- begin closure to overcome local limits and interference @@ -1085,12 +1085,12 @@ local function simple_table(t) else tt[nt]=tostring(v) end - elseif tv=="boolean" then - nt=nt+1 - tt[nt]=tostring(v) elseif tv=="string" then nt=nt+1 tt[nt]=format("%q",v) + elseif tv=="boolean" then + nt=nt+1 + tt[nt]=v and "true" or "false" else tt=nil break @@ -1123,7 +1123,7 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s[%q]={",depth,name)) end elseif tn=="boolean" then - handle(format("%s[%s]={",depth,tostring(name))) + handle(format("%s[%s]={",depth,name and "true" or "false")) else handle(format("%s{",depth)) end @@ -1147,21 +1147,21 @@ local function do_serialize(root,name,depth,level,indexed) for i=1,#sk do local k=sk[i] local v=root[k] - local t,tk=type(v),type(k) + local tv,tk=type(v),type(k) if compact and first and tk=="number" and k>=first and k<=last then - if t=="number" then + if tv=="number" then if hexify then handle(format("%s 0x%04X,",depth,v)) else handle(format("%s %s,",depth,v)) end - elseif t=="string" then + elseif tv=="string" then if reduce and tonumber(v) then handle(format("%s %s,",depth,v)) else handle(format("%s %q,",depth,v)) end - elseif t=="table" then + elseif tv=="table" then if not next(v) then handle(format("%s {},",depth)) elseif inline then @@ -1174,9 +1174,9 @@ local function do_serialize(root,name,depth,level,indexed) else do_serialize(v,k,depth,level+1,true) end - elseif t=="boolean" then - handle(format("%s %s,",depth,tostring(v))) - elseif t=="function" then + elseif tv=="boolean" then + handle(format("%s %s,",depth,v and "true" or "false")) + elseif tv=="function" then if functions then handle(format('%s load(%q),',depth,dump(v))) else @@ -1189,7 +1189,7 @@ local function do_serialize(root,name,depth,level,indexed) if false then handle(format("%s __p__=nil,",depth)) end - elseif t=="number" then + elseif tv=="number" then if tk=="number" then if hexify then handle(format("%s [0x%04X]=0x%04X,",depth,k,v)) @@ -1198,9 +1198,9 @@ local function do_serialize(root,name,depth,level,indexed) end elseif tk=="boolean" then if hexify then - handle(format("%s [%s]=0x%04X,",depth,tostring(k),v)) + handle(format("%s [%s]=0x%04X,",depth,k and "true" or "false",v)) else - handle(format("%s [%s]=%s,",depth,tostring(k),v)) + handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) end elseif noquotes and not reserved[k] and lpegmatch(propername,k) then if hexify then @@ -1215,7 +1215,7 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s [%q]=%s,",depth,k,v)) end end - elseif t=="string" then + elseif tv=="string" then if reduce and tonumber(v) then if tk=="number" then if hexify then @@ -1224,7 +1224,7 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s [%s]=%s,",depth,k,v)) end elseif tk=="boolean" then - handle(format("%s [%s]=%s,",depth,tostring(k),v)) + handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) elseif noquotes and not reserved[k] and lpegmatch(propername,k) then handle(format("%s %s=%s,",depth,k,v)) else @@ -1238,14 +1238,14 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s [%s]=%q,",depth,k,v)) end elseif tk=="boolean" then - handle(format("%s [%s]=%q,",depth,tostring(k),v)) + handle(format("%s [%s]=%q,",depth,k and "true" or "false",v)) elseif noquotes and not reserved[k] and lpegmatch(propername,k) then handle(format("%s %s=%q,",depth,k,v)) else handle(format("%s [%q]=%q,",depth,k,v)) end end - elseif t=="table" then + elseif tv=="table" then if not next(v) then if tk=="number" then if hexify then @@ -1254,7 +1254,7 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s [%s]={},",depth,k)) end elseif tk=="boolean" then - handle(format("%s [%s]={},",depth,tostring(k))) + handle(format("%s [%s]={},",depth,k and "true" or "false")) elseif noquotes and not reserved[k] and lpegmatch(propername,k) then handle(format("%s %s={},",depth,k)) else @@ -1270,7 +1270,7 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s [%s]={ %s },",depth,k,concat(st,", "))) end elseif tk=="boolean" then - handle(format("%s [%s]={ %s },",depth,tostring(k),concat(st,", "))) + handle(format("%s [%s]={ %s },",depth,k and "true" or "false",concat(st,", "))) elseif noquotes and not reserved[k] and lpegmatch(propername,k) then handle(format("%s %s={ %s },",depth,k,concat(st,", "))) else @@ -1282,21 +1282,21 @@ local function do_serialize(root,name,depth,level,indexed) else do_serialize(v,k,depth,level+1) end - elseif t=="boolean" then + elseif tv=="boolean" then if tk=="number" then if hexify then - handle(format("%s [0x%04X]=%s,",depth,k,tostring(v))) + handle(format("%s [0x%04X]=%s,",depth,k,v and "true" or "false")) else - handle(format("%s [%s]=%s,",depth,k,tostring(v))) + handle(format("%s [%s]=%s,",depth,k,v and "true" or "false")) end elseif tk=="boolean" then - handle(format("%s [%s]=%s,",depth,tostring(k),tostring(v))) + handle(format("%s [%s]=%s,",depth,tostring(k),v and "true" or "false")) elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=%s,",depth,k,tostring(v))) + handle(format("%s %s=%s,",depth,k,v and "true" or "false")) else - handle(format("%s [%q]=%s,",depth,k,tostring(v))) + handle(format("%s [%q]=%s,",depth,k,v and "true" or "false")) end - elseif t=="function" then + elseif tv=="function" then if functions then local f=getinfo(v).what=="C" and dump(dummy) or dump(v) if tk=="number" then @@ -1306,7 +1306,7 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s [%s]=load(%q),",depth,k,f)) end elseif tk=="boolean" then - handle(format("%s [%s]=load(%q),",depth,tostring(k),f)) + handle(format("%s [%s]=load(%q),",depth,k and "true" or "false",f)) elseif noquotes and not reserved[k] and lpegmatch(propername,k) then handle(format("%s %s=load(%q),",depth,k,f)) else @@ -1321,7 +1321,7 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s [%s]=%q,",depth,k,tostring(v))) end elseif tk=="boolean" then - handle(format("%s [%s]=%q,",depth,tostring(k),tostring(v))) + handle(format("%s [%s]=%q,",depth,k and "true" or "false",tostring(v))) elseif noquotes and not reserved[k] and lpegmatch(propername,k) then handle(format("%s %s=%q,",depth,k,tostring(v))) else @@ -2926,10 +2926,13 @@ local function add(t,name,template,preamble) end end strings.formatters.add=add -lpeg.patterns.xmlescape=Cs((P("<")/"<"+P(">")/">"+P("&")/"&"+P('"')/"""+P(1))^0) -lpeg.patterns.texescape=Cs((C(S("#$%\\{}"))/"\\%1"+P(1))^0) +patterns.xmlescape=Cs((P("<")/"<"+P(">")/">"+P("&")/"&"+P('"')/"""+P(1))^0) +patterns.texescape=Cs((C(S("#$%\\{}"))/"\\%1"+P(1))^0) +patterns.luaescape=Cs(((1-S('"\n'))^1+P('"')/'\\"'+P('\n')/'\\n"')^0) +patterns.luaquoted=Cs(Cc('"')*((1-S('"\n'))^1+P('"')/'\\"'+P('\n')/'\\n"')^0*Cc('"')) add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],[[local xmlescape = lpeg.patterns.xmlescape]]) add(formatters,"tex",[[lpegmatch(texescape,%s)]],[[local texescape = lpeg.patterns.texescape]]) +add(formatters,"lua",[[lpegmatch(luaescape,%s)]],[[local luaescape = lpeg.patterns.luaescape]]) end -- closure @@ -10100,8 +10103,6 @@ local function featuresprocessor(head,font,attr) else start=start.next end - elseif id==math_code then - start=end_of_math(start).next else start=start.next end -- cgit v1.2.3