summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/mkxl/node-res.lmt
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkxl/node-res.lmt')
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/node-res.lmt563
1 files changed, 563 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkxl/node-res.lmt b/Master/texmf-dist/tex/context/base/mkxl/node-res.lmt
new file mode 100644
index 00000000000..fbb1d1fe235
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkxl/node-res.lmt
@@ -0,0 +1,563 @@
+if not modules then modules = { } end modules ['node-res'] = {
+ 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"
+}
+
+local type, next, rawset = type, next, rawset
+local gmatch, format = string.gmatch, string.format
+
+--[[ldx--
+<p>The next function is not that much needed but in <l n='context'/> we use
+for debugging <l n='luatex'/> node management.</p>
+--ldx]]--
+
+local nodes, node = nodes, node
+
+local report_nodes = logs.reporter("nodes","housekeeping")
+
+nodes.pool = nodes.pool or { }
+local nodepool = nodes.pool
+
+local gluecodes = nodes.gluecodes
+local kerncodes = nodes.kerncodes
+local rulecodes = nodes.rulecodes
+local nodecodes = nodes.nodecodes
+local boundarycodes = nodes.boundarycodes
+local usercodes = nodes.usercodes
+
+local nodeproperties = nodes.properties.data
+
+local glyph_code = nodecodes.glyph
+local rule_code = nodecodes.rule
+local kern_code = nodecodes.kern
+local glue_code = nodecodes.glue
+local gluespec_code = nodecodes.gluespec
+
+local currentfont = font.current
+local texgetcount = tex.getcount
+
+local allocate = utilities.storage.allocate
+
+local reserved = { }
+local nofreserved = 0
+
+-- nuts overload
+
+local nuts = nodes.nuts
+local nutpool = { }
+nuts.pool = nutpool
+
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+
+local getbox = nuts.getbox
+local getid = nuts.getid
+local getlist = nuts.getlist
+local getglue = nuts.getglue
+
+local setfield = nuts.setfield
+local setchar = nuts.setchar
+local setlist = nuts.setlist
+local setwhd = nuts.setwhd
+local setglue = nuts.setglue
+local setdisc = nuts.setdisc
+local setfont = nuts.setfont
+local setkern = nuts.setkern
+local setpenalty = nuts.setpenalty
+local setdir = nuts.setdir
+local setdirection = nuts.setdirection
+local setshift = nuts.setshift
+local setwidth = nuts.setwidth
+local setsubtype = nuts.setsubtype
+local setleader = nuts.setleader
+
+local setdata = nuts.setdata
+local setruledata = nuts.setruledata
+local setvalue = nuts.setvalue
+
+local copy_nut = nuts.copy_only or nuts.copy
+local new_nut = nuts.new
+local flush_nut = nuts.flush
+
+-- at some point we could have a dual set (the overhead of tonut is not much larger than
+-- metatable associations at the lua/c end esp if we also take assignments into account
+
+-- table.setmetatableindex(nodepool,function(t,k,v)
+-- -- report_nodes("defining nodepool[%s] instance",k)
+-- local f = nutpool[k]
+-- local v = function(...)
+-- return tonode(f(...))
+-- end
+-- t[k] = v
+-- return v
+-- end)
+--
+-- -- we delay one step because that permits us a forward reference
+-- -- e.g. in pdfsetmatrix
+
+table.setmetatableindex(nodepool,function(t,k,v)
+ -- report_nodes("defining nodepool[%s] instance",k)
+ local v = function(...)
+ local f = nutpool[k]
+ local v = function(...)
+ return tonode(f(...))
+ end
+ t[k] = v
+ return v(...)
+ end
+ t[k] = v
+ return v
+end)
+
+local function register_nut(n)
+ nofreserved = nofreserved + 1
+ reserved[nofreserved] = n
+ return n
+end
+
+local function register_node(n)
+ nofreserved = nofreserved + 1
+ if type(n) == "number" then -- isnut(n)
+ reserved[nofreserved] = n
+ else
+ reserved[nofreserved] = tonut(n)
+ end
+ return n
+end
+
+nodepool.register = register_node
+nutpool.register = register_node -- could be register_nut
+
+-- so far
+
+local disc = register_nut(new_nut(nodecodes.disc))
+local kern = register_nut(new_nut(kern_code,kerncodes.userkern))
+local fontkern = register_nut(new_nut(kern_code,kerncodes.fontkern))
+local italickern = register_nut(new_nut(kern_code,kerncodes.italiccorrection))
+local penalty = register_nut(new_nut(nodecodes.penalty))
+local glue = register_nut(new_nut(glue_code))
+local gluespec = register_nut(new_nut(gluespec_code))
+local glyph = register_nut(new_nut(glyph_code,0))
+
+local textdir = register_nut(new_nut(nodecodes.dir))
+
+local left_margin_kern = register_nut(new_nut(kern_code,kerncodes.leftmargincode))
+local right_margin_kern = register_nut(new_nut(kern_code,kerncodes.rightmargincode))
+
+local lineskip = register_nut(new_nut(glue_code,gluecodes.lineskip))
+local baselineskip = register_nut(new_nut(glue_code,gluecodes.baselineskip))
+local leftskip = register_nut(new_nut(glue_code,gluecodes.leftskip))
+local rightskip = register_nut(new_nut(glue_code,gluecodes.rightskip))
+local lefthangskip = register_nut(new_nut(glue_code,gluecodes.lefthangskip))
+local righthangskip = register_nut(new_nut(glue_code,gluecodes.righthangskip))
+local indentskip = register_nut(new_nut(glue_code,gluecodes.indentskip))
+local correctionskip = register_nut(new_nut(glue_code,gluecodes.correctionskip))
+
+local temp = register_nut(new_nut(nodecodes.temp,0))
+
+local noad = register_nut(new_nut(nodecodes.noad))
+local delimiter = register_nut(new_nut(nodecodes.delimiter))
+local fence = register_nut(new_nut(nodecodes.fence))
+local submlist = register_nut(new_nut(nodecodes.submlist))
+local accent = register_nut(new_nut(nodecodes.accent))
+local radical = register_nut(new_nut(nodecodes.radical))
+local fraction = register_nut(new_nut(nodecodes.fraction))
+local subbox = register_nut(new_nut(nodecodes.subbox))
+local mathchar = register_nut(new_nut(nodecodes.mathchar))
+local mathtextchar = register_nut(new_nut(nodecodes.mathtextchar))
+local choice = register_nut(new_nut(nodecodes.choice))
+
+local boundary = register_nut(new_nut(nodecodes.boundary,boundarycodes.user))
+local wordboundary = register_nut(new_nut(nodecodes.boundary,boundarycodes.word))
+
+local cleader = register_nut(copy_nut(glue)) setsubtype(cleader,gluecodes.cleaders) setglue(cleader,0,65536,0,2,0)
+
+-- the dir field needs to be set otherwise crash:
+
+local lefttoright_code = nodes.dirvalues.lefttoright
+
+local rule = register_nut(new_nut(rule_code)) -- setdirection(rule, lefttoright_code)
+local emptyrule = register_nut(new_nut(rule_code,rulecodes.empty)) -- setdirection(rule, lefttoright_code)
+local userrule = register_nut(new_nut(rule_code,rulecodes.user)) -- setdirection(rule, lefttoright_code)
+local outlinerule = register_nut(new_nut(rule_code,rulecodes.outline)) -- setdirection(rule, lefttoright_code)
+local hlist = register_nut(new_nut(nodecodes.hlist)) setdirection(hlist,lefttoright_code)
+local vlist = register_nut(new_nut(nodecodes.vlist)) setdirection(vlist,lefttoright_code)
+
+function nutpool.glyph(fnt,chr)
+ local n = copy_nut(glyph)
+ if fnt then
+ setfont(n,fnt == true and currentfont() or fnt,chr)
+ elseif chr then
+ setchar(n,chr)
+ end
+ return n
+end
+
+function nutpool.penalty(p)
+ local n = copy_nut(penalty)
+ if p and p ~= 0 then
+ setpenalty(n,p)
+ end
+ return n
+end
+
+function nutpool.kern(k)
+ local n = copy_nut(kern)
+ if k and k ~= 0 then
+ setkern(n,k)
+ end
+ return n
+end
+
+function nutpool.boundary(v)
+ local n = copy_nut(boundary)
+ if v and v ~= 0 then
+ setvalue(n,v)
+ end
+ return n
+end
+
+function nutpool.wordboundary(v)
+ local n = copy_nut(wordboundary)
+ if v and v ~= 0 then
+ setvalue(n,v)
+ end
+ return n
+end
+
+function nutpool.fontkern(k)
+ local n = copy_nut(fontkern)
+ if k and k ~= 0 then
+ setkern(n,k)
+ end
+ return n
+end
+
+function nutpool.italickern(k)
+ local n = copy_nut(italickern)
+ if k and k ~= 0 then
+ setkern(n,k)
+ end
+ return n
+end
+
+function nutpool.gluespec(width,stretch,shrink,stretch_order,shrink_order)
+ local n = copy_nut(gluespec)
+ if width or stretch or shrink or stretch_order or shrink_order then
+ setglue(n,width,stretch,shrink,stretch_order,shrink_order)
+ end
+ return n
+end
+
+local function someskip(skip,width,stretch,shrink,stretch_order,shrink_order)
+ -- maybe setglue
+ local n = copy_nut(skip)
+ if width or stretch or shrink or stretch_order or shrink_order then
+ setglue(n,width,stretch,shrink,stretch_order,shrink_order)
+ end
+ return n
+end
+
+function nutpool.stretch(a,b)
+ -- width stretch shrink stretch_order shrink_order
+ local n = copy_nut(glue)
+ if not b then
+ a, b = 1, a or 1
+ end
+ setglue(n,0,a,0,b,0)
+ return n
+end
+
+function nutpool.shrink(a,b)
+ local n = copy_nut(glue)
+ if not b then
+ a, b = 1, a or 1
+ end
+ setglue(n,0,0,a,0,0,b)
+ return n
+end
+
+function nutpool.glue(width,stretch,shrink,stretch_order,shrink_order)
+ return someskip(glue,width,stretch,shrink,stretch_order,shrink_order)
+end
+
+function nutpool.negatedglue(glue)
+ local n = copy_nut(glue)
+ local width, stretch, shrink = getglue(n)
+ setglue(n,-width,-stretch,-shrink)
+ return n
+end
+
+function nutpool.leftskip(width,stretch,shrink,stretch_order,shrink_order)
+ return someskip(leftskip,width,stretch,shrink,stretch_order,shrink_order)
+end
+
+function nutpool.rightskip(width,stretch,shrink,stretch_order,shrink_order)
+ return someskip(rightskip,width,stretch,shrink,stretch_order,shrink_order)
+end
+
+function nutpool.lefthangskip(width,stretch,shrink,stretch_order,shrink_order)
+ return someskip(lefthangskip,width,stretch,shrink,stretch_order,shrink_order)
+end
+
+function nutpool.righthangskip(width,stretch,shrink,stretch_order,shrink_order)
+ return someskip(righthangskip,width,stretch,shrink,stretch_order,shrink_order)
+end
+
+function nutpool.indentskip(width,stretch,shrink,stretch_order,shrink_order)
+ return someskip(indentskip,width,stretch,shrink,stretch_order,shrink_order)
+end
+
+function nutpool.lineskip(width,stretch,shrink,stretch_order,shrink_order)
+ return someskip(lineskip,width,stretch,shrink,stretch_order,shrink_order)
+end
+
+function nutpool.baselineskip(width,stretch,shrink)
+ return someskip(baselineskip,width,stretch,shrink)
+end
+
+function nutpool.disc(pre,post,replace)
+ local d = copy_nut(disc)
+ if pre or post or replace then
+ setdisc(d,pre,post,replace)
+ end
+ return d
+end
+
+function nutpool.direction(dir,swap)
+ local t = copy_nut(textdir)
+ if not dir then
+ -- just a l2r start node
+ elseif swap then
+ setdirection(t,dir,true)
+ else
+ setdirection(t,dir,false)
+ end
+ return t
+end
+
+function nutpool.rule(width,height,depth) -- w/h/d == nil will let them adapt
+ local n = copy_nut(rule)
+ if width or height or depth then
+ setwhd(n,width,height,depth)
+ end
+ return n
+end
+
+function nutpool.emptyrule(width,height,depth) -- w/h/d == nil will let them adapt
+ local n = copy_nut(emptyrule)
+ if width or height or depth then
+ setwhd(n,width,height,depth)
+ end
+ return n
+end
+
+function nutpool.userrule(width,height,depth) -- w/h/d == nil will let them adapt
+ local n = copy_nut(userrule)
+ if width or height or depth then
+ setwhd(n,width,height,depth)
+ end
+ return n
+end
+
+function nutpool.outlinerule(width,height,depth,line) -- w/h/d == nil will let them adapt
+ local n = copy_nut(outlinerule)
+ if width or height or depth then
+ setwhd(n,width,height,depth)
+ end
+ if line then
+ setruledata(n,line)
+ end
+ return n
+end
+
+function nutpool.leader(width,list)
+ local n = copy_nut(cleader)
+ if width then
+ setwidth(n,width)
+ end
+ if list then
+ setleader(n,list)
+ end
+ return n
+end
+
+function nutpool.leftmarginkern(glyph,width)
+ local n = copy_nut(left_margin_kern)
+ if not glyph then
+ report_nodes("invalid pointer to left margin glyph node")
+ elseif getid(glyph) ~= glyph_code then
+ report_nodes("invalid node type %a for %s margin glyph node",nodecodes[glyph],"left")
+ else
+ setfield(n,"glyph",glyph)
+ end
+ if width and width ~= 0 then
+ setwidth(n,width)
+ end
+ return n
+end
+
+function nutpool.rightmarginkern(glyph,width)
+ local n = copy_nut(right_margin_kern)
+ if not glyph then
+ report_nodes("invalid pointer to right margin glyph node")
+ elseif getid(glyph) ~= glyph_code then
+ report_nodes("invalid node type %a for %s margin glyph node",nodecodes[p],"right")
+ else
+ setfield(n,"glyph",glyph)
+ end
+ if width and width ~= 0 then
+ setwidth(n,width)
+ end
+ return n
+end
+
+function nutpool.temp()
+ return copy_nut(temp)
+end
+
+function nutpool.noad() return copy_nut(noad) end
+function nutpool.delimiter() return copy_nut(delimiter) end nutpool.delim = nutpool.delimiter
+function nutpool.fence() return copy_nut(fence) end
+function nutpool.submlist() return copy_nut(submlist) end
+function nutpool.noad() return copy_nut(noad) end
+function nutpool.fence() return copy_nut(fence) end
+function nutpool.accent() return copy_nut(accent) end
+function nutpool.radical() return copy_nut(radical) end
+function nutpool.fraction() return copy_nut(fraction) end
+function nutpool.subbox() return copy_nut(subbox) end
+function nutpool.mathchar() return copy_nut(mathchar) end
+function nutpool.mathtextchar() return copy_nut(mathtextchar) end
+function nutpool.choice() return copy_nut(choice) end
+
+local function new_hlist(list,width,height,depth,shift)
+ local n = copy_nut(hlist)
+ if list then
+ setlist(n,list)
+ end
+ if width or height or depth then
+ setwhd(n,width,height,depth)
+ end
+ if shift and shift ~= 0 then
+ setshift(n,shift)
+ end
+ return n
+end
+
+local function new_vlist(list,width,height,depth,shift)
+ local n = copy_nut(vlist)
+ if list then
+ setlist(n,list)
+ end
+ if width or height or depth then
+ setwhd(n,width,height,depth)
+ end
+ if shift and shift ~= 0 then
+ setshift(n,shift)
+ end
+ return n
+end
+
+nutpool.hlist = new_hlist
+nutpool.vlist = new_vlist
+
+function nodepool.hlist(list,width,height,depth,shift)
+ return tonode(new_hlist(list and tonut(list),width,height,depth,shift))
+end
+
+function nodepool.vlist(list,width,height,depth,shift)
+ return tonode(new_vlist(list and tonut(list),width,height,depth,shift))
+end
+
+function nutpool.usernode(id,data)
+ local n = copy_nut(user_node)
+ nodeproperties[n] = {
+ id = id,
+ data = data,
+ }
+ return n
+end
+
+-- housekeeping
+
+local function cleanup(nofboxes) -- todo
+ local tracers = nodes.tracers
+ if tracers and tracers.steppers then -- to be resolved
+ tracers.steppers.reset() -- todo: make a registration subsystem
+ end
+ local nl = 0
+ local nr = nofreserved
+ for i=1,nofreserved do
+ local ri = reserved[i]
+ flush_nut(reserved[i])
+ end
+ if nofboxes then
+ for i=0,nofboxes do
+ local l = getbox(i)
+ if l then
+ flush_nut(l) -- also list ?
+ nl = nl + 1
+ end
+ end
+ end
+ reserved = { }
+ nofreserved = 0
+ return nr, nl, nofboxes -- can be nil
+end
+
+local usage = node.inuse
+local stock = node.instock
+
+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()
+ return format("%s nodes, %s lists of %s", cleanup(texgetcount("c_syst_last_allocated_box")))
+end) -- \topofboxstack
+
+statistics.register("node memory usage", function() -- comes after cleanup !
+ local used = usage()
+ if next(used) then
+ local t, n = { }, 0
+ for k, v in table.sortedhash(used) do
+ n = n + 1 ; t[n] = format("%s %s",v,k)
+ end
+ return table.concat(t,", ")
+ end
+end)
+
+lua.registerfinalizer(cleanup, "cleanup reserved nodes")
+
+do
+
+ local glyph = glyph
+ local traverse_id = nuts.traverse_id
+
+ local traversers = table.setmetatableindex(function(t,k)
+ local v = traverse_id(type(k) == "number" and k or nodecodes[k],glyph)
+ t[k] = v
+ return v
+ end)
+
+ -- these are special:
+
+ traversers.node = nuts.traverse (glyph)
+ traversers.char = nuts.traverse_char (glyph)
+ traversers.glyph = nuts.traverse_glyph (glyph)
+ traversers.list = nuts.traverse_list (glyph)
+ traversers.content = nuts.traverse_content(glyph)
+
+ nuts.traversers = traversers
+
+end