diff options
25 files changed, 1381 insertions, 82 deletions
diff --git a/doc/context/documents/general/manuals/luametatex.pdf b/doc/context/documents/general/manuals/luametatex.pdf Binary files differindex d1e920204..25bd874ae 100644 --- a/doc/context/documents/general/manuals/luametatex.pdf +++ b/doc/context/documents/general/manuals/luametatex.pdf diff --git a/doc/context/sources/general/manuals/luametatex/luametatex.tex b/doc/context/sources/general/manuals/luametatex/luametatex.tex index e1e22c482..debfdb358 100644 --- a/doc/context/sources/general/manuals/luametatex/luametatex.tex +++ b/doc/context/sources/general/manuals/luametatex/luametatex.tex @@ -50,9 +50,7 @@  % Thanks to sebastian.miele@gmail.com for close reading the manual and  % sending fixes. -% \enabledirectives[system.usage] - -% \enabletrackers[*] +\enabletrackers[system.usage=summary]  \environment luametatex-style  \environment luametatex-private diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index 3d592f4ed..20642a907 100644 --- a/tex/context/base/mkii/cont-new.mkii +++ b/tex/context/base/mkii/cont-new.mkii @@ -11,7 +11,7 @@  %C therefore copyrighted by \PRAGMA. See mreadme.pdf for  %C details. -\newcontextversion{2020.08.25 19:56} +\newcontextversion{2020.08.27 19:25}  %D This file is loaded at runtime, thereby providing an  %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii index 7c22b1c87..16de426df 100644 --- a/tex/context/base/mkii/context.mkii +++ b/tex/context/base/mkii/context.mkii @@ -20,7 +20,7 @@  %D your styles an modules.  \edef\contextformat {\jobname} -\edef\contextversion{2020.08.25 19:56} +\edef\contextversion{2020.08.27 19:25}  %D For those who want to use this: diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index 40c3c3272..fc27b0538 100644 --- a/tex/context/base/mkiv/cont-new.mkiv +++ b/tex/context/base/mkiv/cont-new.mkiv @@ -13,7 +13,7 @@  % \normalend % uncomment this to get the real base runtime -\newcontextversion{2020.08.25 19:56} +\newcontextversion{2020.08.27 19:25}  %D This file is loaded at runtime, thereby providing an excellent place for hacks,  %D patches, extensions and new features. There can be local overloads in cont-loc @@ -21,6 +21,9 @@  %D so old that I need to remind myself to check it occasionally, so here is the  %D reminder). +% \enabletrackers[pages.timing] +% \enabletrackers[system.usage=summary] +  \unprotect  \writestatus\m!system{beware: some patches loaded from cont-new.mkiv} diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index 092b16960..5164ea5dd 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -45,7 +45,7 @@  %D {YYYY.MM.DD HH:MM} format.  \edef\contextformat {\jobname} -\edef\contextversion{2020.08.25 19:56} +\edef\contextversion{2020.08.27 19:25}  %D Kind of special: diff --git a/tex/context/base/mkiv/context.mkxl b/tex/context/base/mkiv/context.mkxl index 5c6ded5c9..e7d0ffdfd 100644 --- a/tex/context/base/mkiv/context.mkxl +++ b/tex/context/base/mkiv/context.mkxl @@ -29,7 +29,7 @@  %D {YYYY.MM.DD HH:MM} format.  \edef\contextformat {\jobname} -\edef\contextversion{2020.08.25 19:56} +\edef\contextversion{2020.08.27 19:25}  %D Kind of special: diff --git a/tex/context/base/mkiv/font-cff.lua b/tex/context/base/mkiv/font-cff.lua index c2cf0e699..b7d45392d 100644 --- a/tex/context/base/mkiv/font-cff.lua +++ b/tex/context/base/mkiv/font-cff.lua @@ -610,15 +610,15 @@ do        + p_unsupported      )^1 -    parsedictionaries = function(data,dictionaries,what) +    parsedictionaries = function(data,dictionaries,version)          stack   = { }          strings = data.strings          if trace_charstrings then -            report("charstring format %a",what) +            report("charstring format %a",version)          end          for i=1,#dictionaries do              top    = 0 -            result = what == "cff" and { +            result = version == "cff" and {                  monospaced         = false,                  italicangle        = 0,                  underlineposition  = -100, @@ -2265,8 +2265,8 @@ do  end -local function readglobals(f,data) -    local routines = readlengths(f) +local function readglobals(f,data,version) +    local routines = readlengths(f,version == "cff2")      for i=1,#routines do          routines[i] = readbytetable(f,routines[i])      end @@ -2324,14 +2324,14 @@ local function readprivates(f,data)      end  end -local function readlocals(f,data,dictionary) +local function readlocals(f,data,dictionary,version)      local header  = data.header      local private = dictionary.private      if private then          local subroutineoffset = private.data.subroutines          if subroutineoffset ~= 0 then              setposition(f,header.offset+private.offset+subroutineoffset) -            local subroutines = readlengths(f) +            local subroutines = readlengths(f,version == "cff2")              for i=1,#subroutines do                  subroutines[i] = readbytetable(f,subroutines[i])              end @@ -2348,7 +2348,7 @@ end  -- These charstrings are little programs and described in: Technical Note #5177. A truetype  -- font has only one dictionary. -local function readcharstrings(f,data,what) +local function readcharstrings(f,data,version)      local header       = data.header      local dictionaries = data.dictionaries      local dictionary   = dictionaries[1] @@ -2359,7 +2359,7 @@ local function readcharstrings(f,data,what)      elseif stringtype == 2 then          setposition(f,header.offset+offset)          -- could be a metatable .. delayed loading -        local charstrings = readlengths(f,what=="cff2") +        local charstrings = readlengths(f,version=="cff2")          local nofglyphs   = #charstrings          for i=1,nofglyphs do              charstrings[i] = readstring(f,charstrings[i]) @@ -2394,7 +2394,8 @@ readers.parsecharstrings = parsecharstrings -- used in font-onr.lua (type 1)  local function readnoselect(f,fontdata,data,glyphs,doshapes,version,streams)      local dictionaries = data.dictionaries      local dictionary   = dictionaries[1] -    readglobals(f,data) +    local cid          = not dictionary.private and dictionary.cid +    readglobals(f,data,version)      readcharstrings(f,data,version)      if version == "cff2" then          dictionary.charset = nil @@ -2402,9 +2403,27 @@ local function readnoselect(f,fontdata,data,glyphs,doshapes,version,streams)          readencodings(f,data)          readcharsets(f,data,dictionary)      end +    if cid then +        local fdarray = cid.fdarray +        if fdarray then +            setposition(f,data.header.offset + fdarray) +            local dictionaries    = readlengths(f,version=="cff2") +            local nofdictionaries = #dictionaries +            if nofdictionaries > 0 then +                for i=1,nofdictionaries do +                    dictionaries[i] = readstring(f,dictionaries[i]) +                end +                parsedictionaries(data,dictionaries) +                dictionary.private = dictionaries[1].private +                if nofdictionaries > 1 then +                    report("ignoring dictionaries > 1 in cid font") +                end +            end +        end +    end      readprivates(f,data)      parseprivates(data,data.dictionaries) -    readlocals(f,data,dictionary) +    readlocals(f,data,dictionary,version)      startparsing(fontdata,data,streams)      parsecharstrings(fontdata,data,glyphs,doshapes,version,streams)      stopparsing(fontdata,data) @@ -2416,7 +2435,7 @@ local function readfdselect(f,fontdata,data,glyphs,doshapes,version,streams)      local dictionary   = dictionaries[1]      local cid          = dictionary.cid      local cidselect    = cid and cid.fdselect -    readglobals(f,data) +    readglobals(f,data,version)      readcharstrings(f,data,version)      if version ~= "cff2" then          readencodings(f,data) @@ -2462,7 +2481,7 @@ local function readfdselect(f,fontdata,data,glyphs,doshapes,version,streams)          local cidarray = cid.fdarray          if cidarray then              setposition(f,header.offset+cidarray) -            local dictionaries = readlengths(f) +            local dictionaries = readlengths(f,version == "cff2")              for i=1,#dictionaries do                  dictionaries[i] = readstring(f,dictionaries[i])              end @@ -2470,7 +2489,7 @@ local function readfdselect(f,fontdata,data,glyphs,doshapes,version,streams)              cid.dictionaries = dictionaries              readcidprivates(f,data)              for i=1,#dictionaries do -                readlocals(f,data,dictionaries[i]) +                readlocals(f,data,dictionaries[i],version)              end              startparsing(fontdata,data,streams)              for i=1,#charstrings do diff --git a/tex/context/base/mkiv/font-con.lua b/tex/context/base/mkiv/font-con.lua index 495148341..7162338c6 100644 --- a/tex/context/base/mkiv/font-con.lua +++ b/tex/context/base/mkiv/font-con.lua @@ -451,6 +451,7 @@ function constructors.scale(tfmdata,specification)      target.format        = properties.format      target.cache         = constructors.cacheintex and "yes" or "renew"      -- +    local original = properties.original or tfmdata.original      local fontname = properties.fontname or tfmdata.fontname      local fullname = properties.fullname or tfmdata.fullname      local filename = properties.filename or tfmdata.filename @@ -462,6 +463,7 @@ function constructors.scale(tfmdata,specification)      --      local psname, psfixed = fixedpsname(psname,fontname or fullname or file.nameonly(filename))      -- +    target.original = original      target.fontname = fontname      target.fullname = fullname      target.filename = filename diff --git a/tex/context/base/mkiv/font-ctx.lua b/tex/context/base/mkiv/font-ctx.lua index e6ed58492..eec967c1c 100644 --- a/tex/context/base/mkiv/font-ctx.lua +++ b/tex/context/base/mkiv/font-ctx.lua @@ -1221,6 +1221,7 @@ do  -- else too many locals               -- ctx_setemptyfontsize()              end              specification = definers.makespecification(str,lookup,name,sub,method,detail,size) +-- specification.original = str              if trace_defining then                  report_defining("stop stage one")              end @@ -1239,11 +1240,6 @@ do  -- else too many locals          combinefeatures = v      end) - - - - -      implement {          name      = "definefont_two",          arguments = { @@ -1269,7 +1265,6 @@ do  -- else too many locals                          fontdesignsize,  -- \m_font_designsize                          scaledfontmode   -- \scaledfontmode                      ) -              if trace_defining then                  report_defining("start stage two: %s, size %s, features %a & %a, mode %a",str,size,classfeatures,fontfeatures,inheritancemode)              end @@ -1424,6 +1419,7 @@ do  -- else too many locals                      context(function()                          busy = false                          mathematics.finishfallbacks(tfmdata,specification,fallbacks) +tfmdata.original = specification.specification                          local id = definefont(tfmdata)                          csnames[id] = specification.cs                          properties.id = id @@ -1461,6 +1457,7 @@ do  -- else too many locals                      end)                      return                  else +tfmdata.original = specification.specification                      local id = definefont(tfmdata)                      csnames[id] = specification.cs                      properties.id = id diff --git a/tex/context/base/mkiv/font-def.lua b/tex/context/base/mkiv/font-def.lua index 09f2e2c32..b752b3258 100644 --- a/tex/context/base/mkiv/font-def.lua +++ b/tex/context/base/mkiv/font-def.lua @@ -489,7 +489,9 @@ function definers.read(specification,size,id) -- id can be optional, name can al          end      else          tfmdata = definers.loadfont(specification) -- can be overloaded +-- put in properties instead          if tfmdata then +            tfmdata.original = specification.specification              if trace_defining then                  report_defining("loaded and hashed: %s",hash)              end diff --git a/tex/context/base/mkiv/node-aux.lmt b/tex/context/base/mkiv/node-aux.lmt new file mode 100644 index 000000000..9e7c02028 --- /dev/null +++ b/tex/context/base/mkiv/node-aux.lmt @@ -0,0 +1,396 @@ +if not modules then modules = { } end modules ['node-aux'] = { +    version   = 1.001, +    comment   = "companion to node-ini.mkiv", +    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL", +    copyright = "PRAGMA ADE / ConTeXt Development Team", +    license   = "see context related readme files" +} + +-- todo: n1 .. n2 : __concat metatable + +local type, tostring = type, tostring + +local nodes              = nodes +local context            = context + +local utfvalues          = utf.values + +local nodecodes          = nodes.nodecodes + +local glyph_code         = nodecodes.glyph +local hlist_code         = nodecodes.hlist +local vlist_code         = nodecodes.vlist +local attributelist_code = nodecodes.attributelist -- temporary +local localpar_code      = nodecodes.localpar + +local nuts               = nodes.nuts +local tonut              = nuts.tonut +local tonode             = nuts.tonode +local vianuts            = nuts.vianuts + +local getbox             = nuts.getbox +local getnext            = nuts.getnext +local getid              = nuts.getid +local getsubtype         = nuts.getsubtype +local getlist            = nuts.getlist +local getattr            = nuts.getattr +local getboth            = nuts.getboth +local getprev            = nuts.getprev +local getwidth           = nuts.getwidth +local setwidth           = nuts.setwidth +local getboxglue         = nuts.getboxglue +local setboxglue         = nuts.setboxglue + +local setfield           = nuts.setfield +local setattr            = nuts.setattr +local setlink            = nuts.setlink +local setlist            = nuts.setlist +local setnext            = nuts.setnext +local setprev            = nuts.setprev +local setattrlist        = nuts.setattrlist + +local traversers         = nuts.traversers +local nextnode           = traversers.node +local nextglyph          = traversers.glyph + +local flush_node         = nuts.flush +local flush_list         = nuts.flush_list +local hpack_nodes        = nuts.hpack +local unset_attribute    = nuts.unset_attribute +local first_glyph        = nuts.first_glyph +local copy_node          = nuts.copy +local find_tail          = nuts.tail +local getbox             = nuts.getbox +local count              = nuts.count +local isglyph            = nuts.isglyph + +local nodepool           = nuts.pool +local new_glue           = nodepool.glue +local new_glyph          = nodepool.glyph + +local unsetvalue         = attributes.unsetvalue + +local current_font       = font.current + +local texsetbox          = tex.setbox + +local report_error       = logs.reporter("node-aux:error") + +local function takebox(id) +    local box = getbox(id) +    if box then +        local list = getlist(box) +        setlist(box,nil) +        local copy = copy_node(box) +        if list then +            setlist(copy,list) +        end +        texsetbox(id,false) +        return copy +    end +end + +function nodes.takebox(id) +    local b = takebox(id) +    if b then +        return tonode(b) +    end +end + +local splitbox = tex.splitbox +nodes.splitbox = splitbox + +function nuts.splitbox(id,height) +    return tonut(splitbox(id,height)) +end + +-- function nodes.takelist(n) +--     -- when we need it +-- end + +function nuts.takelist(n) +    local l = getlist(n) +    setlist(n) +    flush_node(n) +    return l +end + +nuts.takebox = takebox +tex.takebox  = nodes.takebox -- sometimes more clear + +-- so far + +local function repackhlist(list,...) +    local temp, b = hpack_nodes(list,...) +    list = getlist(temp) +    setlist(temp) +    flush_node(temp) +    return list, b +end + +nuts.repackhlist = repackhlist + +function nodes.repackhlist(list,...) +    local list, b = repackhlist(tonut(list),...) +    return tonode(list), b +end + +local function set_attributes(head,attr,value) +    for n, id in nextnode, head do +        setattr(n,attr,value) +        if id == hlist_node or id == vlist_node then +            set_attributes(getlist(n),attr,value) +        end +    end +end + +local function set_unset_attributes(head,attr,value) +    for n, id in nextnode, head do +        if not getattr(n,attr) then +            setattr(n,attr,value) +        end +        if id == hlist_code or id == vlist_code then +            set_unset_attributes(getlist(n),attr,value) +        end +    end +end + +local function unset_attributes(head,attr) +    for n, id in nextnode, head do +        setattr(n,attr,unsetvalue) +        if id == hlist_code or id == vlist_code then +            unset_attributes(getlist(n),attr) +        end +    end +end + +-- for old times sake + +nuts.setattribute        = nuts.setattr                      nodes.setattribute       = nodes.setattr +nuts.getattribute        = nuts.getattr                      nodes.getattribute       = nodes.getattr +nuts.unsetattribute      = nuts.unset_attribute              nodes.unsetattribute     = nodes.unset_attribute +nuts.has_attribute       = nuts.has_attribute                nodes.has_attribute      = nodes.has_attribute +nuts.firstglyph          = nuts.first_glyph                  nodes.firstglyph         = nodes.first_glyph + +nuts.setattributes       = set_attributes                    nodes.setattributes      = vianuts(set_attributes) +nuts.setunsetattributes  = set_unset_attributes              nodes.setunsetattributes = vianuts(set_unset_attributes) +nuts.unsetattributes     = unset_attributes                  nodes.unsetattributes    = vianuts(unset_attributes) + +function nuts.firstcharacter(n,untagged) -- tagged == subtype > 255 +    if untagged then +        return first_glyph(n) +    else +        for g in nextglyph ,n do +            return g +        end +    end +end + +local function firstcharinbox(n) +    local l = getlist(getbox(n)) +    if l then +        for g, c in nextglyph, l do +            return c +        end +    end +    return 0 +end + +nuts .firstcharinbox = firstcharinbox +nodes.firstcharinbox = firstcharinbox -- hm, ok ? +nodes.firstcharacter = vianuts(firstcharacter) + +interfaces.implement { +    name      = "buildtextaccent", +    arguments = "integer", +    actions   = function(n) -- Is this crap really used? Or was it an experiment? +        local char = firstcharinbox(n) +        if char > 0 then +         -- context.accent(false,char) +            context([[\accent%s\relax]],char) +        end +    end +} + +-- this depends on fonts, so we have a funny dependency ... will be +-- sorted out .. we could make tonodes a plugin into this + +local function tonodes(str,fnt,attr) -- (str,template_glyph) -- moved from blob-ini +    if not str or str == "" then +        return +    end +    local head, tail, space, fnt, template = nil, nil, nil, nil, nil +    if not fnt then +        fnt = current_font() +    elseif type(fnt) ~= "number" and getid(fnt) == glyph_code then -- so it has to be a real node +        fnt, template = nil, tonut(fnt) +    end +    for s in utfvalues(str) do +        local n +        if s == 32 then +            if space then +                n = copy_node(space) +            elseif fonts then -- depedency +                local parameters = fonts.hashes.identifiers[fnt].parameters +                space = new_glue(parameters.space,parameters.space_stretch,parameters.space_shrink) +                n = space +            end +        elseif template then +            n = copy_node(template) +            setvalue(n,"char",s) +        else +            n = new_glyph(fnt,s) +        end +        if attr then -- normally false when template +            setattrlist(n,attr) +        end +        if head then +            setlink(tail,n) +        else +            head = n +        end +        tail = n +    end +    return head, tail +end + +nuts.tonodes = tonodes + +nodes.tonodes = function(str,fnt,attr) +    local head, tail = tonodes(str,fnt,attr) +    return tonode(head), tonode(tail) +end + +local function link(list,currentfont,currentattr,head,tail) -- an oldie, might be replaced +    for i=1,#list do +        local n = list[i] +        if n then +            local tn = type(n) +            if tn == "string" then +                if #tn > 0 then +                    if not currentfont then +                        currentfont = current_font() +                    end +                    local h, t = tonodes(n,currentfont,currentattr) +                    if not h then +                        -- skip +                    elseif not head then +                        head, tail = h, t +                    else +                        setnext(tail,h) +                        setprev(h,t) +                        tail = t +                    end +                end +            elseif tn == "table" then +                if #tn > 0 then +                    if not currentfont then +                        currentfont = current_font() +                    end +                    head, tail = link(n,currentfont,currentattr,head,tail) +                end +            elseif not head then +                head = n +                tail = find_tail(n) +            elseif getid(n) == attributelist_code then +                -- weird case +                report_error("weird node type in list at index %s:",i) +                for i=1,#list do +                    local l = list[i] +                    report_error("%3i: %s %S",i,getid(l) == attributelist_code and "!" or ">",l) +                end +                os.exit() +            else +                setlink(tail,n) +                if getnext(n) then +                    tail = find_tail(n) +                else +                    tail = n +                end +            end +        else +            -- permitting nil is convenient +        end +    end +    return head, tail +end + +nuts.link = link + +nodes.link = function(list,currentfont,currentattr,head,tail) +    local head, tail = link(list,currentfont,currentattr,tonut(head),tonut(tail)) +    return tonode(head), tonode(tail) +end + +local function locate(start,wantedid,wantedsubtype) +    for n, id, subtype in nextnode, start do +        if id == wantedid then +            if not wantedsubtype or subtype == wantedsubtype then +                return n +            end +        elseif id == hlist_code or id == vlist_code then +            local found = locate(getlist(n),wantedid,wantedsubtype) +            if found then +                return found +            end +        end +    end +end + +nuts.locate = locate + +function nodes.locate(start,wantedid,wantedsubtype) +    local found = locate(tonut(start),wantedid,wantedsubtype) +    return found and tonode(found) +end + +local function rehpack(n,width) +    local head = getlist(n) +    local size = width or getwidth(n) +    local temp = hpack_nodes(head,size,"exactly") +    setwidth(n,size) +    local set, order, sign = getboxglue(temp) +    setboxglue(n,set,order,sign) +    setlist(temp) +    flush_node(temp) +    return n +end + +nuts.rehpack = rehpack + +function nodes.rehpack(n,...) +    rehpack(tonut(n),...) +end + +do + +    local localparcodes = nodes.localparcodes +    local hmodepar_code = localparcodes.vmode_par +    local vmodepar_code = localparcodes.hmode_par + +    local getnest       = tex.getnest +    local getsubtype    = nuts.getsubtype + +    function nuts.setparproperty(action,...) +        local tail = tonut(getnest().tail) +        while tail do +            if getid(tail) == localpar_code then +                local s = getsubtype(tail) +                if s == hmodepar_code or s == vmodepar_code then +                    return action(tail,...) +                else +                    -- something is wrong here +                end +            end +            tail = getprev(tail) +        end +    end + +    local getsubtype = nodes.getsubtype + +    function nodes.start_of_par(n) +        local s = getsubtype(n) +        return s == hmodepar_code or s == vmodepar_code +    end + +end diff --git a/tex/context/base/mkiv/node-aux.lua b/tex/context/base/mkiv/node-aux.lua index 407ebb09c..aa7dc0292 100644 --- a/tex/context/base/mkiv/node-aux.lua +++ b/tex/context/base/mkiv/node-aux.lua @@ -413,10 +413,7 @@ do  end --- Currently only in luametatex ... experimental anyway .. if it doesn't end --- up in luatex I'll move this to a different module. - -do +if not nuts.getnormalizedline then      local nextnode           = traversers.glue      local findfail           = nuts.tail @@ -459,9 +456,7 @@ do      nuts.find_node = find_node - -- if CONTEXTLMTXMODE then ... end - -    nuts.getnormalizedline = direct.getnormalizedline or function(h) +    function nuts.getnormalizedline(h)          if getid(h) == hlist_code and getsubtype(h) == line_code then              local ls, rs = 0, 0              local lh, rh = 0, 0 diff --git a/tex/context/base/mkiv/node-ini.lmt b/tex/context/base/mkiv/node-ini.lmt new file mode 100644 index 000000000..2f0b98e88 --- /dev/null +++ b/tex/context/base/mkiv/node-ini.lmt @@ -0,0 +1,287 @@ +if not modules then modules = { } end modules ['node-ini'] = { +    version   = 1.001, +    comment   = "companion to node-ini.mkiv", +    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL", +    copyright = "PRAGMA ADE / ConTeXt Development Team", +    license   = "see context related readme files" +} + +--[[ldx-- +<p>Most of the code that had accumulated here is now separated in modules.</p> +--ldx]]-- + +local next, type, tostring = next, type, tostring +local gsub = string.gsub +local concat, remove = table.concat, table.remove +local sortedhash, sortedkeys, swapped = table.sortedhash, table.sortedkeys, table.swapped + +--[[ldx-- +<p>Access to nodes is what gives <l n='luatex'/> its power. Here we implement a +few helper functions. These functions are rather optimized.</p> +--ldx]]-- + +nodes               = nodes or { } +local nodes         = nodes +nodes.handlers      = nodes.handlers or { } + +local mark          = utilities.storage.mark +local allocate      = utilities.storage.allocate +local formatcolumns = utilities.formatters.formatcolumns + +local getsubtypes   = node.subtypes +local getvalues     = node.values + +tex.magicconstants = { -- we use tex.constants for something else +    running  = -1073741824, -- null_flag +    maxdimen =  1073741823, -- max_dimen +    trueinch =     4736286, +} + +local listcodes     = mark(getsubtypes("list")) +local rulecodes     = mark(getsubtypes("rule")) +local dircodes      = mark(getsubtypes("dir")) +local glyphcodes    = mark(getsubtypes("glyph")) +local disccodes     = mark(getsubtypes("disc")) +local gluecodes     = mark(getsubtypes("glue")) +local leadercodes   = mark(getsubtypes("leader")) +local fillcodes     = mark(getsubtypes("fill")) +local boundarycodes = mark(getsubtypes("boundary")) +local penaltycodes  = mark(getsubtypes("penalty")) +local kerncodes     = mark(getsubtypes("kern")) +local mathcodes     = mark(getsubtypes("math")) +local noadcodes     = mark(getsubtypes("noad")) +local radicalcodes  = mark(getsubtypes("radical")) +local accentcodes   = mark(getsubtypes("accent")) +local fencecodes    = mark(getsubtypes("fence")) +----- fractioncodes = mark(getsubtypes("fraction")) +local localparcodes = CONTEXTLMTXMODE > 0 and mark(getsubtypes("localpar")) + +if not localparcodes then +    localparcodes = allocate { [0] = "new_graf", "local_box", "hmode_par", "penalty", "math" } +end + +local function simplified(t) +    local r = { } +    for k, v in next, t do +        r[k] = gsub(v,"_","") +    end +    return r +end + +local nodecodes = simplified(node.types()) +local whatcodes = simplified(node.whatsits and node.whatsits() or { }) + +local dirvalues  = mark(getvalues("dir")) +local gluevalues = mark(getvalues("glue")) + +local whatcodes = { +    literal     = 0x1, [0x1] = "literal", +    latelua     = 0x2, [0x2] = "latelua", +    userdefined = 0x3, [0x3] = "userdefined", +    savepos     = 0x4, [0x4] = "savepos", +    save        = 0x5, [0x5] = "save", +    restore     = 0x6, [0x6] = "restore", +    setmatrix   = 0x7, [0x7] = "setmatrix", +    open        = 0x8, [0x8] = "open", +    close       = 0x9, [0x9] = "close", +    write       = 0xA, [0xA] = "write", +} + +local usercodes = allocate { +    [ 97] = "attribute", -- a +    [100] = "number",    -- d +    [102] = "float",     -- f +    [108] = "lua",       -- l +    [110] = "node",      -- n +    [115] = "string",    -- s +    [116] = "token"      -- t +} + +local noadoptions = allocate { +    set      =        0x08, +    unused_1 = 0x00 + 0x08, +    unused_2 = 0x01 + 0x08, +    axis     = 0x02 + 0x08, +    no_axis  = 0x04 + 0x08, +    exact    = 0x10 + 0x08, +    left     = 0x11 + 0x08, +    middle   = 0x12 + 0x08, +    right    = 0x14 + 0x08, +} + +local literalvalues = allocate { +    [0] = "origin", +    [1] = "page", +    [2] = "always", +    [3] = "raw", +    [4] = "text", +    [5] = "font", +    [6] = "special", +} + +gluecodes     = allocate(swapped(gluecodes,gluecodes)) +dircodes      = allocate(swapped(dircodes,dircodes)) +boundarycodes = allocate(swapped(boundarycodes,boundarycodes)) +noadcodes     = allocate(swapped(noadcodes,noadcodes)) +radicalcodes  = allocate(swapped(radicalcodes,radicalcodes)) +nodecodes     = allocate(swapped(nodecodes,nodecodes)) +whatcodes     = allocate(swapped(whatcodes,whatcodes)) +listcodes     = allocate(swapped(listcodes,listcodes)) +glyphcodes    = allocate(swapped(glyphcodes,glyphcodes)) +kerncodes     = allocate(swapped(kerncodes,kerncodes)) +penaltycodes  = allocate(swapped(penaltycodes,penaltycodes)) +mathcodes     = allocate(swapped(mathcodes,mathcodes)) +fillcodes     = allocate(swapped(fillcodes,fillcodes)) +disccodes     = allocate(swapped(disccodes,disccodes)) +accentcodes   = allocate(swapped(accentcodes,accentcodes)) +fencecodes    = allocate(swapped(fencecodes,fencecodes)) +localparcodes = allocate(swapped(localparcodes,localparcodes)) +rulecodes     = allocate(swapped(rulecodes,rulecodes)) +leadercodes   = allocate(swapped(leadercodes,leadercodes)) +usercodes     = allocate(swapped(usercodes,usercodes)) +noadoptions   = allocate(swapped(noadoptions,noadoptions)) +dirvalues     = allocate(swapped(dirvalues,dirvalues)) +gluevalues    = allocate(swapped(gluevalues,gluevalues)) +literalvalues = allocate(swapped(literalvalues,literalvalues)) + +nodes.gluecodes     = gluecodes +nodes.dircodes      = dircodes +nodes.boundarycodes = boundarycodes +nodes.noadcodes     = noadcodes +nodes.nodecodes     = nodecodes +nodes.whatcodes     = whatcodes +nodes.listcodes     = listcodes +nodes.glyphcodes    = glyphcodes +nodes.kerncodes     = kerncodes +nodes.penaltycodes  = penaltycodes +nodes.mathcodes     = mathcodes +nodes.fillcodes     = fillcodes +nodes.disccodes     = disccodes +nodes.accentcodes   = accentcodes +nodes.radicalcodes  = radicalcodes +nodes.fencecodes    = fencecodes +nodes.localparcodes = localparcodes +nodes.rulecodes     = rulecodes +nodes.leadercodes   = leadercodes +nodes.usercodes     = usercodes +nodes.noadoptions   = noadoptions +nodes.dirvalues     = dirvalues +nodes.gluevalues    = gluevalues +nodes.literalvalues = literalvalues + +nodes.subtypes = allocate { +    [nodecodes.accent]   = accentcodes, +    [nodecodes.boundary] = boundarycodes, +    [nodecodes.dir]      = dircodes, +    [nodecodes.disc]     = disccodes, +    [nodecodes.fence]    = fencecodes, +    [nodecodes.glue]     = gluecodes, +    [nodecodes.glyph]    = glyphcodes, +    [nodecodes.hlist]    = listcodes, +    [nodecodes.kern]     = kerncodes, +    [nodecodes.localpar] = localparcodes, +    [nodecodes.math]     = mathcodes, +    [nodecodes.noad]     = noadcodes, +    [nodecodes.penalty]  = penaltycodes, +    [nodecodes.radical]  = radicalcodes, +    [nodecodes.rule]     = rulecodes, + -- [nodecodes.user]     = usercodes, +    [nodecodes.vlist]    = listcodes, +    [nodecodes.whatsit]  = whatcodes, +} + +table.setmetatableindex(nodes.subtypes,function(t,k) +    local v = { } +    t[k] = v +    return v +end) + +-- a few more friendly aliases: + +nodes.skipcodes            = gluecodes +nodes.directioncodes       = dircodes +nodes.whatsitcodes         = whatcodes +nodes.discretionarycodes   = disccodes +nodes.directionvalues      = dirvalues +nodes.skipvalues           = gluevalues +nodes.literalvalues        = literalvalues + +glyphcodes.glyph           = glyphcodes.character + +localparcodes.vmode_par    = localparcodes.new_graf + +listcodes.row              = listcodes.alignment +listcodes.column           = listcodes.alignment + +kerncodes.kerning          = kerncodes.fontkern +kerncodes.italiccorrection = kerncodes.italiccorrection or 1 -- new + +literalvalues.direct       = literalvalues.always + +nodes.codes = allocate { -- mostly for listing +    glue        = skipcodes, +    boundary    = boundarycodes, +    noad        = noadcodes, +    node        = nodecodes, +    hlist       = listcodes, +    vlist       = listcodes, +    glyph       = glyphcodes, +    kern        = kerncodes, +    penalty     = penaltycodes, +    math        = mathnodes, +    fill        = fillcodes, +    disc        = disccodes, +    whatsit     = whatcodes, +    accent      = accentcodes, +    fence       = fencecodes, +    rule        = rulecodes, +    leader      = leadercodes, +    user        = usercodes, +    noadoptions = noadoptions, +} + +nodes.noadoptions = { +    set      =        0x08, +    unused_1 = 0x00 + 0x08, +    unused_2 = 0x01 + 0x08, +    axis     = 0x02 + 0x08, +    no_axis  = 0x04 + 0x08, +    exact    = 0x10 + 0x08, +    left     = 0x11 + 0x08, +    middle   = 0x12 + 0x08, +    right    = 0x14 + 0x08, +} + +local report_codes = logs.reporter("nodes","codes") + +function nodes.showcodes() +    local t = { } +    for name, codes in sortedhash(nodes.codes) do +        local sorted = sortedkeys(codes) +        for i=1,#sorted do +            local s = sorted[i] +            if type(s) ~= "number" then +                t[#t+1] = { name, s, codes[s] } +            end +        end +    end +    formatcolumns(t) +    for k=1,#t do +        report_codes (t[k]) +    end +end + +trackers.register("system.showcodes", nodes.showcodes) + +-- We use the real node code numbers. + +local texchardef = tex.chardef + +for i=0,nodecodes.glyph do +    texchardef(nodecodes[i] .. "nodecode",i) +end +for i=0,#gluecodes do +    texchardef(gluecodes[i] .. "subtypecode",i) +end + +-- tex.set("internalcodesmode",1) -- obsolete diff --git a/tex/context/base/mkiv/node-ini.mkiv b/tex/context/base/mkiv/node-ini.mkiv index 2ecef4a54..8a3aa65df 100644 --- a/tex/context/base/mkiv/node-ini.mkiv +++ b/tex/context/base/mkiv/node-ini.mkiv @@ -21,12 +21,12 @@      \registerctxluafile{node-cmp}{autosuffix}  \fi -\registerctxluafile{node-ini}{} +\registerctxluafile{node-ini}{autosuffix}  \registerctxluafile{node-met}{} -\registerctxluafile{node-nut}{} +\registerctxluafile{node-nut}{autosuffix}  \registerctxluafile{node-res}{}  %registerctxluafile{node-ppt}{} % experimental, not used so probably useless -\registerctxluafile{node-aux}{} +\registerctxluafile{node-aux}{autosuffix}  \registerctxluafile{node-gcm}{autosuffix}  \registerctxluafile{node-tst}{}  \registerctxluafile{node-tra}{} % we might split it off (module) diff --git a/tex/context/base/mkiv/node-met.lua b/tex/context/base/mkiv/node-met.lua index f472d31a9..feaff70eb 100644 --- a/tex/context/base/mkiv/node-met.lua +++ b/tex/context/base/mkiv/node-met.lua @@ -1,4 +1,4 @@ -if not modules then modules = { } end modules ['node-nut'] = { +if not modules then modules = { } end modules ['node-MET'] = {      version   = 1.001,      comment   = "companion to node-ini.mkiv",      author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL", diff --git a/tex/context/base/mkiv/node-nut.lmt b/tex/context/base/mkiv/node-nut.lmt new file mode 100644 index 000000000..004729a3c --- /dev/null +++ b/tex/context/base/mkiv/node-nut.lmt @@ -0,0 +1,572 @@ +if not modules then modules = { } end modules ['node-nut'] = { +    version   = 1.001, +    comment   = "companion to node-ini.mkiv", +    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL", +    copyright = "PRAGMA ADE / ConTeXt Development Team", +    license   = "see context related readme files" +} + +-- Some comments anbout going nuts can be found in the mkiv file with the +-- suffix "lua", including some timing and musings. We copy the direct table +-- (1) because that's what we did while things evolved and (2) because we +-- also add some more helpers. + +local type, rawget = type, rawget + +local nodes           = nodes +local direct          = node.direct + +local fastcopy        = table.fastcopy + +local nodecodes       = nodes.nodecodes +local hlist_code      = nodecodes.hlist +local vlist_code      = nodecodes.vlist +local glyph_code      = nodecodes.glyph + +local tonode          = direct.tonode +local tonut           = direct.todirect + +local is_node         = direct.is_node +local is_nut          = direct.is_direct + +local d_remove_node   = direct.remove +local d_flush_node    = direct.flush_node +local d_getnext       = direct.getnext +local d_getprev       = direct.getprev +local d_getid         = direct.getid +local d_getlist       = direct.getlist +local d_find_tail     = direct.tail +local d_insert_after  = direct.insert_after +local d_insert_before = direct.insert_before +local d_slide         = direct.slide +local d_traverse      = direct.traverse +local d_setlink       = direct.setlink +local d_getboth       = direct.getboth + +local nuts = { +    check_discretionaries   = direct.check_discretionaries, +    copy                    = direct.copy, +    copy_list               = direct.copy_list, +    copy_node               = direct.copy, +    copy_only               = direct.copy_only or direct.copy, +    count                   = direct.count, +    current_attr            = direct.current_attr, +    delete                  = direct.delete, +    dimensions              = direct.dimensions, +    effective_glue          = direct.effective_glue, +    end_of_math             = direct.end_of_math, +    exchange                = direct.exchange, +    find_attribute          = direct.find_attribute, +    first_glyph             = direct.first_glyph, +    flatten_discretionaries = direct.flatten_discretionaries, +    flush                   = d_flush_node, +    flush_components        = direct.flush_components, +    flush_list              = direct.flush_list, +    flush_node              = direct.flush_node, +    free                    = direct.free, +    get_synctex_fields      = direct.get_synctex_fields, +    getattr                 = direct.get_attribute, +    getattributelist        = direct.getattributelist, +    getattrlist             = direct.getattributelist, +    getboth                 = d_getboth, +    getbox                  = direct.getbox, +    getboxglue              = direct.getglue, +    getchar                 = direct.getchar, +    getcomponents           = direct.getcomponents, +    getdata                 = direct.getdata, +    getdepth                = direct.getdepth, +    getdir                  = direct.getdir, +    getdirection            = direct.getdirection, +    getdisc                 = direct.getdisc, +    getdiscretionary        = direct.getdisc, +    getexpansion            = direct.getexpansion, +    getfam                  = direct.getfam, +    getfield                = direct.getfield, +    getfont                 = direct.getfont, +    getglue                 = direct.getglue, +    getglyphdata            = direct.getglyphdata, +    getheight               = direct.getheight, +    getid                   = d_getid, +    getkern                 = direct.getkern, +    getlang                 = direct.getlang, +    getlanguage             = direct.getlang, +    getleader               = direct.getleader, +    getlist                 = d_getlist, +    getnext                 = d_getnext, +    getnormalizedline       = direct.getnormalizedline, +    getnucleus              = direct.getnucleus, +    getoffsets              = direct.getoffsets, +    getorientation          = direct.getorientation, +    getpenalty              = direct.getpenalty, +    getpost                 = direct.getpost, +    getpre                  = direct.getpre, +    getprev                 = d_getprev, +    getreplace              = direct.getreplace, +    getruledata             = direct.getglyphdata, +    getscript               = direct.setscript, +    getshift                = direct.getshift, +    getstate                = direct.getstate, +    getsub                  = direct.getsub, +    getsubpre               = direct.getsubpre, +    getsubtype              = direct.getsubtype, +    getsup                  = direct.getsup, +    getsuppre               = direct.getsuppre, +    getsurround             = direct.getkern, +    gettotal                = direct.gettotal, +    getvalue                = direct.getdata, -- obsolete +    getwhd                  = direct.getwhd, +    getwidth                = direct.getwidth, +    has_attribute           = direct.has_attribute, +    has_dimensions          = direct.has_dimensions, +    has_field               = direct.has_field, +    has_glyph               = direct.has_glyph or direct.first_glyph, +    hpack                   = direct.hpack, +    hyphenating             = direct.hyphenating, +    insert_after            = d_insert_after, +    insert_before           = d_insert_before, +    is_direct               = is_direct, +    is_node                 = is_node, +    is_nut                  = direct.is_direct, +    is_zero_glue            = direct.is_zero_glue, +    ischar                  = direct.is_char, +    isglyph                 = direct.is_glyph, +    kerning                 = direct.kerning, +    last_node               = direct.last_node, +    length                  = direct.length, +    ligaturing              = direct.ligaturing, +    migrate                 = direct.migrate, +    mlist_to_hlist          = direct.mlist_to_hlist, +    new                     = direct.new, +    protect_glyph           = direct.protect_glyph, +    protect_glyphs          = direct.protect_glyphs, +    protrusion_skippable    = direct.protrusion_skippable, +    rangedimensions         = direct.rangedimensions, +    remove                  = d_remove_node, +    reverse                 = direct.reverse, +    set_attribute           = direct.set_attribute, +    set_synctex_fields      = direct.set_synctex_fields, +    setattr                 = direct.set_attribute, +    setattributelist        = direct.setattributelist, +    setattrlist             = direct.setattributelist, +    setboth                 = direct.setboth, +    setbox                  = direct.setbox, +    setboxglue              = direct.setglue, +    setchar                 = direct.setchar, +    setcomponents           = direct.setcomponents, +    setdata                 = direct.setdata, +    setdepth                = direct.setdepth, +    setdir                  = direct.setdir, +    setdirection            = direct.setdirection, +    setdisc                 = direct.setdisc, +    setdiscretionary        = direct.setdisc, +    setexpansion            = direct.setexpansion, +    setfam                  = direct.setfam, +    setfield                = direct.setfield, +    setfont                 = direct.setfont, +    setglue                 = direct.setglue, +    setglyphdata            = direct.setglyphdata, +    setheight               = direct.setheight, +    setkern                 = direct.setkern, +    setlang                 = direct.setlang, +    setlanguage             = direct.setlang, +    setleader               = direct.setleader, +    setlink                 = d_setlink, +    setlist                 = direct.setlist, +    setnext                 = direct.setnext, +    setnucleus              = direct.setnucleus, +    setoffsets              = direct.setoffsets, +    setorientation          = direct.setorientation, +    setpenalty              = direct.setpenalty, +    setpost                 = direct.setpost, +    setpre                  = direct.setpre, +    setprev                 = direct.setprev, +    setreplace              = direct.setreplace, +    setruledata             = direct.setglyphdata, +    setscript               = direct.getscript, +    setshift                = direct.setshift, +    setsplit                = direct.setsplit, +    setstate                = direct.setstate, +    setsub                  = direct.setsub, +    setsubpre               = direct.setsubpre, +    setsubtype              = direct.setsubtype, +    setsup                  = direct.setsup, +    setsuppre               = direct.setsuppre, +    setsurround             = direct.setkern, +    setvalue                = direct.setdata, -- obsolete +    setwhd                  = direct.setwhd, +    setwidth                = direct.setwidth, +    slide                   = d_slide, +    start_of_par            = direct.start_of_par, +    tail                    = d_find_tail, +    takeattr                = direct.unset_attribute, -- ? +    tonode                  = tonode, +    tonut                   = tonut, +    tostring                = direct.tostring, +    traverse                = d_traverse, +    traverse_char           = direct.traverse_char, +    traverse_glyph          = direct.traverse_glyph, +    traverse_id             = direct.traverse_id, +    traverse_list           = direct.traverse_list, +    unprotect_glyph         = direct.unprotect_glyph, +    unprotect_glyphs        = direct.unprotect_glyphs, +    unset_attribute         = direct.unset_attribute, +    usedlist                = direct.usedlist, +    uses_font               = direct.uses_font, +    vpack                   = direct.vpack, +    writable_spec           = direct.writable_spec, +    write                   = direct.write, +} + + +nodes.nuts      = nuts + +nodes.is_node   = is_node +nodes.is_direct = is_nut +nodes.is_nut    = is_nut + +nodes.tonode    = tonode +nodes.tonut     = tonut + +function nuts.delete(head,current) +    return d_remove_node(head,current,true) +end + +function nuts.replace(head,current,new) -- no head returned if false +    if not new then +        head, current, new = false, head, current +    end +    local prev, next = d_getboth(current) +    if prev or next then +        d_setlink(prev,new,next) +    end +    if head then +        if head == current then +            head = new +        end +        d_flush_node(current) +        return head, new +    else +        d_flush_node(current) +        return new +    end +end + +local function countall(stack,flat) +    local n = 0 +    while stack do +        local id = d_getid(stack) +        if not flat and id == hlist_code or id == vlist_code then +            local list = d_getlist(stack) +            if list then +                n = n + 1 + countall(list) -- self counts too +            else +                n = n + 1 +            end +        else +            n = n + 1 +        end +        stack = d_getnext(stack) +    end +    return n +end + +nuts.countall = countall + +function nodes.countall(stack,flat) +    return countall(tonut(stack),flat) +end + +function nuts.append(head,current,...) +    for i=1,select("#",...) do +        head, current = d_insert_after(head,current,(select(i,...))) +    end +    return head, current +end + +function nuts.prepend(head,current,...) +    for i=1,select("#",...) do +        head, current = d_insert_before(head,current,(select(i,...))) +    end +    return head, current +end + +function nuts.linked(...) -- slides ! +    local head, last +    for i=1,select("#",...) do +        local next = select(i,...) +        if next then +            if head then +                d_setlink(last,next) +            else +                head = next +            end +            last = d_find_tail(next) -- we could skip the last one +        end +    end +    return head +end + +function nuts.concat(list) -- consider tail instead of slide +    local head, tail +    for i=1,#list do +        local li = list[i] +        if li then +            if head then +                d_setlink(tail,li) +            else +                head = li +            end +            tail = d_slide(li) +        end +    end +    return head, tail +end + +function nuts.reference(n) +    return n or "<none>" +end + +function nuts.vianuts (f) return function(n,...) return tonode(f(tonut (n),...)) end end +function nuts.vianodes(f) return function(n,...) return tonut (f(tonode(n),...)) end end + +nodes.vianuts  = nuts.vianuts +nodes.vianodes = nuts.vianodes + +function nodes.insert_list_after(h,c,n) +    local t = n_tail(n) +    if c then +        local cn = n_getnext(c) +        if cn then +            -- no setboth here yet +            n_setfield(t,"next",cn) +            n_setfield(cn,"prev",t) +        else +            n_setfield(t,"next",nil) +        end +        n_setfield(c,"next",n) +        n_setfield(n,"prev",c) +        return h, n +    end +    return n, t +end + +function nuts.insert_list_after(h,c,n) +    local t = d_tail(n) +    if c then +        local cn = d_getnext(c) +        if cn then +            d_setlink(t,cn) +        else +            d_setnext(t) +        end +        d_setlink(c,n) +        return h, n +    end +    return n, t +end + +-- test code only + +-- collectranges and mix + +local report = logs.reporter("sliding") + +local function message(detail,head,current,previous) +    report("error: %s, current: %s:%s, previous: %s:%s, list: %s, text: %s", +        detail, +        nodecodes[d_getid(current)], +        current, +        nodecodes[d_getid(previous)], +        previous, +        nodes.idstostring(head), +        nodes.listtoutf(head) +    ) +    utilities.debugger.showtraceback(report) +end + +local function warn() +    report() +    report("warning: the slide tracer is enabled") +    report() +    warn = false +end + +local function tracedslide(head) +    if head then +        if warn then +            warn() +        end +        local next = d_getnext(head) +        if next then +            local prev = head +            for n in d_traverse(next) do +                local p = d_getprev(n) +                if not p then +                    message("unset",head,n,prev) +                 -- break +                elseif p ~= prev then +                    message("wrong",head,n,prev) +                 -- break +                end +                prev = n +            end +        end +        return d_slide(head) +    end +end + +local function nestedtracedslide(head,level) -- no sliding ! +    if head then +        if warn then +            warn() +        end +        local id = d_getid(head) +        local next = d_getnext(head) +        if next then +            report("%whead:%s",level or 0,nodecodes[id]) +            local prev = head +            for n in d_traverse(next) do +                local p = d_getprev(n) +                if not p then +                    message("unset",head,n,prev) +                 -- break +                elseif p ~= prev then +                    message("wrong",head,n,prev) +                 -- break +                end +                prev = n +                local id = d_getid(n) +                if id == hlist_code or id == vlist_code then +                    nestedtracedslide(d_getlist(n),(level or 0) + 1) +                end +            end +        elseif id == hlist_code or id == vlist_code then +            report("%wlist:%s",level or 0,nodecodes[id]) +            nestedtracedslide(d_getlist(head),(level or 0) + 1) +        end +     -- return d_slide(head) +    end +end + +local function untracedslide(head) +    if head then +        if warn then +            warn() +        end +        local next = d_getnext(head) +        if next then +            local prev = head +            for n in d_traverse(next) do +                local p = d_getprev(n) +                if not p then +                    return "unset", d_getid(n) +                elseif p ~= prev then +                    return "wrong", d_getid(n) +                end +                prev = n +            end +        end +        return d_slide(head) +    end +end + +nuts.tracedslide       = tracedslide +nuts.untracedslide     = untracedslide +nuts.nestedtracedslide = nestedtracedslide + +-- this might move + +local propertydata = direct.get_properties_table(true) + +local getattr = nuts.getattr +local setattr = nuts.setattr + +nodes.properties = { +    data = propertydata, +} + +-- experimental code with respect to copying attributes has been removed +-- as it doesn't pay of (most attributes are only accessed once anyway) + +function nuts.getprop(n,k) +    local p = propertydata[n] +    if p then +        if k then +            return p[k] +        else +            return p +        end +    end +end + +function nuts.rawprop(n,k) +    local p = rawget(propertydata,n) +    if p then +        if k then +            return p[k] +        else +            return p +        end +    end +end + +function nuts.setprop(n,k,v) +    local p = propertydata[n] +    if p then +        p[k] = v +    else +        propertydata[n] = { [k] = v } +    end +end + +function nuts.theprop(n) +    local p = propertydata[n] +    if not p then +        p = { } +        propertydata[n] = p +    end +    return p +end + + +function nuts.isdone(n,k) +    local p = propertydata[n] +    if not p then +        propertydata[n] = { [k] = true } +        return false +    end +    local v = p[k] +    if v == nil then +        propertydata[n] = { [k] = true } +        return false +    end +    return v +end + +function nuts.copy_properties(source,target,what) +    local newprops = propertydata[source] +    if not newprops then +        -- nothing to copy +        return +    end +    if what then +        -- copy one category +        newprops = rawget(source,what) +        if newprops then +            newprops = fastcopy(newprops) +            local p = rawget(propertydata,target) +            if p then +                p[what] = newprops +            else +                propertydata[target] = { +                    [what] = newprops, +                } +            end +        end +    else +        -- copy all properties +        newprops = fastcopy(newprops) +        propertydata[target] = newprops +    end +    return newprops -- for checking +end diff --git a/tex/context/base/mkiv/node-nut.lua b/tex/context/base/mkiv/node-nut.lua index 80335e933..68d238b1a 100644 --- a/tex/context/base/mkiv/node-nut.lua +++ b/tex/context/base/mkiv/node-nut.lua @@ -1,4 +1,4 @@ -if not modules then modules = { } end modules ['node-met'] = { +if not modules then modules = { } end modules ['node-nut'] = {      version   = 1.001,      comment   = "companion to node-ini.mkiv",      author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL", @@ -396,7 +396,7 @@ local d_setlink       = direct.setlink  local d_setboth       = direct.setboth  local d_getboth       = direct.getboth -local remove = CONTEXTLMTXMODE > 0 and d_remove_node or function(head,current,free_too) +local remove = function(head,current,free_too)      if current then          local h, c = d_remove_node(head,current)          if free_too then @@ -812,8 +812,6 @@ nuts.tracedslide       = tracedslide  nuts.untracedslide     = untracedslide  nuts.nestedtracedslide = nestedtracedslide --- nuts.slide          = tracedslide -  -- this might move  local propertydata = direct.get_properties_table(true) @@ -877,17 +875,7 @@ local getstate = direct.getstate  local setstate = direct.setstate  if not setstate or not getstate then - -- setstate = function(n,v) - --     setprop(n,"state",v) - -- end - -- getstate = function(n,v) - --     local s = getprop(n,"state") - --     if v then - --         return s == v - --     else - --         return s - --     end - -- end +      setstate = function(n,v)          local p = propertydata[n]          if p then @@ -896,6 +884,7 @@ if not setstate or not getstate then              propertydata[n] = { state = v }          end      end +      getstate = function(n,v)          local p = propertydata[n]          if p then @@ -919,7 +908,7 @@ local setscript = direct.setscript or function(n,v) end -- elsewhere  nuts.setscript = getscript  nuts.getscript = setscript -nuts.isdone = function(n,k) +function nuts.isdone(n,k)      local p = propertydata[n]      if not p then          propertydata[n] = { [k] = true } @@ -933,9 +922,6 @@ nuts.isdone = function(n,k)      return v  end --- nodes.setprop = nodes.setproperty --- nodes.getprop = nodes.getproperty -  function nuts.copy_properties(source,target,what)      local newprops = propertydata[source]      if not newprops then diff --git a/tex/context/base/mkiv/node-res.lua b/tex/context/base/mkiv/node-res.lua index 9b76fed54..c27059003 100644 --- a/tex/context/base/mkiv/node-res.lua +++ b/tex/context/base/mkiv/node-res.lua @@ -584,12 +584,17 @@ local usage = CONTEXTLMTXMODE > 0 and node.inuse or function()      return t  end +local stock = CONTEXTLMTXMODE > 0 and node.instock or { } +  nutpool .cleanup = cleanup  nodepool.cleanup = cleanup  nutpool .usage   = usage  nodepool.usage   = usage +nutpool .stock   = stock +nodepool.stock   = stock +  -- end  statistics.register("cleaned up reserved nodes", function() diff --git a/tex/context/base/mkiv/node-snp.lmt b/tex/context/base/mkiv/node-snp.lmt index d058a142a..8c0237a5c 100644 --- a/tex/context/base/mkiv/node-snp.lmt +++ b/tex/context/base/mkiv/node-snp.lmt @@ -16,6 +16,7 @@ nodes.snapshots = snapshots  local status    = status  local nodeusage = nodes.pool and nodes.pool.usage +local nodestock = nodes.pool and nodes.pool.stock  local clock     = os.gettimeofday or os.clock -- should go in environment  local lasttime  = clock()  local samples   = { } @@ -25,6 +26,7 @@ function snapshots.takesample(comment)          local c = clock()          samples[#samples+1] = {              nodes            = nodeusage(), +            stock            = nodestock(),              texcallbacks     = status.getcallbackstate(),              mpcallbacks      = mplib.getcallbackstate(),              backendcallbacks = backends.getcallbackstate(), @@ -51,6 +53,8 @@ function snapshots.takesample(comment)                  read      = status.getreadstate(),                  font      = status.getfontstate(),                  language  = status.getlanguagestate(), +                mark      = status.getmarkstate(), +                sparse    = status.getsparsestate(),              },          }      end diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf Binary files differindex 41c6c2f60..56e1600c9 100644 --- a/tex/context/base/mkiv/status-files.pdf +++ b/tex/context/base/mkiv/status-files.pdf diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf Binary files differindex 5d19ce520..1b46f8863 100644 --- a/tex/context/base/mkiv/status-lua.pdf +++ b/tex/context/base/mkiv/status-lua.pdf diff --git a/tex/context/base/mkiv/trac-inf.lmt b/tex/context/base/mkiv/trac-inf.lmt index 1729c87e5..80bb3b2f6 100644 --- a/tex/context/base/mkiv/trac-inf.lmt +++ b/tex/context/base/mkiv/trac-inf.lmt @@ -289,20 +289,20 @@ function statistics.showusage(when)      local list   = {          "stringstate", "poolstate",          "hashstate", "lookupstate", -        "nodestate", "tokenstate", +        "nodestate", "extrastate", "tokenstate",          "bufferstate", "inputstate", "filestate",          "neststate", "parameterstate", "savestate", -        "fontstate", "languagestate", +        "fontstate", "languagestate", "markstate", "sparsestate",      }      local fields = { "max", "min", "set", "stp", false, "mem", "all", false, "ini", "ptr", "top" } -    local line   = rep("-",172) +    local line   = rep("-",190)      do          local t = { }          for i=1,#list do              t[i] = gsub(list[i],"state","")          end          report("%w%s",2,line) -        report("%w%12s%12s%12s%12s%12s%12s%12s%12s%12s%12s%12s%12s%12s%12s",5,unpack(t)) +        report("%w%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s",5,unpack(t))          report("%w%s",2,line)      end      for i=1,#fields do @@ -311,9 +311,9 @@ function statistics.showusage(when)              local t = { }              for i=1,#list do                  local n = s[list[i]][f] -                t[i] = n < 0 and formatters["%w"](12) or formatters["%12i"](n) +                t[i] = n < 0 and formatters["%w"](11) or formatters["%11i"](n)              end -            report("  %3s%12s%12s%12s%12s%12s%12s%12s%12s%12s%12s%12s%12s%12s%12s",f,unpack(t)) +            report("  %3s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s",f,unpack(t))          else              report("")          end @@ -363,8 +363,18 @@ local enabled    = false  trackers.register("system.usage", function(v)      if v and not registered then          logs.private.enablepagetiming() -        luatex.registerpageactions(function() if enabled then statistics.showusage("page")   end end) -        luatex.registerstopactions(function() if enabled then statistics.showusage("finish") end end) +        if v ~= "summary" then +            luatex.registerpageactions(function() +                if enabled then +                    statistics.showusage("page") +                end +            end) +        end +        luatex.registerstopactions(function() +            if enabled then +                statistics.showusage("finish") +            end +        end)          registered = true      end      enabled = v diff --git a/tex/context/base/mkiv/trac-tim.lmt b/tex/context/base/mkiv/trac-tim.lmt index ce61c7440..fcba7f132 100644 --- a/tex/context/base/mkiv/trac-tim.lmt +++ b/tex/context/base/mkiv/trac-tim.lmt @@ -123,6 +123,7 @@ local function convert(name)                  end                  collect("nodes") +                collect("stock")                  collect("memories")                  collect("variables")                  collect("texvariables") diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index aaea6ff2f..ff1b629b8 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@  -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua  -- parent file : c:/data/develop/context/sources/luatex-fonts.lua --- merge date  : 2020-08-25 19:56 +-- merge date  : 2020-08-27 19:25  do -- begin closure to overcome local limits and interference @@ -9131,12 +9131,14 @@ function constructors.scale(tfmdata,specification)   target.cidinfo=properties.cidinfo   target.format=properties.format   target.cache=constructors.cacheintex and "yes" or "renew" + local original=properties.original or tfmdata.original   local fontname=properties.fontname or tfmdata.fontname   local fullname=properties.fullname or tfmdata.fullname   local filename=properties.filename or tfmdata.filename   local psname=properties.psname   or tfmdata.psname   local name=properties.name  or tfmdata.name   local psname,psfixed=fixedpsname(psname,fontname or fullname or file.nameonly(filename)) + target.original=original   target.fontname=fontname   target.fullname=fullname   target.filename=filename @@ -13275,15 +13277,15 @@ do   local p_dictionary=(    p_byte+p_positive+p_negative+p_short+p_long+p_nibbles+p_single+p_double+p_unsupported   )^1 - parsedictionaries=function(data,dictionaries,what) + parsedictionaries=function(data,dictionaries,version)    stack={}    strings=data.strings    if trace_charstrings then -   report("charstring format %a",what) +   report("charstring format %a",version)    end    for i=1,#dictionaries do     top=0 -   result=what=="cff" and { +   result=version=="cff" and {      monospaced=false,      italicangle=0,      underlineposition=-100, @@ -14658,8 +14660,8 @@ do    processshape(tab,index-1)   end  end -local function readglobals(f,data) - local routines=readlengths(f) +local function readglobals(f,data,version) + local routines=readlengths(f,version=="cff2")   for i=1,#routines do    routines[i]=readbytetable(f,routines[i])   end @@ -14713,14 +14715,14 @@ local function readprivates(f,data)    private.data=readstring(f,private.size)   end  end -local function readlocals(f,data,dictionary) +local function readlocals(f,data,dictionary,version)   local header=data.header   local private=dictionary.private   if private then    local subroutineoffset=private.data.subroutines    if subroutineoffset~=0 then     setposition(f,header.offset+private.offset+subroutineoffset) -   local subroutines=readlengths(f) +   local subroutines=readlengths(f,version=="cff2")     for i=1,#subroutines do      subroutines[i]=readbytetable(f,subroutines[i])     end @@ -14733,7 +14735,7 @@ local function readlocals(f,data,dictionary)    dictionary.subroutines={}   end  end -local function readcharstrings(f,data,what) +local function readcharstrings(f,data,version)   local header=data.header   local dictionaries=data.dictionaries   local dictionary=dictionaries[1] @@ -14742,7 +14744,7 @@ local function readcharstrings(f,data,what)   if type(offset)~="number" then   elseif stringtype==2 then    setposition(f,header.offset+offset) -  local charstrings=readlengths(f,what=="cff2") +  local charstrings=readlengths(f,version=="cff2")    local nofglyphs=#charstrings    for i=1,nofglyphs do     charstrings[i]=readstring(f,charstrings[i]) @@ -14772,7 +14774,8 @@ readers.parsecharstrings=parsecharstrings  local function readnoselect(f,fontdata,data,glyphs,doshapes,version,streams)   local dictionaries=data.dictionaries   local dictionary=dictionaries[1] - readglobals(f,data) + local cid=not dictionary.private and dictionary.cid + readglobals(f,data,version)   readcharstrings(f,data,version)   if version=="cff2" then    dictionary.charset=nil @@ -14780,9 +14783,27 @@ local function readnoselect(f,fontdata,data,glyphs,doshapes,version,streams)    readencodings(f,data)    readcharsets(f,data,dictionary)   end + if cid then +  local fdarray=cid.fdarray +  if fdarray then +   setposition(f,data.header.offset+fdarray) +   local dictionaries=readlengths(f,version=="cff2") +   local nofdictionaries=#dictionaries +   if nofdictionaries>0 then +    for i=1,nofdictionaries do +     dictionaries[i]=readstring(f,dictionaries[i]) +    end +    parsedictionaries(data,dictionaries) +    dictionary.private=dictionaries[1].private +    if nofdictionaries>1 then +     report("ignoring dictionaries > 1 in cid font") +    end +   end +  end + end   readprivates(f,data)   parseprivates(data,data.dictionaries) - readlocals(f,data,dictionary) + readlocals(f,data,dictionary,version)   startparsing(fontdata,data,streams)   parsecharstrings(fontdata,data,glyphs,doshapes,version,streams)   stopparsing(fontdata,data) @@ -14793,7 +14814,7 @@ local function readfdselect(f,fontdata,data,glyphs,doshapes,version,streams)   local dictionary=dictionaries[1]   local cid=dictionary.cid   local cidselect=cid and cid.fdselect - readglobals(f,data) + readglobals(f,data,version)   readcharstrings(f,data,version)   if version~="cff2" then    readencodings(f,data) @@ -14837,7 +14858,7 @@ local function readfdselect(f,fontdata,data,glyphs,doshapes,version,streams)    local cidarray=cid.fdarray    if cidarray then     setposition(f,header.offset+cidarray) -   local dictionaries=readlengths(f) +   local dictionaries=readlengths(f,version=="cff2")     for i=1,#dictionaries do      dictionaries[i]=readstring(f,dictionaries[i])     end @@ -14845,7 +14866,7 @@ local function readfdselect(f,fontdata,data,glyphs,doshapes,version,streams)     cid.dictionaries=dictionaries     readcidprivates(f,data)     for i=1,#dictionaries do -    readlocals(f,data,dictionaries[i]) +    readlocals(f,data,dictionaries[i],version)     end     startparsing(fontdata,data,streams)     for i=1,#charstrings do @@ -35924,8 +35945,9 @@ function definers.read(specification,size,id)     report_defining("already hashed: %s",hash)    end   else -  tfmdata=definers.loadfont(specification)  +  tfmdata=definers.loadfont(specification)    if tfmdata then +   tfmdata.original=specification.specification     if trace_defining then      report_defining("loaded and hashed: %s",hash)     end  | 
