summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/mkiv/node-fin.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkiv/node-fin.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/node-fin.lua222
1 files changed, 119 insertions, 103 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-fin.lua b/Master/texmf-dist/tex/context/base/mkiv/node-fin.lua
index dc681d16556..a848cef69da 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/node-fin.lua
+++ b/Master/texmf-dist/tex/context/base/mkiv/node-fin.lua
@@ -12,10 +12,12 @@ if not modules then modules = { } end modules ['node-fin'] = {
-- leaders are also triggers ... see colo-ext for an example (negate a box)
local next, type, format = next, type, string.format
+local setmetatableindex = table.setmetatableindex
local attributes, nodes, node = attributes, nodes, node
local nuts = nodes.nuts
+local tonut = nodes.tonut
local getnext = nuts.getnext
local getid = nuts.getid
@@ -25,6 +27,8 @@ local getattr = nuts.getattr
local getwidth = nuts.getwidth
local getwhd = nuts.getwhd
local getorientation = nuts.getorientation
+local has_dimensions = nuts.has_dimensions
+local getbox = nuts.getbox
local setlist = nuts.setlist
local setleader = nuts.setleader
@@ -38,16 +42,9 @@ local nextnode = nuts.traversers.node
local nodecodes = nodes.nodecodes
local rulecodes = nodes.rulecodes
------ normalrule_code = rulecodes.normal
local boxrule_code = rulecodes.box
local imagerule_code = rulecodes.image
local emptyrule_code = rulecodes.empty
------ userrule_code = rulecodes.user
------ overrule_code = rulecodes.over
------ underrule_code = rulecodes.under
------ fractionrule_code = rulecodes.fraction
------ radicalrule_code = rulecodes.radical
------ outlinerule_code = rulecodes.outline
local glyph_code = nodecodes.glyph
local disc_code = nodecodes.disc
@@ -56,6 +53,9 @@ local rule_code = nodecodes.rule
local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
+local texlists = tex.lists
+local texgetnest = tex.getnest
+
local states = attributes.states
local numbers = attributes.numbers
local a_trigger = attributes.private('trigger')
@@ -182,7 +182,7 @@ local function process(attribute,head,inheritance,default) -- one attribute
local leader = nil
for stack, id in nextnode, head do
if id == glyph_code or id == disc_code then
- check = true -- disc no longer needed as we flatten replace
+ check = true
elseif id == glue_code then
leader = getleader(stack)
if leader then
@@ -235,8 +235,7 @@ local function process(attribute,head,inheritance,default) -- one attribute
-- end nested --
end
elseif id == rule_code then
- local wd, ht, dp = getwhd(stack)
- check = wd ~= 0 or (ht+dp) ~= 0
+ check = has_dimensions(stack)
end
-- much faster this way than using a check() and nested() function
if check then
@@ -309,7 +308,7 @@ local function selective(attribute,head,inheritance,default) -- two attributes
local leader = nil
for stack, id, subtype in nextnode, head do
if id == glyph_code or id == disc_code then
- check = true -- disc no longer needed as we flatten replace
+ check = true
elseif id == glue_code then
leader = getleader(stack)
if leader then
@@ -374,8 +373,7 @@ local function selective(attribute,head,inheritance,default) -- two attributes
-- so no redundant color stuff (only here, layers for instance should obey)
check = false
else
- local wd, ht, dp = getwhd(stack)
- check = wd ~= 0 or (ht+dp) ~= 0
+ check = has_dimensions(stack)
end
end
if check then
@@ -485,8 +483,7 @@ local function stacked(attribute,head,default) -- no triggering, no inheritance,
end
end
elseif id == rule_code then
- local wd, ht, dp = getwhd(stack)
- check = wd ~= 0 or (ht+dp) ~= 0
+ check = has_dimensions(stack)
end
if check then
local a = getattr(stack,attribute)
@@ -559,20 +556,25 @@ local function stacker(attribute,head,default) -- no triggering, no inheritance,
if a and attrib ~= a and nslistwise[a] then -- viewerlayer
head = insert_node_before(head,current,copy_node(nsdata[a]))
list = stacker(attribute,content,a)
+ if list ~= content then
+ setlist(current,list)
+ end
head, current = insert_node_after(head,current,copy_node(nsnone))
else
list = stacker(attribute,content,attrib)
+ if list ~= content then
+ setlist(current,list)
+ end
end
else
list = stacker(attribute,content,default)
- end
- if list ~= content then
- setlist(current,list)
+ if list ~= content then
+ setlist(current,list)
+ end
end
end
elseif id == rule_code then
- local wd, ht, dp = getwhd(current)
- check = wd ~= 0 or (ht+dp) ~= 0
+ check = has_dimensions(current)
end
if check then
@@ -621,89 +623,6 @@ local function stacker(attribute,head,default) -- no triggering, no inheritance,
return head
end
--- local nextid = nodes.nuts.traversers.id
---
--- local function stacker(attribute,head,default) -- no triggering, no inheritance, but list-wise
---
--- -- nsbegin()
--- local stacked = false
---
--- local current = head
--- local previous = head
--- local attrib = default or unsetvalue
--- local check = false
--- local leader = false
---
--- local id = getid(current)
--- while current do
--- if id == glyph_code then
--- check = true
--- elseif id == glue_code then
--- leader = getleader(current)
--- if leader then
--- check = true
--- end
--- elseif id == hlist_code or id == vlist_code then
--- local content = getlist(current)
--- if content then
--- local list
--- if nslistwise then
--- local a = getattr(current,attribute)
--- if a and attrib ~= a and nslistwise[a] then -- viewerlayer
--- head = insert_node_before(head,current,copy_node(nsdata[a]))
--- list = stacker(attribute,content,a)
--- head, current = insert_node_after(head,current,copy_node(nsnone))
--- else
--- list = stacker(attribute,content,attrib)
--- end
--- else
--- list = stacker(attribute,content,default)
--- end
--- if list ~= content then
--- setlist(current,list)
--- end
--- end
--- elseif id == rule_code then
--- check = getwidth(current) ~= 0
--- end
---
--- if check then
--- local a = getattr(current,attribute) or unsetvalue
--- if a ~= attrib then
--- if not stacked then
--- stacked = true
--- nsbegin()
--- end
--- local n = nsstep(a)
--- if n then
--- head = insert_node_before(head,current,n) -- a
--- end
--- attrib = a
--- if leader then
--- -- tricky as a leader has to be a list so we cannot inject before
--- local list = stacker(attribute,leader,attrib)
--- leader = false
--- end
--- end
--- check = false
--- end
---
--- previous = current
---
--- current, id = nextid(current,current)
--- end
---
--- if stacked then
--- local n = nsend()
--- while n do
--- head = insert_node_after(head,previous,n)
--- n = nsend()
--- end
--- end
---
--- return head
--- end
-
states.stacker = function(namespace,attribute,head,default)
local head = stacker(attribute,head,default)
nsreset()
@@ -715,3 +634,100 @@ end
statistics.register("attribute processing time", function()
return statistics.elapsedseconds(attributes,"front- and backend")
end)
+
+-- -- --
+
+do
+
+ local cleaners = { }
+ local trace = true -- false
+
+ function attributes.cleanup()
+ if next(cleaners) then
+ local values = setmetatableindex("table")
+
+ if trace then
+ starttiming(values)
+ end
+
+ local function check(l)
+ for n, id in nextnode, l do
+ if id == hlist_code or id == vlist_code or id == glue_code then
+ local l = getlist(n)
+ if l then
+ check(l)
+ end
+ end
+ for a in next, cleaners do
+ local v = getattr(n,a)
+ if v then
+ -- values[a] = values[a] + 1
+ values[a][v] = true
+ end
+ end
+ end
+ end
+
+ local top = texgetnest("ptr")
+ for i=1,top do
+ local l = texgetnest(i)
+ if l then
+ check(tonut(l.head))
+ end
+ end
+
+ do local l
+ l = tonut(texlists.page_ins_head) if l then check(l) end
+ l = tonut(texlists.contrib_head) if l then check(l) end
+ l = tonut(texlists.page_discards_head) if l then check(l) end
+ l = tonut(texlists.split_discards_head) if l then check(l) end
+ l = tonut(texlists.page_head) if l then check(l) end
+ end
+
+ -- todo: traverseboxes
+
+ for i=0,65535 do
+ local b = getbox(i)
+ if b then
+ local l = getlist(b)
+ if l then
+ check(l)
+ end
+ end
+ end
+
+ for a, t in next, values do
+ cleaners[a](a,t)
+ end
+
+ if trace then
+ stoptiming(values)
+ local a = table.sortedkeys(values)
+ local t = statistics.elapsedtime(values)
+ local r = tex.getcount("realpageno")
+ if #a == 0 then
+ logs.report("attributes","cleaning up at page %i took %s seconds, no attributes",r,t)
+ else
+ logs.report("attributes","cleaning up at page %i took %s seconds, attributes: % t",r,t,a)
+ end
+ end
+ end
+ end
+
+ -- not yet used but when we do ... delay a call till we enable it (attr-ini.mkiv)
+
+ -- local function show(a,t) for k, v in next, t do print(a,k) end end
+ --
+ -- attributes.registercleaner( 1, show)
+ -- attributes.registercleaner( 2, show)
+
+ function attributes.registercleaner(a,f)
+ cleaners[a] = f
+ end
+
+ implement {
+ name = "cleanupattributes",
+ actions = attributes.cleanup,
+ }
+
+end