diff options
Diffstat (limited to 'tex/context/base/trac-vis.lua')
-rw-r--r-- | tex/context/base/trac-vis.lua | 294 |
1 files changed, 164 insertions, 130 deletions
diff --git a/tex/context/base/trac-vis.lua b/tex/context/base/trac-vis.lua index dc8bcc5e7..420e9a00d 100644 --- a/tex/context/base/trac-vis.lua +++ b/tex/context/base/trac-vis.lua @@ -34,6 +34,7 @@ local formatters = string.formatters -- todo: inline concat (more efficient) local nodecodes = nodes.nodecodes +local disc_code = nodecodes.disc local kern_code = nodecodes.kern local glyph_code = nodecodes.glyph local hlist_code = nodecodes.hlist @@ -58,21 +59,41 @@ local rightskip_code = gluecodes.rightskip local whatsitcodes = nodes.whatsitcodes -local hpack_nodes = node.hpack -local vpack_nodes = node.vpack -local fast_hpack_string = nodes.typesetters.fast_hpack -local copy_node = node.copy -local copy_list = node.copy_list -local free_node = node.free -local free_node_list = node.flush_list -local insert_node_before = node.insert_before -local insert_node_after = node.insert_after -local fast_hpack = nodes.fasthpack -local traverse_nodes = node.traverse +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 setfield = nuts.setfield +local getattr = nuts.getattr +local setattr = nuts.setattr +local getfont = nuts.getfont +local getsubtype = nuts.getsubtype +local getchar = nuts.getchar +local getbox = nuts.getbox +local getlist = nuts.getlist +local getleader = nuts.getleader + +local hpack_nodes = nuts.hpack +local vpack_nodes = nuts.vpack +local copy_node = nuts.copy +local copy_list = nuts.copy_list +local free_node = nuts.free +local free_node_list = nuts.flush_list +local insert_node_before = nuts.insert_before +local insert_node_after = nuts.insert_after +local traverse_nodes = nuts.traverse +local linked_nodes = nuts.linked + +local fast_hpack = nuts.fasthpack +local fast_hpack_string = nuts.typesetters.fast_hpack local texgetattribute = tex.getattribute local texsetattribute = tex.setattribute -local texgetbox = tex.getbox + local unsetvalue = attributes.unsetvalue local current_font = font.current @@ -81,7 +102,7 @@ local exheights = fonts.hashes.exheights local emwidths = fonts.hashes.emwidths local pt_factor = number.dimenfactors.pt -local nodepool = nodes.pool +local nodepool = nuts.pool local new_rule = nodepool.rule local new_kern = nodepool.kern local new_glue = nodepool.glue @@ -293,39 +314,39 @@ local c_white_d = "trace:dw" local function sometext(str,layer,color,textcolor) -- we can just paste verbatim together .. no typesteting needed local text = fast_hpack_string(str,usedfont) - local size = text.width + local size = getfield(text,"width") local rule = new_rule(size,2*exheight,exheight/2) local kern = new_kern(-size) if color then setcolor(rule,color) end if textcolor then - setlistcolor(text.list,textcolor) + setlistcolor(getlist(text),textcolor) end - local info = rule .. kern .. text + local info = linked_nodes(rule,kern,text) setlisttransparency(info,c_zero) info = fast_hpack(info) if layer then - info[a_layer] = layer + setattr(info,a_layer,layer) end - local width = info.width - info.width = 0 - info.height = 0 - info.depth = 0 + local width = getfield(info,"width") + setfield(info,"width",0) + setfield(info,"height",0) + setfield(info,"depth",0) return info, width end local f_cache = { } local function fontkern(head,current) - local kern = current.kern + local kern = getfield(current,"kern") local info = f_cache[kern] if info then -- print("hit fontkern") else local text = fast_hpack_string(formatters[" %0.3f"](kern*pt_factor),usedfont) local rule = new_rule(emwidth/10,6*exheight,2*exheight) - local list = text.list + local list = getlist(text) if kern > 0 then setlistcolor(list,c_positive_d) elseif kern < 0 then @@ -335,13 +356,12 @@ local function fontkern(head,current) end setlisttransparency(list,c_text_d) settransparency(rule,c_text_d) - text.shift = -5 * exheight - info = rule .. text - info = fast_hpack(info) - info[a_layer] = l_fontkern - info.width = 0 - info.height = 0 - info.depth = 0 + setfield(text,"shift",-5 * exheight) + info = fast_hpack(linked_nodes(rule,text)) + setattr(info,a_layer,l_fontkern) + setfield(info,"width",0) + setfield(info,"height",0) + setfield(info,"depth",0) f_cache[kern] = info end head = insert_node_before(head,current,copy_list(info)) @@ -382,7 +402,7 @@ local tags = { } local function whatsit(head,current) - local what = current.subtype + local what = getsubtype(current) local info = w_cache[what] if info then -- print("hit whatsit") @@ -390,7 +410,7 @@ local function whatsit(head,current) local tag = whatsitcodes[what] -- maybe different text colors per tag info = sometext(formatters["W:%s"](tag and tags[tag] or what),usedfont,nil,c_white) - info[a_layer] = l_whatsit + setattr(info,a_layer,l_whatsit) w_cache[what] = info end head, current = insert_node_after(head,current,copy_list(info)) @@ -398,13 +418,13 @@ local function whatsit(head,current) end local function user(head,current) - local what = current.subtype + local what = getsubtype(current) local info = w_cache[what] if info then -- print("hit user") else info = sometext(formatters["U:%s"](what),usedfont) - info[a_layer] = l_user + setattr(info,a_layer,l_user) w_cache[what] = info end head, current = insert_node_after(head,current,copy_list(info)) @@ -414,14 +434,14 @@ end local b_cache = { } local function ruledbox(head,current,vertical,layer,what,simple,previous) - local wd = current.width + local wd = getfield(current,"width") if wd ~= 0 then - local ht = current.height - local dp = current.depth - local next = current.next - local prev = previous -- current.prev ... prev can be wrong in math mode - current.next = nil - current.prev = nil + local ht = getfield(current,"height") + local dp = getfield(current,"depth") + local next = getnext(current) + local prev = previous -- getprev(current) ... prev can be wrong in math mode + setfield(current,"next",nil) + setfield(current,"prev",nil) local linewidth = emwidth/10 local baseline, baseskip if dp ~= 0 and ht ~= 0 then @@ -430,16 +450,16 @@ local function ruledbox(head,current,vertical,layer,what,simple,previous) if not baseline then -- due to an optimized leader color/transparency we need to set the glue node in order -- to trigger this mechanism - local leader = new_glue(2*linewidth) .. new_rule(6*linewidth,linewidth,0) .. new_glue(2*linewidth) + local leader = linked_nodes(new_glue(2*linewidth),new_rule(6*linewidth,linewidth,0),new_glue(2*linewidth)) -- setlisttransparency(leader,c_text) leader = fast_hpack(leader) -- setlisttransparency(leader,c_text) baseline = new_glue(0) - baseline.leader = leader - baseline.subtype = cleaders_code - local spec = baseline.spec - spec.stretch = 65536 - spec.stretch_order = 2 + setfield(baseline,"leader",leader) + setfield(baseline,"subtype",cleaders_code) + local spec = getfield(baseline,"spec") + setfield(spec,"stretch",65536) + setfield(spec,"stretch_order",2) setlisttransparency(baseline,c_text) b_cache.baseline = baseline end @@ -461,47 +481,49 @@ local function ruledbox(head,current,vertical,layer,what,simple,previous) this = b_cache[what] if not this then local text = fast_hpack_string(what,usedfont) - this = new_kern(-text.width) .. text + this = linked_nodes(new_kern(-getfield(text,"width")),text) setlisttransparency(this,c_text) this = fast_hpack(this) - this.width = 0 - this.height = 0 - this.depth = 0 + setfield(this,"width",0) + setfield(this,"height",0) + setfield(this,"depth",0) b_cache[what] = this end end -- we need to trigger the right mode (else sometimes no whatits) - local info = - (this and copy_list(this) or nil) .. - new_rule(linewidth,ht,dp) .. - new_rule(wd-2*linewidth,-dp+linewidth,dp) .. - new_rule(linewidth,ht,dp) .. - new_kern(-wd+linewidth) .. + local info = linked_nodes( + this and copy_list(this) or nil, + new_rule(linewidth,ht,dp), + new_rule(wd-2*linewidth,-dp+linewidth,dp), + new_rule(linewidth,ht,dp), + new_kern(-wd+linewidth), new_rule(wd-2*linewidth,ht,-ht+linewidth) + ) if baseskip then - info = info .. baseskip .. baseline + info = linked_nodes(info,baseskip,baseline) end setlisttransparency(info,c_text) info = fast_hpack(info) - info.width = 0 - info.height = 0 - info.depth = 0 - info[a_layer] = layer - local info = current .. new_kern(-wd) .. info + setfield(info,"width",0) + setfield(info,"height",0) + setfield(info,"depth",0) + setattr(info,a_layer,layer) + local info = linked_nodes(current,new_kern(-wd),info) info = fast_hpack(info,wd) if vertical then info = vpack_nodes(info) end if next then - info.next = next - next.prev = info + setfield(info,"next",next) + setfield(next,"prev",info) end if prev then - if prev.id == gluespec_code then - -- weird, how can this happen, an inline glue-spec + if getid(prev) == gluespec_code then + report_visualize("ignoring invalid prev") + -- weird, how can this happen, an inline glue-spec, probably math else - info.prev = prev - prev.next = info + setfield(info,"prev",prev) + setfield(prev,"next",info) end end if head == current then @@ -515,14 +537,14 @@ local function ruledbox(head,current,vertical,layer,what,simple,previous) end local function ruledglyph(head,current,previous) - local wd = current.width + local wd = getfield(current,"width") if wd ~= 0 then - local ht = current.height - local dp = current.depth - local next = current.next + local ht = getfield(current,"height") + local dp = getfield(current,"depth") + local next = getnext(current) local prev = previous - current.next = nil - current.prev = nil + setfield(current,"next",nil) + setfield(current,"prev",nil) local linewidth = emwidth/20 local baseline if dp ~= 0 and ht ~= 0 then @@ -530,31 +552,32 @@ local function ruledglyph(head,current,previous) end local doublelinewidth = 2*linewidth -- could be a pdf rule - local info = - new_rule(linewidth,ht,dp) .. - new_rule(wd-doublelinewidth,-dp+linewidth,dp) .. - new_rule(linewidth,ht,dp) .. - new_kern(-wd+linewidth) .. - new_rule(wd-doublelinewidth,ht,-ht+linewidth) .. - new_kern(-wd+doublelinewidth) .. + local info = linked_nodes( + new_rule(linewidth,ht,dp), + new_rule(wd-doublelinewidth,-dp+linewidth,dp), + new_rule(linewidth,ht,dp), + new_kern(-wd+linewidth), + new_rule(wd-doublelinewidth,ht,-ht+linewidth), + new_kern(-wd+doublelinewidth), baseline + ) setlistcolor(info,c_glyph) setlisttransparency(info,c_glyph_d) info = fast_hpack(info) - info.width = 0 - info.height = 0 - info.depth = 0 - info[a_layer] = l_glyph - local info = current .. new_kern(-wd) .. info + setfield(info,"width",0) + setfield(info,"height",0) + setfield(info,"depth",0) + setattr(info,a_layer,l_glyph) + local info = linked_nodes(current,new_kern(-wd),info) info = fast_hpack(info) - info.width = wd + setfield(info,"width",wd) if next then - info.next = next - next.prev = info + setfield(info,"next",next) + setfield(next,"prev",info) end if prev then - info.prev = prev - prev.next = info + setfield(info,"prev",prev) + setfield(prev,"next",info) end if head == current then return info, info @@ -599,9 +622,9 @@ local tags = { -- we sometimes pass previous as we can have issues in math (not watertight for all) local function ruledglue(head,current,vertical) - local spec = current.spec - local width = spec.width - local subtype = current.subtype + local spec = getfield(current,"spec") + local width = getfield(spec,"width") + local subtype = getsubtype(current) local amount = formatters["%s:%0.3f"](tags[subtype] or (vertical and "VS") or "HS",width*pt_factor) local info = g_cache[amount] if info then @@ -629,13 +652,13 @@ local function ruledglue(head,current,vertical) info = vpack_nodes(info) end head, current = insert_node_before(head,current,info) - return head, current.next + return head, getnext(current) end local k_cache = { } local function ruledkern(head,current,vertical) - local kern = current.kern + local kern = getfield(current,"kern") local info = k_cache[kern] if info then -- print("kern hit") @@ -655,13 +678,13 @@ local function ruledkern(head,current,vertical) info = vpack_nodes(info) end head, current = insert_node_before(head,current,info) - return head, current.next + return head, getnext(current) end local p_cache = { } local function ruledpenalty(head,current,vertical) - local penalty = current.penalty + local penalty = getfield(current,"penalty") local info = p_cache[penalty] if info then -- print("penalty hit") @@ -681,7 +704,7 @@ local function ruledpenalty(head,current,vertical) info = vpack_nodes(info) end head, current = insert_node_before(head,current,info) - return head, current.next + return head, getnext(current) end local function visualize(head,vertical) @@ -702,8 +725,8 @@ local function visualize(head,vertical) local attr = unsetvalue local prev_trace_fontkern = nil while current do - local id = current.id - local a = current[a_visual] or unsetvalue + local id = getid(current) + local a = getattr(current,a_visual) or unsetvalue if a ~= attr then prev_trace_fontkern = trace_fontkern if a == unsetvalue then @@ -736,30 +759,30 @@ local function visualize(head,vertical) attr = a end if trace_strut then - current[a_layer] = l_strut + setattr(current,a_layer,l_strut) elseif id == glyph_code then if trace_glyph then head, current = ruledglyph(head,current,previous) end elseif id == disc_code then if trace_glyph then - local pre = current.pre + local pre = getfield(current,"pre") if pre then - current.pre = ruledglyph(pre,pre) + setfield(current,"pre",ruledglyph(pre,pre)) end - local post = current.post + local post = getfield(current,"post") if post then - current.post = ruledglyph(post,post) + setfield(current,"post",ruledglyph(post,post)) end - local replace = current.replace + local replace = getfield(current,"replace") if replace then - current.replace = ruledglyph(replace,replace) + setfield(current,"replace",ruledglyph(replace,replace)) end end elseif id == kern_code then - local subtype = current.subtype + local subtype = getsubtype(current) -- tricky ... we don't copy the trace attribute in node-inj (yet) - if subtype == font_kern_code or current[a_fontkern] then + if subtype == font_kern_code or getattr(current,a_fontkern) then if trace_fontkern or prev_trace_fontkern then head, current = fontkern(head,current) end @@ -769,9 +792,9 @@ local function visualize(head,vertical) end end elseif id == glue_code then - local content = current.leader + local content = getleader(current) if content then - current.leader = visualize(content,false) + setfield(current,"leader",visualize(content,false)) elseif trace_glue then head, current = ruledglue(head,current,vertical) end @@ -780,21 +803,21 @@ local function visualize(head,vertical) head, current = ruledpenalty(head,current,vertical) end elseif id == disc_code then - current.pre = visualize(current.pre) - current.post = visualize(current.post) - current.replace = visualize(current.replace) + setfield(current,"pre",visualize(getfield(current,"pre"))) + setfield(current,"post",isualize(getfield(current,"post"))) + setfield(current,"replace",visualize(getfield(current,"replace"))) elseif id == hlist_code then - local content = current.list + local content = getlist(current) if content then - current.list = visualize(content,false) + setfield(current,"list",visualize(content,false)) end if trace_hbox then head, current = ruledbox(head,current,false,l_hbox,"H__",trace_simple,previous) end elseif id == vlist_code then - local content = current.list + local content = getlist(current) if content then - current.list = visualize(content,true) + setfield(current,"list",visualize(content,true)) end if trace_vtop then head, current = ruledbox(head,current,true,l_vtop,"_T_",trace_simple,previous) @@ -811,7 +834,7 @@ local function visualize(head,vertical) end end previous = current - current = current.next + current = getnext(current) end return head end @@ -840,25 +863,36 @@ local function cleanup() -- report_visualize("cache: %s fontkerns, %s skips, %s penalties, %s kerns, %s whatsits, %s boxes",nf,ng,np,nk,nw,nb) end -function visualizers.handler(head) +local function handler(head) if usedfont then starttiming(visualizers) -- local l = texgetattribute(a_layer) -- local v = texgetattribute(a_visual) -- texsetattribute(a_layer,unsetvalue) -- texsetattribute(a_visual,unsetvalue) - head = visualize(head) + head = visualize(tonut(head)) -- texsetattribute(a_layer,l) -- texsetattribute(a_visual,v) -- -- cleanup() stoptiming(visualizers) + return tonode(head), true + else + return head, false end - return head, false end +visualizers.handler = handler + function visualizers.box(n) - local box = texgetbox(n) - box.list = visualizers.handler(box.list) + if usedfont then + starttiming(visualizers) + local box = getbox(n) + setfield(box,"list",visualize(getlist(box))) + stoptiming(visualizers) + return head, true + else + return head, false + end end local last = nil @@ -872,9 +906,9 @@ local mark = { local function markfonts(list) for n in traverse_nodes(list) do - local id = n.id + local id = getid(n) if id == glyph_code then - local font = n.font + local font = getfont(n) local okay = used[font] if not okay then last = last + 1 @@ -883,14 +917,14 @@ local function markfonts(list) end setcolor(n,okay) elseif id == hlist_code or id == vlist_code then - markfonts(n.list) + markfonts(getlist(n)) end end end function visualizers.markfonts(list) last, used = 0, { } - markfonts(type(n) == "number" and texgetbox(n).list or n) + markfonts(type(n) == "number" and getlist(getbox(n)) or n) end function commands.markfonts(n) |