diff options
author | Hans Hagen <pragma@wxs.nl> | 2013-05-19 19:27:00 +0200 |
---|---|---|
committer | Hans Hagen <pragma@wxs.nl> | 2013-05-19 19:27:00 +0200 |
commit | 9a10021cd4cb23995ad3ffa915fc5b7f6890aaf8 (patch) | |
tree | 983e02c29872e4713a10a9dc8ae7708c6da3de88 /tex/context/base/node-tra.lua | |
parent | 0deffde58a47f5c85a46a7d999ff9cf817b81cef (diff) | |
download | context-9a10021cd4cb23995ad3ffa915fc5b7f6890aaf8.tar.gz |
beta 2013.05.19 19:27
Diffstat (limited to 'tex/context/base/node-tra.lua')
-rw-r--r-- | tex/context/base/node-tra.lua | 1058 |
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
|