diff options
Diffstat (limited to 'tex/context/base/node-res.lua')
-rw-r--r-- | tex/context/base/node-res.lua | 812 |
1 files changed, 406 insertions, 406 deletions
diff --git a/tex/context/base/node-res.lua b/tex/context/base/node-res.lua index 768aac404..6ec6895c8 100644 --- a/tex/context/base/node-res.lua +++ b/tex/context/base/node-res.lua @@ -1,406 +1,406 @@ -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 gmatch, format = string.gmatch, string.format -local tonumber, round = tonumber, math.round - ---[[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 report_nodes = logs.reporter("nodes","housekeeping") - -local nodes, node = nodes, node - -local copy_node = node.copy -local free_node = node.free -local free_list = node.flush_list -local new_node = node.new - -nodes.pool = nodes.pool or { } -local pool = nodes.pool - -local whatsitcodes = nodes.whatsitcodes -local skipcodes = nodes.skipcodes -local kerncodes = nodes.kerncodes -local nodecodes = nodes.nodecodes - -local glyph_code = nodecodes.glyph - -local allocate = utilities.storage.allocate - -local reserved, nofreserved = { }, 0 - -local function register_node(n) - nofreserved = nofreserved + 1 - reserved[nofreserved] = n - return n -end - -pool.register = register_node - -function pool.cleanup(nofboxes) -- todo - if nodes.tracers.steppers then -- to be resolved - nodes.tracers.steppers.reset() -- todo: make a registration subsystem - end - local nl, nr = 0, nofreserved - for i=1,nofreserved do - local ri = reserved[i] - -- if not (ri.id == glue_spec and not ri.is_writable) then - free_node(reserved[i]) - -- end - end - if nofboxes then - local tb = tex.box - for i=0,nofboxes do - local l = tb[i] - if l then - free_node(tb[i]) - nl = nl + 1 - end - end - end - reserved = { } - nofreserved = 0 - return nr, nl, nofboxes -- can be nil -end - -function pool.usage() - local t = { } - for n, tag in gmatch(status.node_mem_usage,"(%d+) ([a-z_]+)") do - t[tag] = n - end - return t -end - -local disc = register_node(new_node("disc")) -local kern = register_node(new_node("kern",kerncodes.userkern)) -local fontkern = register_node(new_node("kern",kerncodes.fontkern)) -local penalty = register_node(new_node("penalty")) -local glue = register_node(new_node("glue")) -- glue.spec = nil -local glue_spec = register_node(new_node("glue_spec")) -local glyph = register_node(new_node("glyph",0)) -local textdir = register_node(new_node("whatsit",whatsitcodes.dir)) -local latelua = register_node(new_node("whatsit",whatsitcodes.latelua)) -local special = register_node(new_node("whatsit",whatsitcodes.special)) -local user_n = register_node(new_node("whatsit",whatsitcodes.userdefined)) user_n.type = 100 -- 44 -local user_l = register_node(new_node("whatsit",whatsitcodes.userdefined)) user_l.type = 110 -- 44 -local user_s = register_node(new_node("whatsit",whatsitcodes.userdefined)) user_s.type = 115 -- 44 -local user_t = register_node(new_node("whatsit",whatsitcodes.userdefined)) user_t.type = 116 -- 44 -local left_margin_kern = register_node(new_node("margin_kern",0)) -local right_margin_kern = register_node(new_node("margin_kern",1)) -local lineskip = register_node(new_node("glue",skipcodes.lineskip)) -local baselineskip = register_node(new_node("glue",skipcodes.baselineskip)) -local leftskip = register_node(new_node("glue",skipcodes.leftskip)) -local rightskip = register_node(new_node("glue",skipcodes.rightskip)) -local temp = register_node(new_node("temp",0)) -local noad = register_node(new_node("noad")) - --- the dir field needs to be set otherwise crash: - -local rule = register_node(new_node("rule")) rule .dir = "TLT" -local hlist = register_node(new_node("hlist")) hlist.dir = "TLT" -local vlist = register_node(new_node("vlist")) vlist.dir = "TLT" - -function pool.zeroglue(n) - local s = n.spec - return not writable or ( - s.width == 0 - and s.stretch == 0 - and s.shrink == 0 - and s.stretch_order == 0 - and s.shrink_order == 0 - ) -end - -function pool.glyph(fnt,chr) - local n = copy_node(glyph) - if fnt then n.font = fnt end - if chr then n.char = chr end - return n -end - -function pool.penalty(p) - local n = copy_node(penalty) - n.penalty = p - return n -end - -function pool.kern(k) - local n = copy_node(kern) - n.kern = k - return n -end - -function pool.fontkern(k) - local n = copy_node(fontkern) - n.kern = k - return n -end - -function pool.gluespec(width,stretch,shrink,stretch_order,shrink_order) - local s = copy_node(glue_spec) - if width then s.width = width end - if stretch then s.stretch = stretch end - if shrink then s.shrink = shrink end - if stretch_order then s.stretch_order = stretch_order end - if shrink_order then s.shrink_order = shrink_order end - return s -end - -local function someskip(skip,width,stretch,shrink,stretch_order,shrink_order) - local n = copy_node(skip) - if not width then - -- no spec - elseif width == false or tonumber(width) then - local s = copy_node(glue_spec) - if width then s.width = width end - if stretch then s.stretch = stretch end - if shrink then s.shrink = shrink end - if stretch_order then s.stretch_order = stretch_order end - if shrink_order then s.shrink_order = shrink_order end - n.spec = s - else - -- shared - n.spec = copy_node(width) - end - return n -end - -function pool.stretch(a,b) - local n = copy_node(glue) - local s = copy_node(glue_spec) - if b then - s.stretch = a - s.stretch_order = b - else - s.stretch = 1 - s.stretch_order = a or 1 - end - n.spec = s - return n -end - -function pool.shrink(a,b) - local n = copy_node(glue) - local s = copy_node(glue_spec) - if b then - s.shrink = a - s.shrink_order = b - else - s.shrink = 1 - s.shrink_order = a or 1 - end - n.spec = s - return n -end - - -function pool.glue(width,stretch,shrink,stretch_order,shrink_order) - return someskip(glue,width,stretch,shrink,stretch_order,shrink_order) -end - -function pool.leftskip(width,stretch,shrink,stretch_order,shrink_order) - return someskip(leftskip,width,stretch,shrink,stretch_order,shrink_order) -end - -function pool.rightskip(width,stretch,shrink,stretch_order,shrink_order) - return someskip(rightskip,width,stretch,shrink,stretch_order,shrink_order) -end - -function pool.lineskip(width,stretch,shrink,stretch_order,shrink_order) - return someskip(lineskip,width,stretch,shrink,stretch_order,shrink_order) -end - -function pool.baselineskip(width,stretch,shrink) - return someskip(baselineskip,width,stretch,shrink) -end - -function pool.disc() - return copy_node(disc) -end - -function pool.textdir(dir) - local t = copy_node(textdir) - t.dir = dir - return t -end - -function pool.rule(width,height,depth,dir) -- w/h/d == nil will let them adapt - local n = copy_node(rule) - if width then n.width = width end - if height then n.height = height end - if depth then n.depth = depth end - if dir then n.dir = dir end - return n -end - -if node.has_field(latelua,'string') then - function pool.latelua(code) - local n = copy_node(latelua) - n.string = code - return n - end -else - function pool.latelua(code) - local n = copy_node(latelua) - n.data = code - return n - end -end - -function pool.leftmarginkern(glyph,width) - local n = copy_node(left_margin_kern) - if not glyph then - report_nodes("invalid pointer to left margin glyph node") - elseif glyph.id ~= glyph_code then - report_nodes("invalid node type %a for %s margin glyph node",nodecodes[glyph],"left") - else - n.glyph = glyph - end - if width then - n.width = width - end - return n -end - -function pool.rightmarginkern(glyph,width) - local n = copy_node(right_margin_kern) - if not glyph then - report_nodes("invalid pointer to right margin glyph node") - elseif glyph.id ~= glyph_code then - report_nodes("invalid node type %a for %s margin glyph node",nodecodes[p],"right") - else - n.glyph = glyph - end - if width then - n.width = width - end - return n -end - -function pool.temp() - return copy_node(temp) -end - -function pool.noad() - return copy_node(noad) -end - -function pool.hlist() - return copy_node(hlist) -end - -function pool.vlist() - return copy_node(vlist) -end - ---[[ -<p>At some point we ran into a problem that the glue specification -of the zeropoint dimension was overwritten when adapting a glue spec -node. This is a side effect of glue specs being shared. After a -couple of hours tracing and debugging Taco and I came to the -conclusion that it made no sense to complicate the spec allocator -and settled on a writable flag. This all is a side effect of the -fact that some glues use reserved memory slots (with the zeropoint -glue being a noticeable one). So, next we wrap this into a function -and hide it for the user. And yes, LuaTeX now gives a warning as -well.</p> -]]-- - -function nodes.writable_spec(n) -- not pool - local spec = n.spec - if not spec then - spec = copy_node(glue_spec) - n.spec = spec - elseif not spec.writable then - spec = copy_node(spec) - n.spec = spec - end - return spec -end - --- local num = userids["my id"] --- local str = userids[num] - -local userids = allocate() pool.userids = userids -local lastid = 0 - -setmetatable(userids, { - __index = function(t,k) - if type(k) == "string" then - lastid = lastid + 1 - rawset(userids,lastid,k) - rawset(userids,k,lastid) - return lastid - else - rawset(userids,k,k) - return k - end - end, - __call = function(t,k) - return t[k] - end -} ) - -function pool.usernumber(id,num) - local n = copy_node(user_n) - if num then - n.user_id, n.value = id, num - elseif id then - n.value = id - end - return n -end - -function pool.userlist(id,list) - local n = copy_node(user_l) - if list then - n.user_id, n.value = id, list - else - n.value = id - end - return n -end - -function pool.userstring(id,str) - local n = copy_node(user_s) - if str then - n.user_id, n.value = id, str - else - n.value = id - end - return n -end - -function pool.usertokens(id,tokens) - local n = copy_node(user_t) - if tokens then - n.user_id, n.value = id, tokens - else - n.value = id - end - return n -end - -function pool.special(str) - local n = copy_node(special) - n.data = str - return n -end - -statistics.register("cleaned up reserved nodes", function() - return format("%s nodes, %s lists of %s", pool.cleanup(tex.count["c_syst_last_allocated_box"])) -end) -- \topofboxstack - -statistics.register("node memory usage", function() -- comes after cleanup ! - return status.node_mem_usage -end) - -lua.registerfinalizer(pool.cleanup, "cleanup reserved nodes") +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 gmatch, format = string.gmatch, string.format
+local tonumber, round = tonumber, math.round
+
+--[[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 report_nodes = logs.reporter("nodes","housekeeping")
+
+local nodes, node = nodes, node
+
+local copy_node = node.copy
+local free_node = node.free
+local free_list = node.flush_list
+local new_node = node.new
+
+nodes.pool = nodes.pool or { }
+local pool = nodes.pool
+
+local whatsitcodes = nodes.whatsitcodes
+local skipcodes = nodes.skipcodes
+local kerncodes = nodes.kerncodes
+local nodecodes = nodes.nodecodes
+
+local glyph_code = nodecodes.glyph
+
+local allocate = utilities.storage.allocate
+
+local reserved, nofreserved = { }, 0
+
+local function register_node(n)
+ nofreserved = nofreserved + 1
+ reserved[nofreserved] = n
+ return n
+end
+
+pool.register = register_node
+
+function pool.cleanup(nofboxes) -- todo
+ if nodes.tracers.steppers then -- to be resolved
+ nodes.tracers.steppers.reset() -- todo: make a registration subsystem
+ end
+ local nl, nr = 0, nofreserved
+ for i=1,nofreserved do
+ local ri = reserved[i]
+ -- if not (ri.id == glue_spec and not ri.is_writable) then
+ free_node(reserved[i])
+ -- end
+ end
+ if nofboxes then
+ local tb = tex.box
+ for i=0,nofboxes do
+ local l = tb[i]
+ if l then
+ free_node(tb[i])
+ nl = nl + 1
+ end
+ end
+ end
+ reserved = { }
+ nofreserved = 0
+ return nr, nl, nofboxes -- can be nil
+end
+
+function pool.usage()
+ local t = { }
+ for n, tag in gmatch(status.node_mem_usage,"(%d+) ([a-z_]+)") do
+ t[tag] = n
+ end
+ return t
+end
+
+local disc = register_node(new_node("disc"))
+local kern = register_node(new_node("kern",kerncodes.userkern))
+local fontkern = register_node(new_node("kern",kerncodes.fontkern))
+local penalty = register_node(new_node("penalty"))
+local glue = register_node(new_node("glue")) -- glue.spec = nil
+local glue_spec = register_node(new_node("glue_spec"))
+local glyph = register_node(new_node("glyph",0))
+local textdir = register_node(new_node("whatsit",whatsitcodes.dir))
+local latelua = register_node(new_node("whatsit",whatsitcodes.latelua))
+local special = register_node(new_node("whatsit",whatsitcodes.special))
+local user_n = register_node(new_node("whatsit",whatsitcodes.userdefined)) user_n.type = 100 -- 44
+local user_l = register_node(new_node("whatsit",whatsitcodes.userdefined)) user_l.type = 110 -- 44
+local user_s = register_node(new_node("whatsit",whatsitcodes.userdefined)) user_s.type = 115 -- 44
+local user_t = register_node(new_node("whatsit",whatsitcodes.userdefined)) user_t.type = 116 -- 44
+local left_margin_kern = register_node(new_node("margin_kern",0))
+local right_margin_kern = register_node(new_node("margin_kern",1))
+local lineskip = register_node(new_node("glue",skipcodes.lineskip))
+local baselineskip = register_node(new_node("glue",skipcodes.baselineskip))
+local leftskip = register_node(new_node("glue",skipcodes.leftskip))
+local rightskip = register_node(new_node("glue",skipcodes.rightskip))
+local temp = register_node(new_node("temp",0))
+local noad = register_node(new_node("noad"))
+
+-- the dir field needs to be set otherwise crash:
+
+local rule = register_node(new_node("rule")) rule .dir = "TLT"
+local hlist = register_node(new_node("hlist")) hlist.dir = "TLT"
+local vlist = register_node(new_node("vlist")) vlist.dir = "TLT"
+
+function pool.zeroglue(n)
+ local s = n.spec
+ return not writable or (
+ s.width == 0
+ and s.stretch == 0
+ and s.shrink == 0
+ and s.stretch_order == 0
+ and s.shrink_order == 0
+ )
+end
+
+function pool.glyph(fnt,chr)
+ local n = copy_node(glyph)
+ if fnt then n.font = fnt end
+ if chr then n.char = chr end
+ return n
+end
+
+function pool.penalty(p)
+ local n = copy_node(penalty)
+ n.penalty = p
+ return n
+end
+
+function pool.kern(k)
+ local n = copy_node(kern)
+ n.kern = k
+ return n
+end
+
+function pool.fontkern(k)
+ local n = copy_node(fontkern)
+ n.kern = k
+ return n
+end
+
+function pool.gluespec(width,stretch,shrink,stretch_order,shrink_order)
+ local s = copy_node(glue_spec)
+ if width then s.width = width end
+ if stretch then s.stretch = stretch end
+ if shrink then s.shrink = shrink end
+ if stretch_order then s.stretch_order = stretch_order end
+ if shrink_order then s.shrink_order = shrink_order end
+ return s
+end
+
+local function someskip(skip,width,stretch,shrink,stretch_order,shrink_order)
+ local n = copy_node(skip)
+ if not width then
+ -- no spec
+ elseif width == false or tonumber(width) then
+ local s = copy_node(glue_spec)
+ if width then s.width = width end
+ if stretch then s.stretch = stretch end
+ if shrink then s.shrink = shrink end
+ if stretch_order then s.stretch_order = stretch_order end
+ if shrink_order then s.shrink_order = shrink_order end
+ n.spec = s
+ else
+ -- shared
+ n.spec = copy_node(width)
+ end
+ return n
+end
+
+function pool.stretch(a,b)
+ local n = copy_node(glue)
+ local s = copy_node(glue_spec)
+ if b then
+ s.stretch = a
+ s.stretch_order = b
+ else
+ s.stretch = 1
+ s.stretch_order = a or 1
+ end
+ n.spec = s
+ return n
+end
+
+function pool.shrink(a,b)
+ local n = copy_node(glue)
+ local s = copy_node(glue_spec)
+ if b then
+ s.shrink = a
+ s.shrink_order = b
+ else
+ s.shrink = 1
+ s.shrink_order = a or 1
+ end
+ n.spec = s
+ return n
+end
+
+
+function pool.glue(width,stretch,shrink,stretch_order,shrink_order)
+ return someskip(glue,width,stretch,shrink,stretch_order,shrink_order)
+end
+
+function pool.leftskip(width,stretch,shrink,stretch_order,shrink_order)
+ return someskip(leftskip,width,stretch,shrink,stretch_order,shrink_order)
+end
+
+function pool.rightskip(width,stretch,shrink,stretch_order,shrink_order)
+ return someskip(rightskip,width,stretch,shrink,stretch_order,shrink_order)
+end
+
+function pool.lineskip(width,stretch,shrink,stretch_order,shrink_order)
+ return someskip(lineskip,width,stretch,shrink,stretch_order,shrink_order)
+end
+
+function pool.baselineskip(width,stretch,shrink)
+ return someskip(baselineskip,width,stretch,shrink)
+end
+
+function pool.disc()
+ return copy_node(disc)
+end
+
+function pool.textdir(dir)
+ local t = copy_node(textdir)
+ t.dir = dir
+ return t
+end
+
+function pool.rule(width,height,depth,dir) -- w/h/d == nil will let them adapt
+ local n = copy_node(rule)
+ if width then n.width = width end
+ if height then n.height = height end
+ if depth then n.depth = depth end
+ if dir then n.dir = dir end
+ return n
+end
+
+if node.has_field(latelua,'string') then
+ function pool.latelua(code)
+ local n = copy_node(latelua)
+ n.string = code
+ return n
+ end
+else
+ function pool.latelua(code)
+ local n = copy_node(latelua)
+ n.data = code
+ return n
+ end
+end
+
+function pool.leftmarginkern(glyph,width)
+ local n = copy_node(left_margin_kern)
+ if not glyph then
+ report_nodes("invalid pointer to left margin glyph node")
+ elseif glyph.id ~= glyph_code then
+ report_nodes("invalid node type %a for %s margin glyph node",nodecodes[glyph],"left")
+ else
+ n.glyph = glyph
+ end
+ if width then
+ n.width = width
+ end
+ return n
+end
+
+function pool.rightmarginkern(glyph,width)
+ local n = copy_node(right_margin_kern)
+ if not glyph then
+ report_nodes("invalid pointer to right margin glyph node")
+ elseif glyph.id ~= glyph_code then
+ report_nodes("invalid node type %a for %s margin glyph node",nodecodes[p],"right")
+ else
+ n.glyph = glyph
+ end
+ if width then
+ n.width = width
+ end
+ return n
+end
+
+function pool.temp()
+ return copy_node(temp)
+end
+
+function pool.noad()
+ return copy_node(noad)
+end
+
+function pool.hlist()
+ return copy_node(hlist)
+end
+
+function pool.vlist()
+ return copy_node(vlist)
+end
+
+--[[
+<p>At some point we ran into a problem that the glue specification
+of the zeropoint dimension was overwritten when adapting a glue spec
+node. This is a side effect of glue specs being shared. After a
+couple of hours tracing and debugging Taco and I came to the
+conclusion that it made no sense to complicate the spec allocator
+and settled on a writable flag. This all is a side effect of the
+fact that some glues use reserved memory slots (with the zeropoint
+glue being a noticeable one). So, next we wrap this into a function
+and hide it for the user. And yes, LuaTeX now gives a warning as
+well.</p>
+]]--
+
+function nodes.writable_spec(n) -- not pool
+ local spec = n.spec
+ if not spec then
+ spec = copy_node(glue_spec)
+ n.spec = spec
+ elseif not spec.writable then
+ spec = copy_node(spec)
+ n.spec = spec
+ end
+ return spec
+end
+
+-- local num = userids["my id"]
+-- local str = userids[num]
+
+local userids = allocate() pool.userids = userids
+local lastid = 0
+
+setmetatable(userids, {
+ __index = function(t,k)
+ if type(k) == "string" then
+ lastid = lastid + 1
+ rawset(userids,lastid,k)
+ rawset(userids,k,lastid)
+ return lastid
+ else
+ rawset(userids,k,k)
+ return k
+ end
+ end,
+ __call = function(t,k)
+ return t[k]
+ end
+} )
+
+function pool.usernumber(id,num)
+ local n = copy_node(user_n)
+ if num then
+ n.user_id, n.value = id, num
+ elseif id then
+ n.value = id
+ end
+ return n
+end
+
+function pool.userlist(id,list)
+ local n = copy_node(user_l)
+ if list then
+ n.user_id, n.value = id, list
+ else
+ n.value = id
+ end
+ return n
+end
+
+function pool.userstring(id,str)
+ local n = copy_node(user_s)
+ if str then
+ n.user_id, n.value = id, str
+ else
+ n.value = id
+ end
+ return n
+end
+
+function pool.usertokens(id,tokens)
+ local n = copy_node(user_t)
+ if tokens then
+ n.user_id, n.value = id, tokens
+ else
+ n.value = id
+ end
+ return n
+end
+
+function pool.special(str)
+ local n = copy_node(special)
+ n.data = str
+ return n
+end
+
+statistics.register("cleaned up reserved nodes", function()
+ return format("%s nodes, %s lists of %s", pool.cleanup(tex.count["c_syst_last_allocated_box"]))
+end) -- \topofboxstack
+
+statistics.register("node memory usage", function() -- comes after cleanup !
+ return status.node_mem_usage
+end)
+
+lua.registerfinalizer(pool.cleanup, "cleanup reserved nodes")
|