summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/node-bck.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkiv/node-bck.lua')
-rw-r--r--tex/context/base/mkiv/node-bck.lua378
1 files changed, 244 insertions, 134 deletions
diff --git a/tex/context/base/mkiv/node-bck.lua b/tex/context/base/mkiv/node-bck.lua
index 4ed5abe5e..a19e5e969 100644
--- a/tex/context/base/mkiv/node-bck.lua
+++ b/tex/context/base/mkiv/node-bck.lua
@@ -9,178 +9,288 @@ if not modules then modules = { } end modules ['node-bck'] = {
-- beware, this one takes quite some runtime, so we need a status flag
-- maybe some page related state
+-- todo: done (or just get rid of done altogether) ... saves no purpose
+-- any longer
+
local attributes, nodes, node = attributes, nodes, node
-local enableaction = nodes.tasks.enableaction
+local enableaction = nodes.tasks.enableaction
-local nodecodes = nodes.nodecodes
-local listcodes = nodes.listcodes
+local nodecodes = nodes.nodecodes
+local listcodes = nodes.listcodes
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
-local cell_code = listcodes.cell
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
-local nuts = nodes.nuts
-local nodepool = nuts.pool
+local alignmentlist_code = listcodes.alignment
+local celllist_code = listcodes.cell
-local tonode = nuts.tonode
-local tonut = nuts.tonut
+local nuts = nodes.nuts
+local nodepool = nuts.pool
-local getnext = nuts.getnext
-local getprev = nuts.getprev
-local getid = nuts.getid
-local getlist = nuts.getlist
-local getattr = nuts.getattr
-local getsubtype = nuts.getsubtype
-local getwhd = nuts.getwhd
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getid = nuts.getid
+local getlist = nuts.getlist
+local getattr = nuts.getattr
+local getsubtype = nuts.getsubtype
+local getwhd = nuts.getwhd
+local getwidth = nuts.getwidth
+local getprop = nuts.getprop
-local setattr = nuts.setattr
-local setlink = nuts.setlink
-local setlist = nuts.setlist
+local setattr = nuts.setattr
+local setlink = nuts.setlink
+local setlist = nuts.setlist
+local setattributelist = nuts.setattributelist
+local setprop = nuts.setprop
-local traverse = nuts.traverse
-local traverse_id = nuts.traverse_id
+local takebox = nuts.takebox
+local findtail = nuts.tail
-local new_rule = nodepool.rule
-local new_glue = nodepool.glue
+local nextnode = nuts.traversers.node
+local nexthlist = nuts.traversers.hlist
+local nextlist = nuts.traversers.list
-local a_color = attributes.private('color')
-local a_transparency = attributes.private('transparency')
-local a_colormodel = attributes.private('colormodel')
-local a_background = attributes.private('background')
-local a_alignbackground = attributes.private('alignbackground')
+local flush_node_list = nuts.flush_list
-local function add_backgrounds(head) -- rather old code .. to be redone
- local current = head
- while current do
- local id = getid(current)
- if id == hlist_code or id == vlist_code then
- local list = getlist(current)
- if list then
- local head = add_backgrounds(list)
- if head then
- setlist(current,head)
- list = head
- end
+local new_rule = nodepool.rule
+local new_kern = nodepool.kern
+local new_hlist = nodepool.hlist
+
+local privateattributes = attributes.private
+local unsetvalue = attributes.unsetvalue
+
+local linefillers = nodes.linefillers
+
+local a_color = privateattributes("color")
+local a_transparency = privateattributes("transparency")
+local a_colormodel = privateattributes("colormodel")
+local a_background = privateattributes("background")
+local a_alignbackground = privateattributes("alignbackground")
+local a_linefiller = privateattributes("linefiller")
+local a_ruled = privateattributes("ruled")
+
+local trace_alignment = false
+local report_alignment = logs.reporter("backgrounds","alignment")
+
+trackers.register("backgrounds.alignments",function(v) trace_alignment = v end)
+
+-- We can't use listbuilders with where=alignment because at that stage we have
+-- unset boxes. Also, post_linebreak is unsuitable for nested processing as we
+-- get the same stuff many times (wrapped again and again).
+--
+-- After many experiments with different callbacks the shipout is still the best
+-- place but then we need to store some settings longer or save them with the node.
+-- For color only we can get away with it with an extra attribute flagging a row
+-- but for more complex stuff we can better do as we do here now.
+
+local overshoot = math.floor(65781/5) -- could be an option per table (just also store it)
+
+local function colored_a(current,list,template,id)
+ local width, height, depth = getwhd(current)
+ local total = height + depth
+ if width > 0 and total > 0 then
+ local rule = nil
+ --
+ local a = getattr(template,a_linefiller)
+ if a then
+ local d = linefillers.data[a%1000]
+ if d then
+ rule = linefillers.filler(template,d,width,height,depth)
+ end
+ end
+ --
+ if not rule then
+ rule = new_rule(width,height,depth)
+ end
+ setattributelist(rule,template)
+ local back = new_kern(-((id == vlist_code and total) or width))
+ return setlink(rule,back,list)
+ end
+end
+
+local function colored_b(current,list,template,id,indent)
+ local width, height, depth = getwhd(current)
+ local total = height + depth
+ if width > 0 and total > 0 then
+ local fore = (indent ~= 0) and new_kern(indent)
+ local rule = nil
+ --
+ local a = getattr(template,a_linefiller)
+ if a then
+ local d = linefillers.data[a%1000]
+ if d then
+ rule = linefillers.filler(template,d,width-indent,height,depth)
end
- local width, height, depth = getwhd(current)
- if width > 0 then
- local background = getattr(current,a_background)
+ end
+ --
+ if not rule then
+ rule = new_rule(width-indent,height+overshoot,depth+overshoot)
+ setattributelist(rule,template)
+ end
+ if overshoot == 0 then
+ local back = new_kern(-((id == vlist_code and total) or width))
+ return setlink(fore,rule,back,list)
+ else
+ rule = new_hlist(rule)
+ return setlink(fore,rule,list)
+ end
+ end
+end
+
+local templates = { }
+local currentrow = 0
+local enabled = false
+local alignments = false
+
+local function add_alignbackgrounds(head,list)
+ for current, id, subtype, list in nextlist, list do
+ if list and id == hlist_code and subtype == celllist_code then
+ for template in nexthlist, list do
+ local background = getattr(template,a_alignbackground)
if background then
- -- direct to hbox
- -- colorspace is already set so we can omit that and stick to color
- local mode = getattr(current,a_colormodel)
- if mode then
- local skip = id == hlist_code and width or (height + depth)
- local glue = new_glue(-skip)
- local rule = new_rule(width,height,depth)
- local color = getattr(current,a_color)
- local transparency = getattr(current,a_transparency)
- setattr(rule,a_colormodel,mode)
- if color then
- setattr(rule,a_color,color)
- end
- if transparency then
- setattr(rule,a_transparency,transparency)
- end
--- setlink(rule,glue)
--- if list then
--- setlink(glue,list)
--- end
--- setlist(current,rule)
- setlist(current,rule,glue,list)
+ local list = colored_a(current,list,template)
+ if list then
+ setlist(current,list)
end
+ setattr(template,a_alignbackground,unsetvalue) -- or property
end
+ break
end
end
- current = getnext(current)
end
- return head, true
+ local template = getprop(head,"alignmentchecked")
+ if template then
+ list = colored_b(head,list,template[1],hlist_code,template[2])
+ flush_node_list(template)
+ templates[currentrow] = false
+ return list
+ end
end
-local function add_alignbackgrounds(head)
- local current = head
- while current do
- local id = getid(current)
- if id == hlist_code then
- local list = getlist(current)
- if not list then
- -- no need to look
- elseif getsubtype(current) == cell_code then
- local background = nil
- local found = nil
- -- for l in traverse(list) do
- -- background = getattr(l,a_alignbackground)
- -- if background then
- -- found = l
- -- break
- -- end
- -- end
- -- we know that it's a fake hlist (could be user node)
- -- but we cannot store tables in user nodes yet
- for l in traverse_id(hpack_code,list) do
- background = getattr(l,a_alignbackground)
- if background then
- found = l
+local function add_backgrounds(head,id,list)
+ if list then
+ for current, id, subtype, list in nextlist, list do
+ if list then
+ if alignments and subtype == alignmentlist_code then
+ local l = add_alignbackgrounds(current,list)
+ if l then
+ list = l
+ setlist(current,list)
end
- break
end
- --
- if background then
- -- current has subtype 5 (cell)
- local width, height, depth = getwhd(current)
- if width > 0 then
- local mode = getattr(found,a_colormodel)
- if mode then
- local glue = new_glue(-width)
- local rule = new_rule(width,height,depth)
- local color = getattr(found,a_color)
- local transparency = getattr(found,a_transparency)
- setattr(rule,a_colormodel,mode)
- if color then
- setattr(rule,a_color,color)
- end
- if transparency then
- setattr(rule,a_transparency,transparency)
- end
- setlink(rule,glue)
- if list then
- setlink(glue,list)
- end
- setlist(current,rule)
- end
- end
+ local l = add_backgrounds(current,id,list)
+ if l then
+ list = l
+ setlist(current,l)
end
- else
- add_alignbackgrounds(list)
end
- elseif id == vlist_code then
- local list = getlist(current)
- if list then
- add_alignbackgrounds(list)
+ end
+ end
+ if id == hlist_code or id == vlist_code then
+ local background = getattr(head,a_background)
+ if background then
+ list = colored_a(head,list,head,id)
+ -- not needed
+ setattr(head,a_background,unsetvalue) -- or property
+ return list
+ end
+ end
+end
+
+function nodes.handlers.backgrounds(head)
+ add_backgrounds(head,getid(head),getlist(head))
+ return head
+end
+
+function nodes.handlers.backgroundspage(head,where)
+ if head and where == "alignment" then
+ for n in nexthlist, head do
+ local p = getprop(n,"alignmentchecked")
+ if not p and getsubtype(n) == alignmentlist_code then
+ currentrow = currentrow + 1
+ local template = templates[currentrow]
+ if trace_alignment then
+ report_alignment("%03i %s %s",currentrow,"page",template and "+" or "-")
+ end
+ setprop(n,"alignmentchecked",template)
end
end
- current = getnext(current)
end
- return head, true
+ return head
end
--- nodes.handlers.backgrounds = add_backgrounds
--- nodes.handlers.alignbackgrounds = add_alignbackgrounds
+function nodes.handlers.backgroundsvbox(head,where)
+ if head and where == "vbox" then
+ local list = getlist(head)
+ if list then
+ for n in nexthlist, list do
+ local p = getprop(n,"alignmentchecked")
+ if not p and getsubtype(n) == alignmentlist_code then
+ currentrow = currentrow + 1
+ local template = templates[currentrow]
+ if trace_alignment then
+ report_alignment("%03i %s %s",currentrow,"vbox",template and "+" or "-")
+ end
+ setprop(n,"alignmentchecked",template)
+ end
+ end
+ end
+ end
+ return head
+end
-nodes.handlers.backgrounds = function(head) local head, done = add_backgrounds (tonut(head)) return tonode(head), done end
-nodes.handlers.alignbackgrounds = function(head) local head, done = add_alignbackgrounds(tonut(head)) return tonode(head), done end
+-- interfaces.implement {
+-- name = "enablebackgroundboxes",
+-- onlyonce = true,
+-- actions = enableaction,
+-- arguments = { "'shipouts'", "'nodes.handlers.backgrounds'" }
+-- }
+--
+-- doing it in the shipout works as well but this is nicer
+
+local function enable(alignmentstoo)
+ if not enabled then
+ enabled = true
+ enableaction("shipouts","nodes.handlers.backgrounds")
+ end
+ if not alignments and alignmentstoo then
+ alignments = true
+ enableaction("vboxbuilders","nodes.handlers.backgroundsvbox")
+ enableaction("mvlbuilders", "nodes.handlers.backgroundspage")
+ end
+end
interfaces.implement {
name = "enablebackgroundboxes",
onlyonce = true,
- actions = enableaction,
- arguments = { "'shipouts'", "'nodes.handlers.backgrounds'" }
+ actions = enable,
}
interfaces.implement {
name = "enablebackgroundalign",
onlyonce = true,
- actions = enableaction,
- arguments = { "'shipouts'", "'nodes.handlers.alignbackgrounds'" }
+ actions = function()
+ enable(true)
+ end,
+}
+
+interfaces.implement {
+ name = "setbackgroundrowdata",
+ arguments = { "integer", "integer", "dimension" },
+ actions = function(row,box,indent)
+ row = row -1 -- better here than in tex
+ if box == 0 then
+ templates[row] = false
+ else
+ templates[row] = { takebox(box), indent }
+ end
+ end,
+}
+
+interfaces.implement {
+ name = "resetbackgroundrowdata",
+ actions = function()
+ currentrow = 0
+ end,
}