diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/node-tra.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/node-tra.lua | 388 |
1 files changed, 264 insertions, 124 deletions
diff --git a/Master/texmf-dist/tex/context/base/node-tra.lua b/Master/texmf-dist/tex/context/base/node-tra.lua index 916b2143d03..08110727705 100644 --- a/Master/texmf-dist/tex/context/base/node-tra.lua +++ b/Master/texmf-dist/tex/context/base/node-tra.lua @@ -18,10 +18,10 @@ 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 texgetattribute = tex.getattribute + local tracers = nodes.tracers or { } nodes.tracers = tracers @@ -34,9 +34,30 @@ 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 nuts = nodes.nuts +local tonut = nuts.tonut +local tonode = nuts.tonode + +local getfield = nuts.getfield +local getnext = nuts.getnext +local getprev = nuts.getprev +local getid = nuts.getid +local getchar = nuts.getchar +local getsubtype = nuts.getsubtype +local getlist = nuts.getlist + +local setattr = nuts.setattr + +local flush_list = nuts.flush_list +local count_nodes = nuts.count +local used_nodes = nuts.usedlist + +local traverse_by_id = nuts.traverse_id +local traverse_nodes = nuts.traverse +local d_tostring = nuts.tostring + +local nutpool = nuts.pool +local new_rule = nutpool.rule local nodecodes = nodes.nodecodes local whatcodes = nodes.whatcodes @@ -51,13 +72,11 @@ 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 gluespec_code = nodecodes.gluespec local localpar_code = whatcodes.localpar local dir_code = whatcodes.dir -local nodepool = nodes.pool - local dimenfactors = number.dimenfactors local formatters = string.formatters @@ -67,15 +86,16 @@ function nodes.showlist(head, message) if message then report_nodes(message) end - for n in traverse_nodes(head) do - report_nodes(tostring(n)) + for n in traverse_nodes(tonut(head)) do + report_nodes(d_tostring(n)) end end function nodes.handlers.checkglyphs(head,message) + local h = tonut(head) local t = { } - for g in traverse_by_id(glyph_code,head) do - t[#t+1] = formatters["%U:%s"](g.char,g.subtype) + for g in traverse_by_id(glyph_code,h) do + t[#t+1] = formatters["%U:%s"](getchar(g),getsubtype(g)) end if #t > 0 then if message and message ~= "" then @@ -89,14 +109,14 @@ 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]) + local q = used_nodes() + for p in traverse_nodes(q) do + local s = table.serialize(nodes.astable(p,sparse),nodecodes[getid(p)]) l[s] = (l[s] or 0) + 1 end - node.flush_list(q) + flush_list(q) for k, v in next, l do - write_nl(formatters["%s * %s"](v,k)) + report_nodes("%s * %s",v,k) end end @@ -104,39 +124,40 @@ local f_sequence = formatters["U+%04X:%s"] local function tosequence(start,stop,compact) if start then + start = tonut(start) + stop = stop and tonut(stop) local t = { } while start do - local id = start.id + local id = getid(start) if id == glyph_code then - local c = start.char + local c = getchar(start) if compact then - if start.components then - t[#t+1] = tosequence(start.components,nil,compact) + local components = getfield(start,"components") + if components then + t[#t+1] = tosequence(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 + elseif id == whatsit_code and getsubtype(start) == localpar_code or getsubtype(start) == dir_code then + t[#t+1] = "[" .. getfield(start,"dir") .. "]" + elseif compact then + t[#t+1] = "[]" else - if compact then - t[#t+1] = "[]" - else - t[#t+1] = nodecodes[id] - end + t[#t+1] = nodecodes[id] end if start == stop then break else - start = start.next + start = getnext(start) end end if compact then @@ -152,21 +173,23 @@ end nodes.tosequence = tosequence function nodes.report(t,done) - report_nodes("output %a, %changed %a, %s nodes",status.output_active,done,count_nodes(t)) + report_nodes("output %a, %changed %a, %s nodes",status.output_active,done,count_nodes(tonut(t))) end function nodes.packlist(head) local t = { } - for n in traverse(head) do - t[#t+1] = tostring(n) + for n in traverse_nodes(tonut(head)) do + t[#t+1] = d_tostring(n) end return t end function nodes.idstostring(head,tail) + head = tonut(head) + tail = tail and tonut(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 + local id = getid(n) if not last_id then last_id, last_n = id, 1 elseif last_id == id then @@ -194,6 +217,8 @@ function nodes.idstostring(head,tail) end -- function nodes.xidstostring(head,tail) -- only for special tracing of backlinks +-- head = tonut(head) +-- tail = tonut(tail) -- local n = head -- while n.next do -- n = n.next @@ -216,7 +241,7 @@ end -- if n == head then -- break -- end --- n = n.prev +-- n = getprev(n) -- end -- if not last_id then -- t[#t+1] = "no nodes" @@ -229,48 +254,56 @@ end -- end local function showsimplelist(h,depth,n) + h = h and tonut(h) while h do - write_nl(rep(" ",n) .. tostring(h)) + report_nodes("% w%s",n,d_tostring(h)) if not depth or n < depth then - local id = h.id + local id = getid(h) if id == hlist_code or id == vlist_code then - showsimplelist(h.list,depth,n+1) + showsimplelist(getlist(h),depth,n+1) end end - h = h.next + h = getnext(h) 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 +-- \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 + local id = getid(h) if id == glyph_code then -- always true - w[#w+1] = utfchar(h.char) + local c = getchar(h) + w[#w+1] = c >= 0 and utfchar(c) or formatters["<%i>"](c) if joiner then w[#w+1] = joiner end elseif id == disc_code then - local pre, rep, pos = h.pre, h.replace, h.post + local pre = getfield(h,"pre") + local pos = getfield(h,"post") + local rep = getfield(h,"replace") 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 "" + pos and listtoutf(pos,joiner,textonly) or "", + rep and listtoutf(rep,joiner,textonly) or "" ) elseif textonly then - if id == glue_code and h.spec and h.spec.width > 0 then - w[#w+1] = " " + if id == glue_code then + local spec = getfield(h,"spec") + if spec and getfield(spec,"width") > 0 then + w[#w+1] = " " + end + elseif id == hlist_code or id == vlist_code then + w[#w+1] = "[]" end else w[#w+1] = "[-]" @@ -278,24 +311,28 @@ local function listtoutf(h,joiner,textonly,last) if h == last then break else - h = h.next + h = getnext(h) end end return concat(w) end -nodes.listtoutf = listtoutf +function nodes.listtoutf(h,joiner,textonly,last) + local joiner = joiner == true and utfchar(0x200C) or joiner -- zwnj + return listtoutf(tonut(h),joiner,textonly,last and tonut(last)) +end 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 + depth = depth or 0 + symbol = symbol or "." + for n in traverse_nodes(tonut(n)) do + local id = getid(n) if id == hlist_code or id == vlist_code then - local s = n.subtype + local s = getsubtype(n) report_nodes(rep(symbol,depth) .. what[s] or s) - showboxes(n.list,symbol,depth+1) + showboxes(getlist(n),symbol,depth+1) end end end @@ -318,15 +355,8 @@ local stripper = lpeg.patterns.stripzeros 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 +local function nodetodimen(d,unit,fmt,strip) + d = tonut(d) -- tricky: direct nuts are an issue if unit == true then unit = "pt" fmt = "%0.5f%s" @@ -338,27 +368,23 @@ local function numbertodimen(d,unit,fmt,strip) 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 + local id = getid(d) if id == kern_code then - local str = formatters[fmt](d.width*dimenfactors[unit],unit) + local str = formatters[fmt](getfield(d,"width")*dimenfactors[unit],unit) return strip and lpegmatch(stripper,str) or str end if id == glue_code then - d = d.spec + d = getfield(d,"spec") end - if not d or not d.id == spec_code then + if not d or not getid(d) == gluespec_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 + local width = getfield(d,"width") + local plus = getfield(d,"stretch_order") + local minus = getfield(d,"shrink_order") + local stretch = getfield(d,"stretch") + local shrink = getfield(d,"shrink") if plus ~= 0 then plus = " plus " .. stretch/65536 .. fillcodes[plus] elseif stretch ~= 0 then @@ -375,11 +401,39 @@ local function numbertodimen(d,unit,fmt,strip) else minus = "" end - local str = formatters[fmt](d.width*dimenfactors[unit],unit) + local str = formatters[fmt](getfield(d,"width")*dimenfactors[unit],unit) return (strip and lpegmatch(stripper,str) or str) .. plus .. minus end +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 + elseif t == "number" then + 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 + local str = formatters[fmt](d*dimenfactors[unit],unit) + return strip and lpegmatch(stripper,str) or str + else + return nodetodimen(d,unit,fmt,strip) -- real node + end +end + number.todimen = numbertodimen +nodes .todimen = nodetodimen function number.topoints (n,fmt) return numbertodimen(n,"pt",fmt) end function number.toinches (n,fmt) return numbertodimen(n,"in",fmt) end @@ -394,6 +448,19 @@ 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 +function nodes.topoints (n,fmt) return nodetodimen(n,"pt",fmt) end +function nodes.toinches (n,fmt) return nodetodimen(n,"in",fmt) end +function nodes.tocentimeters (n,fmt) return nodetodimen(n,"cm",fmt) end +function nodes.tomillimeters (n,fmt) return nodetodimen(n,"mm",fmt) end +function nodes.toscaledpoints(n,fmt) return nodetodimen(n,"sp",fmt) end +function nodes.toscaledpoints(n) return n .. "sp" end +function nodes.tobasepoints (n,fmt) return nodetodimen(n,"bp",fmt) end +function nodes.topicas (n,fmt) return nodetodimen(n "pc",fmt) end +function nodes.todidots (n,fmt) return nodetodimen(n,"dd",fmt) end +function nodes.tociceros (n,fmt) return nodetodimen(n,"cc",fmt) end +function nodes.tonewdidots (n,fmt) return nodetodimen(n,"nd",fmt) end +function nodes.tonewciceros (n,fmt) return nodetodimen(n,"nc",fmt) end + -- stop redefinition local points = function(n) @@ -439,8 +506,13 @@ number.basepoints = basepoints number.pts = pts number.nopts = nopts -local colors = { } -tracers.colors = colors +nodes.points = function(n) return numbertodimen(n,"pt",true,true) end +nodes.basepoints = function(n) return numbertodimen(n,"bp",true,true) end +nodes.pts = function(n) return numbertodimen(n,"pt",true) end +nodes.nopts = function(n) return format("%.5f",n*ptfactor) end + +local colors = { } +tracers.colors = colors local unsetvalue = attributes.unsetvalue @@ -450,36 +522,34 @@ 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 + local nn = tonut(n) + if mc then + local mm = s or texgetattribute(a_colormodel) + setattr(nn,a_colormodel,mm <= 0 and mm or 1) + setattr(nn,a_color,mc) else - if not n[a_colormodel] then - n[a_colormodel] = s or 1 - end - n[a_color] = mc + setattr(nn,a_color,unsetvalue) 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 + local nn = tonut(n) + local mc = m_color[c] or unsetvalue + local mm = s or texgetattribute(a_colormodel) + if mm <= 0 then + mm = 1 + end + while nn do + setattr(nn,a_colormodel,mm) + setattr(nn,a_color,mc) + nn = getnext(nn) end - return f + return n end function colors.reset(n) - n[a_color] = unsetvalue + setattr(tonut(n),a_color,unsetvalue) return n end @@ -492,38 +562,108 @@ 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 + setattr(tonut(n),a_transparency,m_transparency[t] or unsetvalue) 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 + local nn = tonut(n) + local mt = m_transparency[c] or unsetvalue + while nn do + setattr(nn,a_transparency,mt) + nn = getnext(nn) end - return f + return n end function transparencies.reset(n) - n[a_transparency] = unsetvalue + setattr(n,a_transparency,unsetvalue) return n end -- for the moment here -nodes.visualizers = { } +local visualizers = nodes.visualizers or { } +nodes.visualizers = visualizers -function nodes.visualizers.handler(head) +function visualizers.handler(head) return head, false end + +-- we could cache attribute lists and set attr (copy will increment count) .. todo .. +-- although tracers are used seldom + +local function setproperties(n,c,s) + local nn = tonut(n) + local mm = texgetattribute(a_colormodel) + setattr(nn,a_colormodel,mm > 0 and mm or 1) + setattr(nn,a_color,m_color[c]) + setattr(nn,a_transparency,m_transparency[c]) + return n +end + +tracers.setproperties = setproperties + +function tracers.setlist(n,c,s) + local nn = tonut(n) + local mc = m_color[c] + local mt = m_transparency[c] + local mm = texgetattribute(a_colormodel) + if mm <= 0 then + mm = 1 + end + while nn do + setattr(nn,a_colormodel,mm) + setattr(nn,a_color,mc) + setattr(nn,a_transparency,mt) + nn = getnext(nn) + end + return n +end + +function tracers.resetproperties(n) + local nn = tonut(n) + setattr(nn,a_color,unsetvalue) + setattr(nn,a_transparency,unsetvalue) + return n +end + +-- this one returns a nut + +local nodestracerpool = { } +local nutstracerpool = { } + +tracers.pool = { + nodes = nodestracerpool, + nuts = nutstracerpool, +} + +table.setmetatableindex(nodestracerpool,function(t,k,v) + local f = nutstracerpool[k] + local v = function(...) + return tonode(f(...)) + end + t[k] = v + return v +end) + +function nutstracerpool.rule(w,h,d,c,s) -- so some day we can consider using literals (speedup) + return setproperties(new_rule(w,h,d),c,s) +end + +tracers.rule = nodestracerpool.rule -- for a while + +-- local function show(head,n,message) +-- print("START",message or "") +-- local i = 0 +-- for current in traverse(head) do +-- local prev = getprev(current) +-- local next = getnext(current) +-- i = i + 1 +-- print(i, prev and nodecodes[getid(prev)],nodecodes[getid(current)],next and nodecodes[getid(next)]) +-- if i == n then +-- break +-- end +-- end +-- print("STOP", message or "") +-- end |