summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/trac-vis.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkiv/trac-vis.lua')
-rw-r--r--tex/context/base/mkiv/trac-vis.lua1204
1 files changed, 650 insertions, 554 deletions
diff --git a/tex/context/base/mkiv/trac-vis.lua b/tex/context/base/mkiv/trac-vis.lua
index 061cef8ba..5d98bc24f 100644
--- a/tex/context/base/mkiv/trac-vis.lua
+++ b/tex/context/base/mkiv/trac-vis.lua
@@ -9,7 +9,7 @@ if not modules then modules = { } end modules ['trac-vis'] = {
local string, number, table = string, number, table
local node, nodes, attributes, fonts, tex = node, nodes, attributes, fonts, tex
local type = type
-local format = string.format
+local gmatch = string.gmatch
local formatters = string.formatters
-- This module started out in the early days of mkiv and luatex with
@@ -76,6 +76,8 @@ local setlist = nuts.setlist
local setleader = nuts.setleader
local setsubtype = nuts.setsubtype
local setattr = nuts.setattr
+local setwidth = nuts.setwidth
+local setshift = nuts.setshift
local getfield = nuts.getfield
local getid = nuts.getid
@@ -90,18 +92,22 @@ local getnext = nuts.getnext
local getprev = nuts.getprev
local getboth = nuts.getboth
local getdisc = nuts.getdisc
+local getwhd = nuts.getwhd
+local getkern = nuts.getkern
+local getpenalty = nuts.getpenalty
+local getdir = nuts.getdir
+local getwidth = nuts.getwidth
+local getshift = nuts.getshift
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 flush_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 apply_to_nodes = nuts.apply
+local find_tail = nuts.tail
local effectiveglue = nuts.effective_glue
local hpack_string = nuts.typesetters.tohpack
@@ -123,7 +129,6 @@ local nodepool = nuts.pool
local new_rule = nodepool.rule
local new_kern = nodepool.kern
local new_glue = nodepool.glue
-local new_penalty = nodepool.penalty
local new_hlist = nodepool.hlist
local new_vlist = nodepool.vlist
@@ -147,6 +152,8 @@ local bit = number.bit
local setbit = number.setbit
local clearbit = number.clearbit
+local enableaction = nodes.tasks.enableaction
+
local trace_hbox
local trace_vbox
local trace_vtop
@@ -159,32 +166,35 @@ local trace_whatsit
local trace_user
local trace_math
local trace_italic
+local trace_discretionary
local report_visualize = logs.reporter("visualize")
local modes = {
- hbox = 1,
- vbox = 2,
- vtop = 4,
- kern = 8,
- glue = 16,
- penalty = 32,
- fontkern = 64,
- strut = 128,
- whatsit = 256,
- glyph = 512,
- simple = 1024,
- simplehbox = 1024 + 1,
- simplevbox = 1024 + 2,
- simplevtop = 1024 + 4,
- user = 2048,
- math = 4096,
- italic = 8192,
- origin = 16384,
+ hbox = 1,
+ vbox = 2,
+ vtop = 4,
+ kern = 8,
+ glue = 16,
+ -- skip = 16,
+ penalty = 32,
+ fontkern = 64,
+ strut = 128,
+ whatsit = 256,
+ glyph = 512,
+ simple = 1024,
+ simplehbox = 1024 + 1,
+ simplevbox = 1024 + 2,
+ simplevtop = 1024 + 4,
+ user = 2048,
+ math = 4096,
+ italic = 8192,
+ origin = 16384,
+ discretionary = 32768,
}
local usedfont, exheight, emwidth
-local l_penalty, l_glue, l_kern, l_fontkern, l_hbox, l_vbox, l_vtop, l_strut, l_whatsit, l_glyph, l_user, l_math, l_italic, l_origin
+local l_penalty, l_glue, l_kern, l_fontkern, l_hbox, l_vbox, l_vtop, l_strut, l_whatsit, l_glyph, l_user, l_math, l_italic, l_origin, l_discretionary
local enabled = false
local layers = { }
@@ -219,30 +229,31 @@ local function enable()
}
layers[mode] = attributes.viewerlayers.register(tag,true)
end
- l_hbox = layers.hbox
- l_vbox = layers.vbox
- l_vtop = layers.vtop
- l_glue = layers.glue
- l_kern = layers.kern
- l_penalty = layers.penalty
- l_fontkern = layers.fontkern
- l_strut = layers.strut
- l_whatsit = layers.whatsit
- l_glyph = layers.glyph
- l_user = layers.user
- l_math = layers.math
- l_italic = layers.italic
- l_origin = layers.origin
- nodes.tasks.enableaction("shipouts","nodes.visualizers.handler")
+ l_hbox = layers.hbox
+ l_vbox = layers.vbox
+ l_vtop = layers.vtop
+ l_glue = layers.glue
+ l_kern = layers.kern
+ l_penalty = layers.penalty
+ l_fontkern = layers.fontkern
+ l_strut = layers.strut
+ l_whatsit = layers.whatsit
+ l_glyph = layers.glyph
+ l_user = layers.user
+ l_math = layers.math
+ l_italic = layers.italic
+ l_origin = layers.origin
+ l_discretionary = layers.discretionary
+ enableaction("shipouts","nodes.visualizers.handler")
report_visualize("enabled")
enabled = true
tex.setcount("global","c_syst_visualizers_state",1) -- so that we can optimize at the tex end
end
-local function setvisual(n,a,what) -- this will become more efficient when we have the bit lib linked in
+local function setvisual(n,a,what,list) -- this will become more efficient when we have the bit lib linked in
if not n or n == "reset" then
return unsetvalue
- elseif n == "makeup" then
+ elseif n == true or n == "makeup" then
if not a or a == 0 or a == unsetvalue then
a = preset_makeup
else
@@ -263,22 +274,15 @@ local function setvisual(n,a,what) -- this will become more efficient when we ha
a = setbit(a,preset_all)
end
else
- local m = modes[n]
- if not m then
- -- go on
- elseif a == unsetvalue then
- if what == false then
- return unsetvalue
- else
- -- a = setbit(0,m)
+ for s in gmatch(n,"[a-z]+") do
+ local m = modes[s]
+ if not m then
+ -- go on
+ elseif not a or a == 0 or a == unsetvalue then
a = m
+ else
+ a = setbit(a,m)
end
- elseif what == false then
- a = clearbit(a,m)
- elseif not a or a == 0 then
- a = m
- else
- a = setbit(a,m)
end
end
if not a or a == 0 or a == unsetvalue then
@@ -293,6 +297,20 @@ function nuts.setvisual(n,mode)
setattr(n,a_visual,setvisual(mode,getattr(n,a_visual),true))
end
+function nuts.setvisuals(n,mode)
+ setattr(n,a_visual,setvisual(mode,getattr(n,a_visual),true,true))
+end
+
+function nuts.applyvisuals(n,mode)
+ local a = unsetvalue
+ if mode == true then
+ a = texgetattribute (a_visual)
+ elseif mode then
+ a = setvisual(mode)
+ end
+ apply_to_nodes(n,function(n) setattr(n,a_visual,a) end)
+end
+
function nuts.copyvisual(n,m)
setattr(n,a_visual,getattr(m,a_visual))
end
@@ -325,35 +343,37 @@ trackers .register("visualizers.makeup", function(v) set("makeup",v) end)
trackers .register("visualizers.boxes", function(v) set("boxes", v) end)
directives.register("visualizers.fraction", function(v) fraction = (v and tonumber(v)) or (v == "more" and 5) or 10 end)
-local c_positive = "trace:b"
-local c_negative = "trace:r"
-local c_zero = "trace:g"
-local c_text = "trace:s"
-local c_space = "trace:y"
-local c_skip_a = "trace:c"
-local c_skip_b = "trace:m"
-local c_glyph = "trace:o"
-local c_ligature = "trace:s"
-local c_white = "trace:w"
-local c_math = "trace:r"
-local c_origin = "trace:o"
-
-local c_positive_d = "trace:db"
-local c_negative_d = "trace:dr"
-local c_zero_d = "trace:dg"
-local c_text_d = "trace:ds"
-local c_space_d = "trace:dy"
-local c_skip_a_d = "trace:dc"
-local c_skip_b_d = "trace:dm"
-local c_glyph_d = "trace:do"
-local c_ligature_d = "trace:ds"
-local c_white_d = "trace:dw"
-local c_math_d = "trace:dr"
-local c_origin_d = "trace:do"
+local c_positive = "trace:b"
+local c_negative = "trace:r"
+local c_zero = "trace:g"
+local c_text = "trace:s"
+local c_space = "trace:y"
+local c_skip_a = "trace:c"
+local c_skip_b = "trace:m"
+local c_glyph = "trace:o"
+local c_ligature = "trace:s"
+local c_white = "trace:w"
+local c_math = "trace:r"
+local c_origin = "trace:o"
+local c_discretionary = "trace:o"
+
+local c_positive_d = "trace:db"
+local c_negative_d = "trace:dr"
+local c_zero_d = "trace:dg"
+local c_text_d = "trace:ds"
+local c_space_d = "trace:dy"
+local c_skip_a_d = "trace:dc"
+local c_skip_b_d = "trace:dm"
+local c_glyph_d = "trace:do"
+local c_ligature_d = "trace:ds"
+local c_white_d = "trace:dw"
+local c_math_d = "trace:dr"
+local c_origin_d = "trace:do"
+local c_discretionary_d = "trace:do"
local function sometext(str,layer,color,textcolor,lap) -- we can just paste verbatim together .. no typesteting needed
local text = hpack_string(str,usedfont)
- local size = getfield(text,"width")
+ local size = getwidth(text)
local rule = new_rule(size,2*exheight,exheight/2)
local kern = new_kern(-size)
if color then
@@ -362,12 +382,14 @@ local function sometext(str,layer,color,textcolor,lap) -- we can just paste verb
if textcolor then
setlistcolor(getlist(text),textcolor)
end
- local info = linked_nodes(rule,kern,text)
+ local info = setlink(rule,kern,text)
setlisttransparency(info,c_zero)
- info = new_hlist(info)
- local width = getfield(info,"width")
+ info = hpack_nodes(info)
+ local width = getwidth(info)
if lap then
- info = new_hlist(linked_nodes(new_kern(-width),info))
+ info = new_hlist(setlink(new_kern(-width),info))
+ else
+ info = new_hlist(info)
end
if layer then
setattr(info,a_layer,layer)
@@ -375,472 +397,537 @@ local function sometext(str,layer,color,textcolor,lap) -- we can just paste verb
return info, width
end
-local f_cache = { }
+local caches = table.setmetatableindex("table")
-local function fontkern(head,current)
- local kern = getfield(current,"kern") + getfield(current,"expansion_factor")
- local info = f_cache[kern]
- if info then
- -- print("hit fontkern")
- else
- local text = hpack_string(formatters[" %0.3f"](kern*pt_factor),usedfont)
- local rule = new_rule(emwidth/fraction,6*exheight,2*exheight)
- local list = getlist(text)
- if kern > 0 then
- setlistcolor(list,c_positive_d)
- elseif kern < 0 then
- setlistcolor(list,c_negative_d)
+local fontkern do
+
+ local f_cache = caches["fontkern"]
+
+ fontkern = function(head,current)
+ local width = getkern(current)
+ local extra = getfield(current,"expansion_factor")
+ local kern = width + extra
+ local info = f_cache[kern]
+ -- report_visualize("fontkern: %p ex %p",width,extra)
+ if info then
+ -- print("hit fontkern")
else
- setlistcolor(list,c_zero_d)
+ local text = hpack_string(formatters[" %0.3f"](kern*pt_factor),usedfont)
+ local rule = new_rule(emwidth/fraction,6*exheight,2*exheight)
+ local list = getlist(text)
+ if kern > 0 then
+ setlistcolor(list,c_positive_d)
+ elseif kern < 0 then
+ setlistcolor(list,c_negative_d)
+ else
+ setlistcolor(list,c_zero_d)
+ end
+ setlisttransparency(list,c_text_d)
+ setcolor(rule,c_text_d)
+ settransparency(rule,c_text_d)
+ setshift(text,-5 * exheight)
+ info = new_hlist(setlink(rule,text))
+ setattr(info,a_layer,l_fontkern)
+ f_cache[kern] = info
end
- setlisttransparency(list,c_text_d)
- settransparency(rule,c_text_d)
- setfield(text,"shift",-5 * exheight)
- info = new_hlist(linked_nodes(rule,text))
- setattr(info,a_layer,l_fontkern)
- f_cache[kern] = info
+ head = insert_node_before(head,current,copy_list(info))
+ return head, current
end
- head = insert_node_before(head,current,copy_list(info))
- return head, current
-end
-local w_cache = { }
-local tags = {
- open = "FIC",
- write = "FIW",
- close = "FIC",
- special = "SPE",
- latelua = "LUA",
- savepos = "POS",
- userdefined = "USR",
- -- backend stuff
- pdfliteral = "PDF",
- pdfrefobj = "PDF",
- pdfannot = "PDF",
- pdfstartlink = "PDF",
- pdfendlink = "PDF",
- pdfdest = "PDF",
- pdfthread = "PDF",
- pdfstartthread = "PDF",
- pdfendthread = "PDF",
- pdfthreaddata = "PDF",
- pdflinkdata = "PDF",
- pdfcolorstack = "PDF",
- pdfsetmatrix = "PDF",
- pdfsave = "PDF",
- pdfrestore = "PDF",
-}
-
-local function whatsit(head,current)
- local what = getsubtype(current)
- local info = w_cache[what]
- if info then
- -- print("hit whatsit")
- else
- 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)
- setattr(info,a_layer,l_whatsit)
- w_cache[what] = info
- end
- head, current = insert_node_after(head,current,copy_list(info))
- return head, current
end
-local u_cache = { }
+local whatsit do
+
+ local w_cache = caches["whatsit"]
+
+ local tags = {
+ open = "FIC",
+ write = "FIW",
+ close = "FIC",
+ special = "SPE",
+ latelua = "LUA",
+ savepos = "POS",
+ userdefined = "USR",
+ -- backend stuff
+ pdfliteral = "PDF",
+ pdfrefobj = "PDF",
+ pdfannot = "PDF",
+ pdfstartlink = "PDF",
+ pdfendlink = "PDF",
+ pdfdest = "PDF",
+ pdfthread = "PDF",
+ pdfstartthread = "PDF",
+ pdfendthread = "PDF",
+ pdfthreaddata = "PDF",
+ pdflinkdata = "PDF",
+ pdfcolorstack = "PDF",
+ pdfsetmatrix = "PDF",
+ pdfsave = "PDF",
+ pdfrestore = "PDF",
+ }
-local function user(head,current)
- local what = getsubtype(current)
- local info = u_cache[what]
- if info then
- -- print("hit user")
- else
- info = sometext(formatters["U:%s"](what),usedfont)
- setattr(info,a_layer,l_user)
- u_cache[what] = info
+ whatsit = function(head,current)
+ local what = getsubtype(current)
+ local info = w_cache[what]
+ if info then
+ -- print("hit whatsit")
+ else
+ 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)
+ setattr(info,a_layer,l_whatsit)
+ w_cache[what] = info
+ end
+ head, current = insert_node_after(head,current,copy_list(info))
+ return head, current
end
- head, current = insert_node_after(head,current,copy_list(info))
- return head, current
+
end
-local m_cache = { }
-local tags = {
- beginmath = "B",
- endmath = "E",
-}
+local user do
-local function math(head,current)
- local what = getsubtype(current)
- local info = m_cache[what]
- if info then
- -- print("hit math")
- else
- local tag = mathcodes[what]
- info = sometext(formatters["M:%s"](tag and tags[tag] or what),usedfont,nil,c_math_d)
- setattr(info,a_layer,l_math)
- m_cache[what] = info
+ local u_cache = caches["user"]
+
+ user = function(head,current)
+ local what = getsubtype(current)
+ local info = u_cache[what]
+ if info then
+ -- print("hit user")
+ else
+ info = sometext(formatters["U:%s"](what),usedfont)
+ setattr(info,a_layer,l_user)
+ u_cache[what] = info
+ end
+ head, current = insert_node_after(head,current,copy_list(info))
+ return head, current
end
- head, current = insert_node_after(head,current,copy_list(info))
- return head, current
+
end
-local b_cache = { }
+local math do
-local o_cache = table.setmetatableindex(function(t,size)
- local rule = new_rule(2*size,size,size)
- origin = hpack_nodes(rule)
- setcolor(rule,c_origin_d)
- settransparency(rule,c_origin_d)
- setattr(rule,a_layer,l_origin)
- t[size] = origin
- return origin
-end)
+ local m_cache = {
+ beginmath = caches["bmath"],
+ endmath = caches["emath"],
+ }
-local function ruledbox(head,current,vertical,layer,what,simple,previous,trace_origin,parent)
- local wd = getfield(current,"width")
- if wd ~= 0 then
- local ht = getfield(current,"height")
- local dp = getfield(current,"depth")
- local shift = getfield(current,"shift")
- local next = getnext(current)
- local prev = previous
- -- local prev = getprev(current) -- prev can be wrong in math mode < 0.78.3
- setboth(current)
- local linewidth = emwidth/fraction
- local size = 2*linewidth
- local baseline, baseskip
- if dp ~= 0 and ht ~= 0 then
- if wd > 20*linewidth then
- baseline = b_cache.baseline
- 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 = linked_nodes(new_glue(size),new_rule(3*size,linewidth,0),new_glue(size))
- leader = hpack_nodes(leader)
- baseline = new_glue(0)
- setleader(baseline,leader)
- setsubtype(baseline,cleaders_code)
- setfield(baseline,"stretch",65536)
- setfield(baseline,"stretch_order",2)
- setlisttransparency(baseline,c_text)
- b_cache.baseline = baseline
- end
- baseline = copy_list(baseline)
- baseline = hpack_nodes(baseline,wd-size)
- -- or new_hlist, set head and also:
- -- baseline.width = wd
- -- baseline.glue_set = wd/65536
- -- baseline.glue_order = 2
- -- baseline.glue_sign = 1
- baseskip = new_kern(-wd+linewidth)
+ local tags = {
+ beginmath = "B",
+ endmath = "E",
+ }
+
+ math = function(head,current)
+ local what = getsubtype(current)
+ local tag = mathcodes[what]
+ local skip = getkern(current) + getwidth(current) -- surround
+ local info = m_cache[tag][skip]
+ if info then
+ -- print("hit math")
+ else
+ local text, width = sometext(formatters["M:%s"](tag and tags[tag] or what),usedfont,nil,c_math_d)
+ local rule = new_rule(skip,-655360/fraction,2*655360/fraction)
+ setcolor(rule,c_math_d)
+ settransparency(rule,c_math_d)
+ setattr(rule,a_layer,l_math)
+ if tag == "beginmath" then
+ info = new_hlist(setlink(new_glue(-skip),rule,new_glue(-width),text))
else
- baseline = new_rule(wd-size,linewidth,0)
- baseskip = new_kern(-wd+size)
+ info = new_hlist(setlink(new_glue(-skip),rule,new_glue(-skip),text))
end
+ setattr(info,a_layer,l_math)
+ m_cache[tag][skip] = info
end
- local this
- if not simple then
- this = b_cache[what]
- if not this then
- local text = hpack_string(what,usedfont)
- this = linked_nodes(new_kern(-getfield(text,"width")),text)
- setlisttransparency(this,c_text)
- this = new_hlist(this)
- b_cache[what] = this
+ head, current = insert_node_after(head,current,copy_list(info))
+ return head, current
+ end
+
+end
+
+local ruledbox do
+
+ local b_cache = caches["box"]
+ local o_cache = caches["origin"]
+
+ table.setmetatableindex(o_cache,function(t,size)
+ local rule = new_rule(2*size,size,size)
+ local origin = hpack_nodes(rule)
+ setcolor(rule,c_origin_d)
+ settransparency(rule,c_origin_d)
+ setattr(rule,a_layer,l_origin)
+ t[size] = origin
+ return origin
+ end)
+
+ ruledbox = function(head,current,vertical,layer,what,simple,previous,trace_origin,parent)
+ local wd, ht, dp = getwhd(current)
+ if wd ~= 0 then
+ local shift = getshift(current)
+ local dir = getdir(current)
+ -- if dir == "LTL" or dir == "RRT" then
+ -- wd, ht, dp = ht + dp, wd, 0
+ -- end
+ local next = getnext(current)
+ local prev = previous
+ -- local prev = getprev(current) -- prev can be wrong in math mode < 0.78.3
+ setboth(current)
+ local linewidth = emwidth/fraction
+ local size = 2*linewidth
+ local baseline, baseskip
+ if dp ~= 0 and ht ~= 0 then
+ if wd > 20*linewidth then
+ local targetsize = wd - size
+ baseline = b_cache[targetsize]
+ 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 = setlink(new_glue(size),new_rule(3*size,linewidth,0),new_glue(size))
+ leader = hpack_nodes(leader)
+ baseline = new_glue(0,65536,0,2,0)
+ setleader(baseline,leader)
+ setsubtype(baseline,cleaders_code)
+ setlisttransparency(baseline,c_text)
+ baseline = hpack_nodes(baseline,targetsize)
+ b_cache[targetsize] = baseline
+ end
+ baseline = copy_list(baseline)
+ baseskip = new_kern(-wd+linewidth)
+ else
+ baseline = new_rule(wd-size,linewidth,0)
+ baseskip = new_kern(-wd+size)
+ end
end
- end
- -- we need to trigger the right mode (else sometimes no whatits)
- local info = linked_nodes(
- this and copy_list(this) or nil,
- new_rule(linewidth,ht,dp),
- new_rule(wd-size,-dp+linewidth,dp),
- new_rule(linewidth,ht,dp),
- new_kern(-wd+linewidth),
- new_rule(wd-size,ht,-ht+linewidth)
- )
- if baseskip then
- info = linked_nodes(info,baseskip,baseline) -- could be in previous linked
- end
- setlisttransparency(info,c_text)
- info = new_hlist(info)
- --
- setattr(info,a_layer,layer)
- if vertical then
- if shift == 0 then
- info = linked_nodes(current,info)
- elseif trace_origin then
- local size = 2*size
- local origin = o_cache[size]
- origin = copy_list(origin)
- if getid(parent) == vlist_code then
- setfield(origin,"shift",-shift)
- info = linked_nodes(current,new_kern(-size),origin,new_kern(-size),info)
+ local this
+ if not simple then
+ this = b_cache[what]
+ if not this then
+ local text = hpack_string(what,usedfont)
+ this = setlink(new_kern(-getwidth(text)),text)
+ setlisttransparency(this,c_text)
+ this = new_hlist(this)
+ b_cache[what] = this
+ end
+ end
+ -- we need to trigger the right mode (else sometimes no whatits)
+ local info = setlink(
+ this and copy_list(this) or nil,
+ new_rule(linewidth,ht,dp),
+ new_rule(wd-size,-dp+linewidth,dp),
+ new_rule(linewidth,ht,dp),
+ new_kern(-wd+linewidth),
+ new_rule(wd-size,ht,-ht+linewidth),
+ baseskip,
+ baseskip and baseline or nil
+ )
+ setlisttransparency(info,c_text)
+ info = new_hlist(info)
+ --
+ setattr(info,a_layer,layer)
+ if vertical then
+ if shift == 0 then
+ info = setlink(current,dp ~= 0 and new_kern(-dp) or nil,info)
+ elseif trace_origin then
+ local size = 2*size
+ local origin = o_cache[size]
+ origin = copy_list(origin)
+ if getid(parent) == vlist_code then
+ setshift(origin,-shift)
+ info = setlink(current,new_kern(-size),origin,new_kern(-size-dp),info)
+ else
+ -- todo .. i need an example
+ info = setlink(current,dp ~= 0 and new_kern(-dp) or nil,info)
+ end
+ setshift(current,0)
else
- -- todo .. i need an example
- info = linked_nodes(current,info)
+ info = setlink(current,new_dp ~= 0 and new_kern(-dp) or nil,info)
+ setshift(current,0)
end
- setfield(current,"shift",0)
+ info = new_vlist(info,wd,ht,dp,shift)
else
- info = linked_nodes(current,info)
- setfield(current,"shift",0)
+ if shift == 0 then
+ info = setlink(current,new_kern(-wd),info)
+ elseif trace_origin then
+ local size = 2*size
+ local origin = o_cache[size]
+ origin = copy_list(origin)
+ if getid(parent) == vlist_code then
+ info = setlink(current,new_kern(-wd-size-shift),origin,new_kern(-size+shift),info)
+ else
+ setshift(origin,-shift)
+ info = setlink(current,new_kern(-wd-size),origin,new_kern(-size),info)
+ end
+ setshift(current,0)
+ else
+ info = setlink(current,new_kern(-wd),info)
+ setshift(current,0)
+ end
+ info = new_hlist(info,wd,ht,dp,shift)
end
- info = new_vlist(info,wd,ht,dp,shift)
- else
- if shift == 0 then
- info = linked_nodes(current,new_kern(-wd),info)
- elseif trace_origin then
- local size = 2*size
- local origin = o_cache[size]
- origin = copy_list(origin)
- if getid(parent) == vlist_code then
- info = linked_nodes(current,new_kern(-wd-size-shift),origin,new_kern(-size+shift),info)
+ if next then
+ setlink(info,next)
+ end
+ if prev then
+ if getid(prev) == gluespec_code then
+ report_visualize("ignoring invalid prev")
+ -- weird, how can this happen, an inline glue-spec, probably math
else
- setfield(origin,"shift",-shift)
- info = linked_nodes(current,new_kern(-wd-size),origin,new_kern(-size),info)
+ setlink(prev,info)
end
- setfield(current,"shift",0)
+ end
+ if head == current then
+ return info, info
else
- info = linked_nodes(current,new_kern(-wd),info)
- setfield(current,"shift",0)
+ return head, info
end
- info = new_hlist(info,wd,ht,dp,shift)
+ else
+ return head, current
end
+ end
--- how about dir, so maybe just copy the node
---
--- local l = getlist(current)
--- setlist(current,nil)
--- local c = copy_node(current)
--- setlist(current,l)
--- setlist(c,info)
--- info = c
-
- if next then
- setlink(info,next)
- end
- if prev then
- if getid(prev) == gluespec_code then
- report_visualize("ignoring invalid prev")
- -- weird, how can this happen, an inline glue-spec, probably math
+end
+
+local ruledglyph do
+
+ ruledglyph = function(head,current,previous) -- wrong for vertical glyphs
+ local wd = getwidth(current)
+ -- local wd = chardata[getfont(current)][getchar(current)].width
+ if wd ~= 0 then
+ local wd, ht, dp = getwhd(current)
+ -- local dir = getdir(current)
+ -- if dir == "LTL" or dir = "RTT" then
+ -- wd, ht, dp = ht + dp, wd, 0
+ -- end
+ local next = getnext(current)
+ local prev = previous
+ setboth(current)
+ local linewidth = emwidth/(2*fraction)
+ local baseline
+ -- if dp ~= 0 and ht ~= 0 then
+ if (dp >= 0 and ht >= 0) or (dp <= 0 and ht <= 0) then
+ baseline = new_rule(wd-2*linewidth,linewidth,0)
+ end
+ local doublelinewidth = 2*linewidth
+ -- could be a pdf rule (or a user rule now)
+ local info = setlink(
+ 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
+ )
+ local char = chardata[getfont(current)][getchar(current)]
+ if char and type(char.unicode) == "table" then -- hackery test
+ setlistcolor(info,c_ligature)
+ setlisttransparency(info,c_ligature_d)
else
+ setlistcolor(info,c_glyph)
+ setlisttransparency(info,c_glyph_d)
+ end
+ info = new_hlist(info)
+ setattr(info,a_layer,l_glyph)
+ local info = setlink(current,new_kern(-wd),info)
+ info = hpack_nodes(info)
+ setwidth(info,wd)
+ if next then
+ setlink(info,next)
+ end
+ if prev then
setlink(prev,info)
end
- end
- if head == current then
- return info, info
+ if head == current then
+ return info, info
+ else
+ return head, info
+ end
else
- return head, info
+ return head, current
end
- else
- return head, current
end
+
end
-local bpfactor = number.dimenfactors.bp
-
--- callback.register("process_rule",function(n,h,v)
--- local p = string.formatters["0 0 %0.6F %0.6F re f"](h*bpfactor,v*bpfactor)
--- pdf.print("direct",p)
--- end)
-
-local function ruledglyph(head,current,previous)
- local wd = getfield(current,"width")
- -- local wd = chardata[getfont(current)][getchar(current)].width
- if wd ~= 0 then
- local ht = getfield(current,"height")
- local dp = getfield(current,"depth")
- local next = getnext(current)
- local prev = previous
- setboth(current)
- local linewidth = emwidth/(2*fraction)
- local baseline
- -- if dp ~= 0 and ht ~= 0 then
- if (dp >= 0 and ht >= 0) or (dp <= 0 and ht <= 0) then
- baseline = new_rule(wd-2*linewidth,linewidth,0)
- end
- local doublelinewidth = 2*linewidth
- -- could be a pdf rule (or a user rule now)
- 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
- )
- local char = chardata[getfont(current)][getchar(current)]
- if char and type(char.unicode) == "table" then -- hackery test
- setlistcolor(info,c_ligature)
- setlisttransparency(info,c_ligature_d)
+local ruledglue do
+
+ local g_cache_v = caches["vglue"]
+ local g_cache_h = caches["hglue"]
+
+ local tags = {
+ -- userskip = "US",
+ lineskip = "LS",
+ baselineskip = "BS",
+ parskip = "PS",
+ abovedisplayskip = "DA",
+ belowdisplayskip = "DB",
+ abovedisplayshortskip = "SA",
+ belowdisplayshortskip = "SB",
+ leftskip = "LS",
+ rightskip = "RS",
+ topskip = "TS",
+ splittopskip = "ST",
+ tabskip = "AS",
+ spaceskip = "SS",
+ xspaceskip = "XS",
+ parfillskip = "PF",
+ thinmuskip = "MS",
+ medmuskip = "MM",
+ thickmuskip = "ML",
+ leaders = "NL",
+ cleaders = "CL",
+ xleaders = "XL",
+ gleaders = "GL",
+ -- true = "VS",
+ -- false = "HS",
+ }
+
+ -- we sometimes pass previous as we can have issues in math (not watertight for all)
+
+ ruledglue = function(head,current,vertical,parent)
+ local subtype = getsubtype(current)
+ local width = effectiveglue(current,parent)
+ local amount = formatters["%s:%0.3f"](tags[subtype] or (vertical and "VS") or "HS",width*pt_factor)
+ local info = (vertical and g_cache_v or g_cache_h)[amount]
+ if info then
+ -- print("glue hit")
else
- setlistcolor(info,c_glyph)
- setlisttransparency(info,c_glyph_d)
- end
- info = new_hlist(info)
- setattr(info,a_layer,l_glyph)
- local info = linked_nodes(current,new_kern(-wd),info)
- info = hpack_nodes(info)
- setfield(info,"width",wd)
- if next then
- setlink(info,next)
- end
- if prev then
- setlink(prev,info)
+ if subtype == space_code or subtype == xspace_code then -- not yet all space
+ info = sometext(amount,l_glue,c_space)
+ elseif subtype == leftskip_code or subtype == rightskip_code then
+ info = sometext(amount,l_glue,c_skip_a)
+ elseif subtype == userskip_code then
+ if width > 0 then
+ info = sometext(amount,l_glue,c_positive)
+ elseif width < 0 then
+ info = sometext(amount,l_glue,c_negative)
+ else
+ info = sometext(amount,l_glue,c_zero)
+ end
+ else
+ info = sometext(amount,l_glue,c_skip_b)
+ end
+ (vertical and g_cache_v or g_cache_h)[amount] = info
end
- if head == current then
- return info, info
- else
- return head, info
+ info = copy_list(info)
+ if vertical then
+ info = vpack_nodes(info)
end
- else
- return head, current
+ head, current = insert_node_before(head,current,info)
+ return head, getnext(current)
end
+
end
-local g_cache_v = { }
-local g_cache_h = { }
-
-local tags = {
- -- userskip = "US",
- lineskip = "LS",
- baselineskip = "BS",
- parskip = "PS",
- abovedisplayskip = "DA",
- belowdisplayskip = "DB",
- abovedisplayshortskip = "SA",
- belowdisplayshortskip = "SB",
- leftskip = "LS",
- rightskip = "RS",
- topskip = "TS",
- splittopskip = "ST",
- tabskip = "AS",
- spaceskip = "SS",
- xspaceskip = "XS",
- parfillskip = "PF",
- thinmuskip = "MS",
- medmuskip = "MM",
- thickmuskip = "ML",
- leaders = "NL",
- cleaders = "CL",
- xleaders = "XL",
- gleaders = "GL",
- -- true = "VS",
- -- false = "HS",
-}
+local ruledkern do
--- we sometimes pass previous as we can have issues in math (not watertight for all)
+ local k_cache_v = caches["vkern"]
+ local k_cache_h = caches["hkern"]
-local function ruledglue(head,current,vertical,parent)
- local subtype = getsubtype(current)
- local width = effectiveglue(current,parent)
- local amount = formatters["%s:%0.3f"](tags[subtype] or (vertical and "VS") or "HS",width*pt_factor)
- local info = (vertical and g_cache_v or g_cache_h)[amount]
- if info then
- -- print("glue hit")
- else
- if subtype == space_code or subtype == xspace_code then -- not yet all space
- info = sometext(amount,l_glue,c_space)
- elseif subtype == leftskip_code or subtype == rightskip_code then
- info = sometext(amount,l_glue,c_skip_a)
- elseif subtype == userskip_code then
- if width > 0 then
- info = sometext(amount,l_glue,c_positive)
- elseif width < 0 then
- info = sometext(amount,l_glue,c_negative)
+ ruledkern = function(head,current,vertical)
+ local kern = getkern(current)
+ local info = (vertical and k_cache_v or k_cache_h)[kern]
+ if info then
+ -- print("kern hit")
+ else
+ local amount = formatters["%s:%0.3f"](vertical and "VK" or "HK",kern*pt_factor)
+ if kern > 0 then
+ info = sometext(amount,l_kern,c_positive)
+ elseif kern < 0 then
+ info = sometext(amount,l_kern,c_negative)
else
- info = sometext(amount,l_glue,c_zero)
+ info = sometext(amount,l_kern,c_zero)
end
- else
- info = sometext(amount,l_glue,c_skip_b)
+ (vertical and k_cache_v or k_cache_h)[kern] = info
end
- (vertical and g_cache_v or g_cache_h)[amount] = info
- end
- info = copy_list(info)
- if vertical then
- info = vpack_nodes(info)
+ info = copy_list(info)
+ if vertical then
+ info = vpack_nodes(info)
+ end
+ head, current = insert_node_before(head,current,info)
+ return head, getnext(current)
end
- head, current = insert_node_before(head,current,info)
- return head, getnext(current)
+
end
-local k_cache_v = { }
-local k_cache_h = { }
+local ruleditalic do
-local function ruledkern(head,current,vertical)
- local kern = getfield(current,"kern")
- local info = (vertical and k_cache_v or k_cache_h)[kern]
- if info then
- -- print("kern hit")
- else
- local amount = formatters["%s:%0.3f"](vertical and "VK" or "HK",kern*pt_factor)
- if kern > 0 then
- info = sometext(amount,l_kern,c_positive)
- elseif kern < 0 then
- info = sometext(amount,l_kern,c_negative)
+ local i_cache = caches["itatalic"]
+
+ ruleditalic = function(head,current)
+ local kern = getkern(current)
+ local info = i_cache[kern]
+ if info then
+ -- print("kern hit")
else
- info = sometext(amount,l_kern,c_zero)
+ local amount = formatters["%s:%0.3f"]("IC",kern*pt_factor)
+ if kern > 0 then
+ info = sometext(amount,l_kern,c_positive)
+ elseif kern < 0 then
+ info = sometext(amount,l_kern,c_negative)
+ else
+ info = sometext(amount,l_kern,c_zero)
+ end
+ i_cache[kern] = info
end
- (vertical and k_cache_v or k_cache_h)[kern] = info
- end
- info = copy_list(info)
- if vertical then
- info = vpack_nodes(info)
+ info = copy_list(info)
+ head, current = insert_node_before(head,current,info)
+ return head, getnext(current)
end
- head, current = insert_node_before(head,current,info)
- return head, getnext(current)
-end
-local i_cache = { }
+end
-local function ruleditalic(head,current)
- local kern = getfield(current,"kern")
- local info = i_cache[kern]
- if info then
- -- print("kern hit")
- else
- local amount = formatters["%s:%0.3f"]("IC",kern*pt_factor)
- if kern > 0 then
- info = sometext(amount,l_kern,c_positive)
- elseif kern < 0 then
- info = sometext(amount,l_kern,c_negative)
- else
- info = sometext(amount,l_kern,c_zero)
+local ruleddiscretionary do
+
+ local d_cache = caches["discretionary"]
+
+ ruleddiscretionary = function(head,current)
+ local d = d_cache[true]
+ if not the_discretionary then
+ local rule = new_rule(4*emwidth/fraction,4*exheight,exheight)
+ local kern = new_kern(-2*emwidth/fraction)
+ setlink(kern,rule)
+ setcolor(rule,c_discretionary_d)
+ settransparency(rule,c_discretionary_d)
+ setattr(rule,a_layer,l_discretionary)
+ d = new_hlist(kern)
+ d_cache[true] = d
end
- i_cache[kern] = info
+ insert_node_after(head,current,copy_list(d))
+ return head, current
end
- info = copy_list(info)
- head, current = insert_node_before(head,current,info)
- return head, getnext(current)
+
end
-local p_cache_v = { }
-local p_cache_h = { }
+local ruledpenalty do
-local function ruledpenalty(head,current,vertical)
- local penalty = getfield(current,"penalty")
- local info = (vertical and p_cache_v or p_cache_h)[penalty]
- if info then
- -- print("penalty hit")
- else
- local amount = formatters["%s:%s"](vertical and "VP" or "HP",penalty)
- if penalty > 0 then
- info = sometext(amount,l_penalty,c_positive)
- elseif penalty < 0 then
- info = sometext(amount,l_penalty,c_negative)
+ local p_cache_v = caches["vpenalty"]
+ local p_cache_h = caches["hpenalty"]
+
+ ruledpenalty = function(head,current,vertical)
+ local penalty = getpenalty(current)
+ local info = (vertical and p_cache_v or p_cache_h)[penalty]
+ if info then
+ -- print("penalty hit")
else
- info = sometext(amount,l_penalty,c_zero)
+ local amount = formatters["%s:%s"](vertical and "VP" or "HP",penalty)
+ if penalty > 0 then
+ info = sometext(amount,l_penalty,c_positive)
+ elseif penalty < 0 then
+ info = sometext(amount,l_penalty,c_negative)
+ else
+ info = sometext(amount,l_penalty,c_zero)
+ end
+ (vertical and p_cache_v or p_cache_h)[penalty] = info
end
- (vertical and p_cache_v or p_cache_h)[penalty] = info
- end
- info = copy_list(info)
- if vertical then
- info = vpack_nodes(info)
- elseif raisepenalties then
- setfield(info,"shift",-65536*4)
+ info = copy_list(info)
+ if vertical then
+ info = vpack_nodes(info)
+ elseif raisepenalties then
+ setshift(info,-65536*4)
+ end
+ head, current = insert_node_before(head,current,info)
+ return head, getnext(current)
end
- head, current = insert_node_before(head,current,info)
- return head, getnext(current)
+
end
local function visualize(head,vertical,forced,parent)
@@ -869,37 +956,39 @@ local function visualize(head,vertical,forced,parent)
if a ~= attr then
prev_trace_fontkern = trace_fontkern
if a == unsetvalue then
- trace_hbox = false
- trace_vbox = false
- trace_vtop = false
- trace_kern = false
- trace_glue = false
- trace_penalty = false
- trace_fontkern = false
- trace_strut = false
- trace_whatsit = false
- trace_glyph = false
- trace_simple = false
- trace_user = false
- trace_math = false
- trace_italic = false
- trace_origin = false
+ trace_hbox = false
+ trace_vbox = false
+ trace_vtop = false
+ trace_kern = false
+ trace_glue = false
+ trace_penalty = false
+ trace_fontkern = false
+ trace_strut = false
+ trace_whatsit = false
+ trace_glyph = false
+ trace_simple = false
+ trace_user = false
+ trace_math = false
+ trace_italic = false
+ trace_origin = false
+ trace_discretionary = false
else -- dead slow:
- trace_hbox = hasbit(a, 1)
- trace_vbox = hasbit(a, 2)
- trace_vtop = hasbit(a, 4)
- trace_kern = hasbit(a, 8)
- trace_glue = hasbit(a, 16)
- trace_penalty = hasbit(a, 32)
- trace_fontkern = hasbit(a, 64)
- trace_strut = hasbit(a, 128)
- trace_whatsit = hasbit(a, 256)
- trace_glyph = hasbit(a, 512)
- trace_simple = hasbit(a, 1024)
- trace_user = hasbit(a, 2048)
- trace_math = hasbit(a, 4096)
- trace_italic = hasbit(a, 8192)
- trace_origin = hasbit(a,16384)
+ trace_hbox = hasbit(a, 1)
+ trace_vbox = hasbit(a, 2)
+ trace_vtop = hasbit(a, 4)
+ trace_kern = hasbit(a, 8)
+ trace_glue = hasbit(a, 16)
+ trace_penalty = hasbit(a, 32)
+ trace_fontkern = hasbit(a, 64)
+ trace_strut = hasbit(a, 128)
+ trace_whatsit = hasbit(a, 256)
+ trace_glyph = hasbit(a, 512)
+ trace_simple = hasbit(a, 1024)
+ trace_user = hasbit(a, 2048)
+ trace_math = hasbit(a, 4096)
+ trace_italic = hasbit(a, 8192)
+ trace_origin = hasbit(a,16384)
+ trace_discretionary = hasbit(a,32768)
end
attr = a
end
@@ -910,6 +999,9 @@ local function visualize(head,vertical,forced,parent)
head, current = ruledglyph(head,current,previous)
end
elseif id == disc_code then
+ if trace_discretionary then
+ head, current = ruleddiscretionary(head,current)
+ end
local pre, post, replace = getdisc(current)
if pre then
pre = visualize(pre,false,a,parent)
@@ -985,46 +1077,21 @@ end
do
- local function freed(cache)
- local n = 0
- for k, v in next, cache do
- free_node_list(v)
- n = n + 1
+ local function cleanup()
+ for tag, cache in next, caches do
+ for k, v in next, cache do
+ flush_node_list(v)
+ end
end
- if n == 0 then
- return 0, cache
- else
- return n, { }
+ cleanup = function()
+ report_visualize("error, duplicate cleanup")
end
end
- local function cleanup()
- local hf, nw, nb, ng_v, ng_h, np_v, np_h, nk_v, nk_h
- nf, f_cache = freed(f_cache)
- nw, w_cache = freed(w_cache)
- nb, b_cache = freed(b_cache)
- no, o_cache = freed(o_cache)
- ng_v, g_cache_v = freed(g_cache_v)
- ng_h, g_cache_h = freed(g_cache_h)
- np_v, p_cache_v = freed(p_cache_v)
- np_h, p_cache_h = freed(p_cache_h)
- nk_v, k_cache_v = freed(k_cache_v)
- nk_h, k_cache_h = freed(k_cache_h)
- -- report_visualize("cache cleanup: %s fontkerns, %s skips, %s penalties, %s kerns, %s whatsits, %s boxes, %s origins",
- -- nf,ng_v+ng_h,np_v+np_h,nk_v+nk_h,nw,nb,no)
- end
-
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(tonut(head),true)
- -- texsetattribute(a_layer,l)
- -- texsetattribute(a_visual,v)
- -- -- cleanup()
stoptiming(visualizers)
return tonode(head), true
else
@@ -1091,7 +1158,7 @@ end
statistics.register("visualization time",function()
if enabled then
-- cleanup() -- in case we don't don't do it each time
- return format("%s seconds",statistics.elapsedtime(visualizers))
+ return formatters["%s seconds"](statistics.elapsedtime(visualizers))
end
end)
@@ -1099,9 +1166,38 @@ end)
local implement = interfaces.implement
-implement { name = "setvisual", arguments = "string", actions = visualizers.setvisual }
-implement { name = "getvisual", arguments = "string", actions = { setvisual, context } }
-implement { name = "setvisuallayer", arguments = "string", actions = visualizers.setlayer }
-implement { name = "markvisualfonts", arguments = "integer", actions = visualizers.markfonts }
-implement { name = "setvisualfont", arguments = "integer", actions = visualizers.setfont }
+implement {
+ name = "setvisual",
+ arguments = "string",
+ actions = visualizers.setvisual
+}
+
+implement {
+ name = "setvisuals",
+ arguments = "string",
+ actions = visualizers.setvisual
+}
+
+implement {
+ name = "getvisual",
+ arguments = "string",
+ actions = { setvisual, context }
+}
+
+ implement {
+ name = "setvisuallayer",
+ arguments = "string",
+ actions = visualizers.setlayer
+}
+
+implement {
+ name = "markvisualfonts",
+ arguments = "integer",
+ actions = visualizers.markfonts
+}
+implement {
+ name = "setvisualfont",
+ arguments = "integer",
+ actions = visualizers.setfont
+}