summaryrefslogtreecommitdiff
path: root/tex/context/base/node-tra.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/node-tra.lua')
-rw-r--r--tex/context/base/node-tra.lua1058
1 files changed, 529 insertions, 529 deletions
diff --git a/tex/context/base/node-tra.lua b/tex/context/base/node-tra.lua
index 916b2143d..f194239bb 100644
--- a/tex/context/base/node-tra.lua
+++ b/tex/context/base/node-tra.lua
@@ -1,529 +1,529 @@
-if not modules then modules = { } end modules ['node-tra'] = {
- 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>This is rather experimental. We need more control and some of this
-might become a runtime module instead. This module will be cleaned up!</p>
---ldx]]--
-
-local utfchar = utf.char
-local format, match, gmatch, concat, rep = string.format, string.match, string.gmatch, table.concat, string.rep
-local lpegmatch = lpeg.match
-local clock = os.gettimeofday or os.clock -- should go in environment
-
-local report_nodes = logs.reporter("nodes","tracing")
-
-nodes = nodes or { }
-
-local nodes, node, context = nodes, node, context
-
-local tracers = nodes.tracers or { }
-nodes.tracers = tracers
-
-local tasks = nodes.tasks or { }
-nodes.tasks = tasks
-
-local handlers = nodes.handlers or {}
-nodes.handlers = handlers
-
-local injections = nodes.injections or { }
-nodes.injections = injections
-
-local traverse_nodes = node.traverse
-local traverse_by_id = node.traverse_id
-local count_nodes = nodes.count
-
-local nodecodes = nodes.nodecodes
-local whatcodes = nodes.whatcodes
-local skipcodes = nodes.skipcodes
-local fillcodes = nodes.fillcodes
-
-local glyph_code = nodecodes.glyph
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
-local disc_code = nodecodes.disc
-local glue_code = nodecodes.glue
-local kern_code = nodecodes.kern
-local rule_code = nodecodes.rule
-local whatsit_code = nodecodes.whatsit
-local spec_code = nodecodes.glue_spec
-
-local localpar_code = whatcodes.localpar
-local dir_code = whatcodes.dir
-
-local nodepool = nodes.pool
-
-local dimenfactors = number.dimenfactors
-local formatters = string.formatters
-
--- this will be reorganized:
-
-function nodes.showlist(head, message)
- if message then
- report_nodes(message)
- end
- for n in traverse_nodes(head) do
- report_nodes(tostring(n))
- end
-end
-
-function nodes.handlers.checkglyphs(head,message)
- local t = { }
- for g in traverse_by_id(glyph_code,head) do
- t[#t+1] = formatters["%U:%s"](g.char,g.subtype)
- end
- if #t > 0 then
- if message and message ~= "" then
- report_nodes("%s, %s glyphs: % t",message,#t,t)
- else
- report_nodes("%s glyphs: % t",#t,t)
- end
- end
- return false
-end
-
-function nodes.handlers.checkforleaks(sparse)
- local l = { }
- local q = node.usedlist()
- for p in traverse(q) do
- local s = table.serialize(nodes.astable(p,sparse),nodecodes[p.id])
- l[s] = (l[s] or 0) + 1
- end
- node.flush_list(q)
- for k, v in next, l do
- write_nl(formatters["%s * %s"](v,k))
- end
-end
-
-local f_sequence = formatters["U+%04X:%s"]
-
-local function tosequence(start,stop,compact)
- if start then
- local t = { }
- while start do
- local id = start.id
- if id == glyph_code then
- local c = start.char
- if compact then
- if start.components then
- t[#t+1] = tosequence(start.components,nil,compact)
- else
- t[#t+1] = utfchar(c)
- end
- else
- t[#t+1] = f_sequence(c,utfchar(c))
- end
- elseif id == whatsit_code and start.subtype == localpar_code or start.subtype == dir_code then
- t[#t+1] = "[" .. start.dir .. "]"
- elseif id == rule_code then
- if compact then
- t[#t+1] = "|"
- else
- t[#t+1] = nodecodes[id]
- end
- else
- if compact then
- t[#t+1] = "[]"
- else
- t[#t+1] = nodecodes[id]
- end
- end
- if start == stop then
- break
- else
- start = start.next
- end
- end
- if compact then
- return concat(t)
- else
- return concat(t," ")
- end
- else
- return "[empty]"
- end
-end
-
-nodes.tosequence = tosequence
-
-function nodes.report(t,done)
- report_nodes("output %a, %changed %a, %s nodes",status.output_active,done,count_nodes(t))
-end
-
-function nodes.packlist(head)
- local t = { }
- for n in traverse(head) do
- t[#t+1] = tostring(n)
- end
- return t
-end
-
-function nodes.idstostring(head,tail)
- local t, last_id, last_n = { }, nil, 0
- for n in traverse_nodes(head,tail) do -- hm, does not stop at tail
- local id = n.id
- if not last_id then
- last_id, last_n = id, 1
- elseif last_id == id then
- last_n = last_n + 1
- else
- if last_n > 1 then
- t[#t+1] = formatters["[%s*%s]"](last_n,nodecodes[last_id] or "?")
- else
- t[#t+1] = formatters["[%s]"](nodecodes[last_id] or "?")
- end
- last_id, last_n = id, 1
- end
- if n == tail then
- break
- end
- end
- if not last_id then
- t[#t+1] = "no nodes"
- elseif last_n > 1 then
- t[#t+1] = formatters["[%s*%s]"](last_n,nodecodes[last_id] or "?")
- else
- t[#t+1] = formatters["[%s]"](nodecodes[last_id] or "?")
- end
- return concat(t," ")
-end
-
--- function nodes.xidstostring(head,tail) -- only for special tracing of backlinks
--- local n = head
--- while n.next do
--- n = n.next
--- end
--- local t, last_id, last_n = { }, nil, 0
--- while n do
--- local id = n.id
--- if not last_id then
--- last_id, last_n = id, 1
--- elseif last_id == id then
--- last_n = last_n + 1
--- else
--- if last_n > 1 then
--- t[#t+1] = formatters["[%s*%s]"](last_n,nodecodes[last_id] or "?")
--- else
--- t[#t+1] = formatters["[%s]"](nodecodes[last_id] or "?")
--- end
--- last_id, last_n = id, 1
--- end
--- if n == head then
--- break
--- end
--- n = n.prev
--- end
--- if not last_id then
--- t[#t+1] = "no nodes"
--- elseif last_n > 1 then
--- t[#t+1] = formatters["[%s*%s]"](last_n,nodecodes[last_id] or "?")
--- else
--- t[#t+1] = formatters["[%s]"](nodecodes[last_id] or "?")
--- end
--- return table.concat(table.reversed(t)," ")
--- end
-
-local function showsimplelist(h,depth,n)
- while h do
- write_nl(rep(" ",n) .. tostring(h))
- if not depth or n < depth then
- local id = h.id
- if id == hlist_code or id == vlist_code then
- showsimplelist(h.list,depth,n+1)
- end
- end
- h = h.next
- end
-end
-
---~ \startluacode
---~ callback.register('buildpage_filter',function() nodes.show_simple_list(tex.lists.contrib_head) end)
---~ \stopluacode
---~ \vbox{b\footnote{n}a}
---~ \startluacode
---~ callback.register('buildpage_filter',nil)
---~ \stopluacode
-
-nodes.showsimplelist = function(h,depth) showsimplelist(h,depth,0) end
-
-local function listtoutf(h,joiner,textonly,last)
- local joiner = (joiner == true and utfchar(0x200C)) or joiner -- zwnj
- local w = { }
- while h do
- local id = h.id
- if id == glyph_code then -- always true
- w[#w+1] = utfchar(h.char)
- if joiner then
- w[#w+1] = joiner
- end
- elseif id == disc_code then
- local pre, rep, pos = h.pre, h.replace, h.post
- w[#w+1] = formatters["[%s|%s|%s]"] (
- pre and listtoutf(pre,joiner,textonly) or "",
- rep and listtoutf(rep,joiner,textonly) or "",
- mid and listtoutf(mid,joiner,textonly) or ""
- )
- elseif textonly then
- if id == glue_code and h.spec and h.spec.width > 0 then
- w[#w+1] = " "
- end
- else
- w[#w+1] = "[-]"
- end
- if h == last then
- break
- else
- h = h.next
- end
- end
- return concat(w)
-end
-
-nodes.listtoutf = listtoutf
-
-local what = { [0] = "unknown", "line", "box", "indent", "row", "cell" }
-
-local function showboxes(n,symbol,depth)
- depth, symbol = depth or 0, symbol or "."
- for n in traverse_nodes(n) do
- local id = n.id
- if id == hlist_code or id == vlist_code then
- local s = n.subtype
- report_nodes(rep(symbol,depth) .. what[s] or s)
- showboxes(n.list,symbol,depth+1)
- end
- end
-end
-
-nodes.showboxes = showboxes
-
-local ptfactor = dimenfactors.pt
-local bpfactor = dimenfactors.bp
-local stripper = lpeg.patterns.stripzeros
-
--- start redefinition
---
--- -- if fmt then
--- -- return formatters[fmt](n*dimenfactors[unit],unit)
--- -- else
--- -- return match(formatters["%.20f"](n*dimenfactors[unit]),"(.-0?)0*$") .. unit
--- -- end
---
--- redefined:
-
-local dimenfactors = number.dimenfactors
-
-local function numbertodimen(d,unit,fmt,strip)
- if not d then
- local str = formatters[fmt](0,unit)
- return strip and lpegmatch(stripper,str) or str
- end
- local t = type(d)
- if t == 'string' then
- return d
- end
- if unit == true then
- unit = "pt"
- fmt = "%0.5f%s"
- else
- unit = unit or 'pt'
- if not fmt then
- fmt = "%s%s"
- elseif fmt == true then
- fmt = "%0.5f%s"
- end
- end
- if t == "number" then
- local str = formatters[fmt](d*dimenfactors[unit],unit)
- return strip and lpegmatch(stripper,str) or str
- end
- local id = node.id
- if id == kern_code then
- local str = formatters[fmt](d.width*dimenfactors[unit],unit)
- return strip and lpegmatch(stripper,str) or str
- end
- if id == glue_code then
- d = d.spec
- end
- if not d or not d.id == spec_code then
- local str = formatters[fmt](0,unit)
- return strip and lpegmatch(stripper,str) or str
- end
- local width = d.width
- local plus = d.stretch_order
- local minus = d.shrink_order
- local stretch = d.stretch
- local shrink = d.shrink
- if plus ~= 0 then
- plus = " plus " .. stretch/65536 .. fillcodes[plus]
- elseif stretch ~= 0 then
- plus = formatters[fmt](stretch*dimenfactors[unit],unit)
- plus = " plus " .. (strip and lpegmatch(stripper,plus) or plus)
- else
- plus = ""
- end
- if minus ~= 0 then
- minus = " minus " .. shrink/65536 .. fillcodes[minus]
- elseif shrink ~= 0 then
- minus = formatters[fmt](shrink*dimenfactors[unit],unit)
- minus = " minus " .. (strip and lpegmatch(stripper,minus) or minus)
- else
- minus = ""
- end
- local str = formatters[fmt](d.width*dimenfactors[unit],unit)
- return (strip and lpegmatch(stripper,str) or str) .. plus .. minus
-end
-
-number.todimen = numbertodimen
-
-function number.topoints (n,fmt) return numbertodimen(n,"pt",fmt) end
-function number.toinches (n,fmt) return numbertodimen(n,"in",fmt) end
-function number.tocentimeters (n,fmt) return numbertodimen(n,"cm",fmt) end
-function number.tomillimeters (n,fmt) return numbertodimen(n,"mm",fmt) end
-function number.toscaledpoints(n,fmt) return numbertodimen(n,"sp",fmt) end
-function number.toscaledpoints(n) return n .. "sp" end
-function number.tobasepoints (n,fmt) return numbertodimen(n,"bp",fmt) end
-function number.topicas (n,fmt) return numbertodimen(n "pc",fmt) end
-function number.todidots (n,fmt) return numbertodimen(n,"dd",fmt) end
-function number.tociceros (n,fmt) return numbertodimen(n,"cc",fmt) end
-function number.tonewdidots (n,fmt) return numbertodimen(n,"nd",fmt) end
-function number.tonewciceros (n,fmt) return numbertodimen(n,"nc",fmt) end
-
--- stop redefinition
-
-local points = function(n)
- if not n or n == 0 then
- return "0pt"
- elseif type(n) == "number" then
- return lpegmatch(stripper,format("%.5fpt",n*ptfactor)) -- faster than formatter
- else
- return numbertodimen(n,"pt",true,true) -- also deals with nodes
- end
-end
-
-local basepoints = function(n)
- if not n or n == 0 then
- return "0bp"
- elseif type(n) == "number" then
- return lpegmatch(stripper,format("%.5fbp",n*bpfactor)) -- faster than formatter
- else
- return numbertodimen(n,"bp",true,true) -- also deals with nodes
- end
-end
-
-local pts = function(n)
- if not n or n == 0 then
- return "0pt"
- elseif type(n) == "number" then
- return format("%.5fpt",n*ptfactor) -- faster than formatter
- else
- return numbertodimen(n,"pt",true) -- also deals with nodes
- end
-end
-
-local nopts = function(n)
- if not n or n == 0 then
- return "0"
- else
- return format("%.5f",n*ptfactor) -- faster than formatter
- end
-end
-
-number.points = points
-number.basepoints = basepoints
-number.pts = pts
-number.nopts = nopts
-
-local colors = { }
-tracers.colors = colors
-
-local unsetvalue = attributes.unsetvalue
-
-local a_color = attributes.private('color')
-local a_colormodel = attributes.private('colormodel')
-local m_color = attributes.list[a_color] or { }
-
-function colors.set(n,c,s)
- local mc = m_color[c]
- if not mc then
- n[a_color] = unsetvalue
- else
- if not n[a_colormodel] then
- n[a_colormodel] = s or 1
- end
- n[a_color] = mc
- end
- return n
-end
-
-function colors.setlist(n,c,s)
- local f = n
- while n do
- local mc = m_color[c]
- if not mc then
- n[a_color] = unsetvalue
- else
- if not n[a_colormodel] then
- n[a_colormodel] = s or 1
- end
- n[a_color] = mc
- end
- n = n.next
- end
- return f
-end
-
-function colors.reset(n)
- n[a_color] = unsetvalue
- return n
-end
-
--- maybe
-
-local transparencies = { }
-tracers.transparencies = transparencies
-
-local a_transparency = attributes.private('transparency')
-local m_transparency = attributes.list[a_transparency] or { }
-
-function transparencies.set(n,t)
- local mt = m_transparency[t]
- if not mt then
- n[a_transparency] = unsetvalue
- else
- n[a_transparency] = mt
- end
- return n
-end
-
-function transparencies.setlist(n,c,s)
- local f = n
- while n do
- local mt = m_transparency[c]
- if not mt then
- n[a_transparency] = unsetvalue
- else
- n[a_transparency] = mt
- end
- n = n.next
- end
- return f
-end
-
-function transparencies.reset(n)
- n[a_transparency] = unsetvalue
- return n
-end
-
--- for the moment here
-
-nodes.visualizers = { }
-
-function nodes.visualizers.handler(head)
- return head, false
-end
+if not modules then modules = { } end modules ['node-tra'] = {
+ 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>This is rather experimental. We need more control and some of this
+might become a runtime module instead. This module will be cleaned up!</p>
+--ldx]]--
+
+local utfchar = utf.char
+local format, match, gmatch, concat, rep = string.format, string.match, string.gmatch, table.concat, string.rep
+local lpegmatch = lpeg.match
+local clock = os.gettimeofday or os.clock -- should go in environment
+
+local report_nodes = logs.reporter("nodes","tracing")
+
+nodes = nodes or { }
+
+local nodes, node, context = nodes, node, context
+
+local tracers = nodes.tracers or { }
+nodes.tracers = tracers
+
+local tasks = nodes.tasks or { }
+nodes.tasks = tasks
+
+local handlers = nodes.handlers or {}
+nodes.handlers = handlers
+
+local injections = nodes.injections or { }
+nodes.injections = injections
+
+local traverse_nodes = node.traverse
+local traverse_by_id = node.traverse_id
+local count_nodes = nodes.count
+
+local nodecodes = nodes.nodecodes
+local whatcodes = nodes.whatcodes
+local skipcodes = nodes.skipcodes
+local fillcodes = nodes.fillcodes
+
+local glyph_code = nodecodes.glyph
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local disc_code = nodecodes.disc
+local glue_code = nodecodes.glue
+local kern_code = nodecodes.kern
+local rule_code = nodecodes.rule
+local whatsit_code = nodecodes.whatsit
+local spec_code = nodecodes.glue_spec
+
+local localpar_code = whatcodes.localpar
+local dir_code = whatcodes.dir
+
+local nodepool = nodes.pool
+
+local dimenfactors = number.dimenfactors
+local formatters = string.formatters
+
+-- this will be reorganized:
+
+function nodes.showlist(head, message)
+ if message then
+ report_nodes(message)
+ end
+ for n in traverse_nodes(head) do
+ report_nodes(tostring(n))
+ end
+end
+
+function nodes.handlers.checkglyphs(head,message)
+ local t = { }
+ for g in traverse_by_id(glyph_code,head) do
+ t[#t+1] = formatters["%U:%s"](g.char,g.subtype)
+ end
+ if #t > 0 then
+ if message and message ~= "" then
+ report_nodes("%s, %s glyphs: % t",message,#t,t)
+ else
+ report_nodes("%s glyphs: % t",#t,t)
+ end
+ end
+ return false
+end
+
+function nodes.handlers.checkforleaks(sparse)
+ local l = { }
+ local q = node.usedlist()
+ for p in traverse(q) do
+ local s = table.serialize(nodes.astable(p,sparse),nodecodes[p.id])
+ l[s] = (l[s] or 0) + 1
+ end
+ node.flush_list(q)
+ for k, v in next, l do
+ write_nl(formatters["%s * %s"](v,k))
+ end
+end
+
+local f_sequence = formatters["U+%04X:%s"]
+
+local function tosequence(start,stop,compact)
+ if start then
+ local t = { }
+ while start do
+ local id = start.id
+ if id == glyph_code then
+ local c = start.char
+ if compact then
+ if start.components then
+ t[#t+1] = tosequence(start.components,nil,compact)
+ else
+ t[#t+1] = utfchar(c)
+ end
+ else
+ t[#t+1] = f_sequence(c,utfchar(c))
+ end
+ elseif id == whatsit_code and start.subtype == localpar_code or start.subtype == dir_code then
+ t[#t+1] = "[" .. start.dir .. "]"
+ elseif id == rule_code then
+ if compact then
+ t[#t+1] = "|"
+ else
+ t[#t+1] = nodecodes[id]
+ end
+ else
+ if compact then
+ t[#t+1] = "[]"
+ else
+ t[#t+1] = nodecodes[id]
+ end
+ end
+ if start == stop then
+ break
+ else
+ start = start.next
+ end
+ end
+ if compact then
+ return concat(t)
+ else
+ return concat(t," ")
+ end
+ else
+ return "[empty]"
+ end
+end
+
+nodes.tosequence = tosequence
+
+function nodes.report(t,done)
+ report_nodes("output %a, %changed %a, %s nodes",status.output_active,done,count_nodes(t))
+end
+
+function nodes.packlist(head)
+ local t = { }
+ for n in traverse(head) do
+ t[#t+1] = tostring(n)
+ end
+ return t
+end
+
+function nodes.idstostring(head,tail)
+ local t, last_id, last_n = { }, nil, 0
+ for n in traverse_nodes(head,tail) do -- hm, does not stop at tail
+ local id = n.id
+ if not last_id then
+ last_id, last_n = id, 1
+ elseif last_id == id then
+ last_n = last_n + 1
+ else
+ if last_n > 1 then
+ t[#t+1] = formatters["[%s*%s]"](last_n,nodecodes[last_id] or "?")
+ else
+ t[#t+1] = formatters["[%s]"](nodecodes[last_id] or "?")
+ end
+ last_id, last_n = id, 1
+ end
+ if n == tail then
+ break
+ end
+ end
+ if not last_id then
+ t[#t+1] = "no nodes"
+ elseif last_n > 1 then
+ t[#t+1] = formatters["[%s*%s]"](last_n,nodecodes[last_id] or "?")
+ else
+ t[#t+1] = formatters["[%s]"](nodecodes[last_id] or "?")
+ end
+ return concat(t," ")
+end
+
+-- function nodes.xidstostring(head,tail) -- only for special tracing of backlinks
+-- local n = head
+-- while n.next do
+-- n = n.next
+-- end
+-- local t, last_id, last_n = { }, nil, 0
+-- while n do
+-- local id = n.id
+-- if not last_id then
+-- last_id, last_n = id, 1
+-- elseif last_id == id then
+-- last_n = last_n + 1
+-- else
+-- if last_n > 1 then
+-- t[#t+1] = formatters["[%s*%s]"](last_n,nodecodes[last_id] or "?")
+-- else
+-- t[#t+1] = formatters["[%s]"](nodecodes[last_id] or "?")
+-- end
+-- last_id, last_n = id, 1
+-- end
+-- if n == head then
+-- break
+-- end
+-- n = n.prev
+-- end
+-- if not last_id then
+-- t[#t+1] = "no nodes"
+-- elseif last_n > 1 then
+-- t[#t+1] = formatters["[%s*%s]"](last_n,nodecodes[last_id] or "?")
+-- else
+-- t[#t+1] = formatters["[%s]"](nodecodes[last_id] or "?")
+-- end
+-- return table.concat(table.reversed(t)," ")
+-- end
+
+local function showsimplelist(h,depth,n)
+ while h do
+ write_nl(rep(" ",n) .. tostring(h))
+ if not depth or n < depth then
+ local id = h.id
+ if id == hlist_code or id == vlist_code then
+ showsimplelist(h.list,depth,n+1)
+ end
+ end
+ h = h.next
+ end
+end
+
+--~ \startluacode
+--~ callback.register('buildpage_filter',function() nodes.show_simple_list(tex.lists.contrib_head) end)
+--~ \stopluacode
+--~ \vbox{b\footnote{n}a}
+--~ \startluacode
+--~ callback.register('buildpage_filter',nil)
+--~ \stopluacode
+
+nodes.showsimplelist = function(h,depth) showsimplelist(h,depth,0) end
+
+local function listtoutf(h,joiner,textonly,last)
+ local joiner = (joiner == true and utfchar(0x200C)) or joiner -- zwnj
+ local w = { }
+ while h do
+ local id = h.id
+ if id == glyph_code then -- always true
+ w[#w+1] = utfchar(h.char)
+ if joiner then
+ w[#w+1] = joiner
+ end
+ elseif id == disc_code then
+ local pre, rep, pos = h.pre, h.replace, h.post
+ w[#w+1] = formatters["[%s|%s|%s]"] (
+ pre and listtoutf(pre,joiner,textonly) or "",
+ rep and listtoutf(rep,joiner,textonly) or "",
+ mid and listtoutf(mid,joiner,textonly) or ""
+ )
+ elseif textonly then
+ if id == glue_code and h.spec and h.spec.width > 0 then
+ w[#w+1] = " "
+ end
+ else
+ w[#w+1] = "[-]"
+ end
+ if h == last then
+ break
+ else
+ h = h.next
+ end
+ end
+ return concat(w)
+end
+
+nodes.listtoutf = listtoutf
+
+local what = { [0] = "unknown", "line", "box", "indent", "row", "cell" }
+
+local function showboxes(n,symbol,depth)
+ depth, symbol = depth or 0, symbol or "."
+ for n in traverse_nodes(n) do
+ local id = n.id
+ if id == hlist_code or id == vlist_code then
+ local s = n.subtype
+ report_nodes(rep(symbol,depth) .. what[s] or s)
+ showboxes(n.list,symbol,depth+1)
+ end
+ end
+end
+
+nodes.showboxes = showboxes
+
+local ptfactor = dimenfactors.pt
+local bpfactor = dimenfactors.bp
+local stripper = lpeg.patterns.stripzeros
+
+-- start redefinition
+--
+-- -- if fmt then
+-- -- return formatters[fmt](n*dimenfactors[unit],unit)
+-- -- else
+-- -- return match(formatters["%.20f"](n*dimenfactors[unit]),"(.-0?)0*$") .. unit
+-- -- end
+--
+-- redefined:
+
+local dimenfactors = number.dimenfactors
+
+local function numbertodimen(d,unit,fmt,strip)
+ if not d then
+ local str = formatters[fmt](0,unit)
+ return strip and lpegmatch(stripper,str) or str
+ end
+ local t = type(d)
+ if t == 'string' then
+ return d
+ end
+ if unit == true then
+ unit = "pt"
+ fmt = "%0.5f%s"
+ else
+ unit = unit or 'pt'
+ if not fmt then
+ fmt = "%s%s"
+ elseif fmt == true then
+ fmt = "%0.5f%s"
+ end
+ end
+ if t == "number" then
+ local str = formatters[fmt](d*dimenfactors[unit],unit)
+ return strip and lpegmatch(stripper,str) or str
+ end
+ local id = node.id
+ if id == kern_code then
+ local str = formatters[fmt](d.width*dimenfactors[unit],unit)
+ return strip and lpegmatch(stripper,str) or str
+ end
+ if id == glue_code then
+ d = d.spec
+ end
+ if not d or not d.id == spec_code then
+ local str = formatters[fmt](0,unit)
+ return strip and lpegmatch(stripper,str) or str
+ end
+ local width = d.width
+ local plus = d.stretch_order
+ local minus = d.shrink_order
+ local stretch = d.stretch
+ local shrink = d.shrink
+ if plus ~= 0 then
+ plus = " plus " .. stretch/65536 .. fillcodes[plus]
+ elseif stretch ~= 0 then
+ plus = formatters[fmt](stretch*dimenfactors[unit],unit)
+ plus = " plus " .. (strip and lpegmatch(stripper,plus) or plus)
+ else
+ plus = ""
+ end
+ if minus ~= 0 then
+ minus = " minus " .. shrink/65536 .. fillcodes[minus]
+ elseif shrink ~= 0 then
+ minus = formatters[fmt](shrink*dimenfactors[unit],unit)
+ minus = " minus " .. (strip and lpegmatch(stripper,minus) or minus)
+ else
+ minus = ""
+ end
+ local str = formatters[fmt](d.width*dimenfactors[unit],unit)
+ return (strip and lpegmatch(stripper,str) or str) .. plus .. minus
+end
+
+number.todimen = numbertodimen
+
+function number.topoints (n,fmt) return numbertodimen(n,"pt",fmt) end
+function number.toinches (n,fmt) return numbertodimen(n,"in",fmt) end
+function number.tocentimeters (n,fmt) return numbertodimen(n,"cm",fmt) end
+function number.tomillimeters (n,fmt) return numbertodimen(n,"mm",fmt) end
+function number.toscaledpoints(n,fmt) return numbertodimen(n,"sp",fmt) end
+function number.toscaledpoints(n) return n .. "sp" end
+function number.tobasepoints (n,fmt) return numbertodimen(n,"bp",fmt) end
+function number.topicas (n,fmt) return numbertodimen(n "pc",fmt) end
+function number.todidots (n,fmt) return numbertodimen(n,"dd",fmt) end
+function number.tociceros (n,fmt) return numbertodimen(n,"cc",fmt) end
+function number.tonewdidots (n,fmt) return numbertodimen(n,"nd",fmt) end
+function number.tonewciceros (n,fmt) return numbertodimen(n,"nc",fmt) end
+
+-- stop redefinition
+
+local points = function(n)
+ if not n or n == 0 then
+ return "0pt"
+ elseif type(n) == "number" then
+ return lpegmatch(stripper,format("%.5fpt",n*ptfactor)) -- faster than formatter
+ else
+ return numbertodimen(n,"pt",true,true) -- also deals with nodes
+ end
+end
+
+local basepoints = function(n)
+ if not n or n == 0 then
+ return "0bp"
+ elseif type(n) == "number" then
+ return lpegmatch(stripper,format("%.5fbp",n*bpfactor)) -- faster than formatter
+ else
+ return numbertodimen(n,"bp",true,true) -- also deals with nodes
+ end
+end
+
+local pts = function(n)
+ if not n or n == 0 then
+ return "0pt"
+ elseif type(n) == "number" then
+ return format("%.5fpt",n*ptfactor) -- faster than formatter
+ else
+ return numbertodimen(n,"pt",true) -- also deals with nodes
+ end
+end
+
+local nopts = function(n)
+ if not n or n == 0 then
+ return "0"
+ else
+ return format("%.5f",n*ptfactor) -- faster than formatter
+ end
+end
+
+number.points = points
+number.basepoints = basepoints
+number.pts = pts
+number.nopts = nopts
+
+local colors = { }
+tracers.colors = colors
+
+local unsetvalue = attributes.unsetvalue
+
+local a_color = attributes.private('color')
+local a_colormodel = attributes.private('colormodel')
+local m_color = attributes.list[a_color] or { }
+
+function colors.set(n,c,s)
+ local mc = m_color[c]
+ if not mc then
+ n[a_color] = unsetvalue
+ else
+ if not n[a_colormodel] then
+ n[a_colormodel] = s or 1
+ end
+ n[a_color] = mc
+ end
+ return n
+end
+
+function colors.setlist(n,c,s)
+ local f = n
+ while n do
+ local mc = m_color[c]
+ if not mc then
+ n[a_color] = unsetvalue
+ else
+ if not n[a_colormodel] then
+ n[a_colormodel] = s or 1
+ end
+ n[a_color] = mc
+ end
+ n = n.next
+ end
+ return f
+end
+
+function colors.reset(n)
+ n[a_color] = unsetvalue
+ return n
+end
+
+-- maybe
+
+local transparencies = { }
+tracers.transparencies = transparencies
+
+local a_transparency = attributes.private('transparency')
+local m_transparency = attributes.list[a_transparency] or { }
+
+function transparencies.set(n,t)
+ local mt = m_transparency[t]
+ if not mt then
+ n[a_transparency] = unsetvalue
+ else
+ n[a_transparency] = mt
+ end
+ return n
+end
+
+function transparencies.setlist(n,c,s)
+ local f = n
+ while n do
+ local mt = m_transparency[c]
+ if not mt then
+ n[a_transparency] = unsetvalue
+ else
+ n[a_transparency] = mt
+ end
+ n = n.next
+ end
+ return f
+end
+
+function transparencies.reset(n)
+ n[a_transparency] = unsetvalue
+ return n
+end
+
+-- for the moment here
+
+nodes.visualizers = { }
+
+function nodes.visualizers.handler(head)
+ return head, false
+end