diff options
author | Karl Berry <karl@freefriends.org> | 2013-04-08 00:43:40 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2013-04-08 00:43:40 +0000 |
commit | 824f7b0903de8ad7f6ee3d7656005e4c59155e06 (patch) | |
tree | abfc8673ef9916f3ab7074e811207384c301492b /Master/texmf-dist/tex/context/base/node-fin.lua | |
parent | 689aefb0727676ed3cddf331337b4be226495e72 (diff) |
context import for TL13, from www.pragma-ade.com/context/beta/cont-tmf.zip
git-svn-id: svn://tug.org/texlive/trunk@29731 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/context/base/node-fin.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/node-fin.lua | 1198 |
1 files changed, 979 insertions, 219 deletions
diff --git a/Master/texmf-dist/tex/context/base/node-fin.lua b/Master/texmf-dist/tex/context/base/node-fin.lua index 5c1cc9ad57a..2e62ebcb5aa 100644 --- a/Master/texmf-dist/tex/context/base/node-fin.lua +++ b/Master/texmf-dist/tex/context/base/node-fin.lua @@ -3,17 +3,18 @@ if not modules then modules = { } end modules ['node-fin'] = { comment = "companion to node-fin.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" + license = "see context related readme files", } -- this module is being reconstructed +-- local functions, only slightly slower local next, type, format = next, type, string.format local attributes, nodes, node = attributes, nodes, node -local has_attribute = node.has_attribute local copy_node = node.copy +local find_tail = node.slide local nodecodes = nodes.nodecodes local whatcodes = nodes.whatcodes @@ -28,13 +29,15 @@ local vlist_code = nodecodes.vlist local pdfliteral_code = whatcodes.pdfliteral -local states = attributes.states -local numbers = attributes.numbers -local trigger = attributes.private('trigger') -local triggering = false +local states = attributes.states +local numbers = attributes.numbers +local a_trigger = attributes.private('trigger') +local triggering = false -local starttiming = statistics.starttiming -local stoptiming = statistics.stoptiming +local starttiming = statistics.starttiming +local stoptiming = statistics.stoptiming +local loadstripped = utilities.lua.loadstripped +local unsetvalue = attributes.unsetvalue -- these two will be like trackers @@ -69,7 +72,7 @@ end -- end -- -- function states.check() --- texio.write_nl(concat(collected,"\n")) +-- logs.report("states",concat(collected,"\n")) -- end -- we used to do the main processor loop here and call processor for each node @@ -77,97 +80,105 @@ end -- so that we moved looping to the processor itself; this may lead to a bit of -- duplicate code once that we have more state handlers -local function process_attribute(head,plugin) -- head,attribute,enabled,initializer,resolver,processor,finalizer - local namespace = plugin.namespace - if namespace.enabled ~= false then -- this test will go away +-- local function process_attribute(head,plugin) -- head,attribute,enabled,initializer,resolver,processor,finalizer +-- local namespace = plugin.namespace +-- if namespace.enabled ~= false then -- this test will go away +-- starttiming(attributes) -- in principle we could delegate this to the main caller +-- local done, used, ok = false, nil, false +-- local attribute = namespace.attribute or numbers[plugin.name] -- todo: plugin.attribute +-- local processor = plugin.processor +-- if processor then +-- local initializer = plugin.initializer +-- local resolver = plugin.resolver +-- local inheritance = (resolver and resolver()) or nil -- -0x7FFFFFFF -- we can best use nil and skip ! +-- if initializer then +-- initializer(namespace,attribute,head) +-- end +-- head, ok = processor(namespace,attribute,head,inheritance) +-- if ok then +-- local finalizer = plugin.finalizer +-- if finalizer then +-- head, ok, used = finalizer(namespace,attribute,head) +-- if used then +-- local flusher = plugin.flusher +-- if flusher then +-- head = flusher(namespace,attribute,head,used) +-- end +-- end +-- end +-- done = true +-- end +-- end +-- stoptiming(attributes) +-- return head, done +-- else +-- return head, false +-- end +-- end +-- +-- function nodes.installattributehandler(plugin) -- we need to avoid this nested function +-- return function(head) +-- return process_attribute(head,plugin) +-- end +-- end + +-- An experiment: lean and mean functions. It is not really faster but +-- with upcoming functionality it might make a difference, e.g. features +-- like 'casing' and 'italics' can be called a lot so there it makes sense. + +nodes.plugindata = nil + +local template = [[ +local plugin = nodes.plugindata +local starttiming = statistics.starttiming +local stoptiming = statistics.stoptiming +local namespace = plugin.namespace +local attribute = namespace.attribute or attributes.numbers[plugin.name] +local processor = plugin.processor +local initializer = plugin.initializer +local resolver = plugin.resolver +local finalizer = plugin.finalizer +local flusher = plugin.flusher +if not processor then + return function(head) + return head, false + end +elseif initializer or finalizer or resolver then + return function(head) starttiming(attributes) local done, used, ok = false, nil, false - local attribute = namespace.attribute or numbers[plugin.name] -- todo: plugin.attribute - local processor = plugin.processor - if processor then - local initializer = plugin.initializer - local resolver = plugin.resolver - local inheritance = (resolver and resolver()) or nil -- -0x7FFFFFFF -- we can best use nil and skip ! - if initializer then - initializer(namespace,attribute,head) - end - head, ok = processor(namespace,attribute,head,inheritance) - if ok then - local finalizer = plugin.finalizer - if finalizer then - head, ok, used = finalizer(namespace,attribute,head) - if used then - local flusher = plugin.flusher - if flusher then - head = flusher(namespace,attribute,head,used) - end - end + local inheritance = (resolver and resolver()) or nil -- -0x7FFFFFFF -- we can best use nil and skip ! + if initializer then + initializer(namespace,attribute,head) + end + head, ok = processor(namespace,attribute,head,inheritance) + if ok then + if finalizer then + head, ok, used = finalizer(namespace,attribute,head) + if used and flusher then + head = flusher(namespace,attribute,head,used) end - done = true end + done = true end stoptiming(attributes) return head, done - else - return head, false end -end - --- nodes.process_attribute = process_attribute - -function nodes.installattributehandler(plugin) -- we need to avoid this nested function +else return function(head) - return process_attribute(head,plugin) + starttiming(attributes) + local head, done = processor(namespace,attribute,head) + stoptiming(attributes) + return head, done end end +nodes.plugindata = nil +]] ---~ experiment (maybe local to function makes more sense) ---~ ---~ plugindata = { } ---~ ---~ local template = [[ ---~ local plugin = plugindata["%s"] ---~ local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming ---~ local namespace = plugin.namespace ---~ local attribute = namespace.attribute ---~ local processor = plugin.processor ---~ local initializer = plugin.initializer ---~ local resolver = plugin.resolver ---~ local finalizer = plugin.finalizer ---~ local flusher = plugin.flusher ---~ return function (head) ---~ if namespace.enabled then ---~ starttiming(attributes) ---~ local done, used, ok = false, nil, false ---~ if procesxsor then ---~ local inheritance = (resolver and resolver()) or nil -- -0x7FFFFFFF -- we can best use nil and skip ! ---~ if initializer then ---~ initializer(namespace,attribute,head) ---~ end ---~ head, ok = processor(namespace,attribute,head,inheritance) ---~ if ok then ---~ if finalizer then ---~ head, ok, used = finalizer(namespace,attribute,head) ---~ if used and flusher then ---~ head = flusher(namespace,attribute,head,used) ---~ end ---~ end ---~ done = true ---~ end ---~ end ---~ stoptiming(attributes) ---~ return head, done ---~ else ---~ return head, false ---~ end ---~ end ---~ ]] ---~ ---~ function nodes.installattributehandler(plugin) -- we need to avoid this nested function ---~ plugindata[plugin.name] = plugin ---~ local str = format(template,plugin.name) ---~ return loadstring(str)() ---~ end +function nodes.installattributehandler(plugin) + nodes.plugindata = plugin + return loadstripped(template)() +end -- the injectors @@ -176,6 +187,7 @@ local insert_node_after = node.insert_after local nsdata, nsnone, nslistwise, nsforced, nsselector, nstrigger local current, current_selector, done = 0, 0, false -- nb, stack has a local current ! +local nsbegin, nsend function states.initialize(namespace,attribute,head) nsdata = namespace.data @@ -183,10 +195,17 @@ function states.initialize(namespace,attribute,head) nsforced = namespace.forced nsselector = namespace.selector nslistwise = namespace.listwise - nstrigger = triggering and namespace.triggering and trigger + nstrigger = triggering and namespace.triggering and a_trigger current = 0 current_selector = 0 done = false -- todo: done cleanup + nsstep = namespace.resolve_step + if nsstep then + nsbegin = namespace.resolve_begin + nsend = namespace.resolve_end + nspush = namespace.push + nspop = namespace.pop + end end function states.finalize(namespace,attribute,head) -- is this one ok? @@ -205,15 +224,351 @@ function states.finalize(namespace,attribute,head) -- is this one ok? return head, false, false end +-- disc nodes can be ignored +-- we need to deal with literals too (reset as well as oval) +-- if id == glyph_code or (id == whatsit_code and stack.subtype == pdfliteral_code) or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then + +-- local function process(namespace,attribute,head,inheritance,default) -- one attribute +-- local stack, done = head, false +-- while stack do +-- local id = stack.id +-- if id == glyph_code or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code +-- local c = stack[attribute] +-- if c then +-- if default and c == inheritance then +-- if current ~= default then +-- head = insert_node_before(head,stack,copy_node(nsdata[default])) +-- current = default +-- done = true +-- end +-- elseif current ~= c then +-- head = insert_node_before(head,stack,copy_node(nsdata[c])) +-- current = c +-- done = true +-- end +-- -- here ? compare selective +-- if id == glue_code then --leader +-- -- same as *list +-- local content = stack.leader +-- if content then +-- local savedcurrent = current +-- local ci = content.id +-- if ci == hlist_code or ci == vlist_code then +-- -- else we reset inside a box unneeded, okay, the downside is +-- -- that we trigger color in each repeated box, so there is room +-- -- for improvement here +-- current = 0 +-- end +-- local ok = false +-- if nstrigger and stack[nstrigger] then +-- local outer = stack[attribute] +-- if outer ~= inheritance then +-- stack.leader, ok = process(namespace,attribute,content,inheritance,outer) +-- else +-- stack.leader, ok = process(namespace,attribute,content,inheritance,default) +-- end +-- else +-- stack.leader, ok = process(namespace,attribute,content,inheritance,default) +-- end +-- current = savedcurrent +-- done = done or ok +-- end +-- end +-- elseif default and inheritance then +-- if current ~= default then +-- head = insert_node_before(head,stack,copy_node(nsdata[default])) +-- current = default +-- done = true +-- end +-- elseif current > 0 then +-- head = insert_node_before(head,stack,copy_node(nsnone)) +-- current = 0 +-- done = true +-- end +-- elseif id == hlist_code or id == vlist_code then +-- local content = stack.list +-- if content then +-- local ok = false +-- if nstrigger and stack[nstrigger] then +-- local outer = stack[attribute] +-- if outer ~= inheritance then +-- stack.list, ok = process(namespace,attribute,content,inheritance,outer) +-- else +-- stack.list, ok = process(namespace,attribute,content,inheritance,default) +-- end +-- else +-- stack.list, ok = process(namespace,attribute,content,inheritance,default) +-- end +-- done = done or ok +-- end +-- end +-- stack = stack.next +-- end +-- return head, done +-- end + +-- local function process(namespace,attribute,head,inheritance,default) -- one attribute +-- local stack, done = head, false + +-- local function check() +-- local c = stack[attribute] +-- if c then +-- if default and c == inheritance then +-- if current ~= default then +-- head = insert_node_before(head,stack,copy_node(nsdata[default])) +-- current = default +-- done = true +-- end +-- elseif current ~= c then +-- head = insert_node_before(head,stack,copy_node(nsdata[c])) +-- current = c +-- done = true +-- end +-- elseif default and inheritance then +-- if current ~= default then +-- head = insert_node_before(head,stack,copy_node(nsdata[default])) +-- current = default +-- done = true +-- end +-- elseif current > 0 then +-- head = insert_node_before(head,stack,copy_node(nsnone)) +-- current = 0 +-- done = true +-- end +-- return c +-- end + +-- local function nested(content) +-- if nstrigger and stack[nstrigger] then +-- local outer = stack[attribute] +-- if outer ~= inheritance then +-- return process(namespace,attribute,content,inheritance,outer) +-- else +-- return process(namespace,attribute,content,inheritance,default) +-- end +-- else +-- return process(namespace,attribute,content,inheritance,default) +-- end +-- end + +-- while stack do +-- local id = stack.id +-- if id == glyph_code then +-- check() +-- elseif id == glue_code then +-- local content = stack.leader +-- if content and check() then +-- local savedcurrent = current +-- local ci = content.id +-- if ci == hlist_code or ci == vlist_code then +-- -- else we reset inside a box unneeded, okay, the downside is +-- -- that we trigger color in each repeated box, so there is room +-- -- for improvement here +-- current = 0 +-- end + +-- local ok = false +-- stack.leader, ok = nested(content) +-- done = done or ok + +-- current = savedcurrent +-- end +-- elseif id == hlist_code or id == vlist_code then +-- local content = stack.list +-- if content then + +-- local ok = false +-- stack.list, ok = nested(content) +-- done = done or ok + +-- end +-- elseif id == rule_code then +-- if stack.width ~= 0 then +-- check() +-- end +-- end +-- stack = stack.next +-- end +-- return head, done +-- end + +-- local function process(namespace,attribute,head,inheritance,default) -- one attribute +-- local stack, done = head, false +-- while stack do +-- local id = stack.id +-- if id == glyph_code then +-- -- begin of check +-- local c = stack[attribute] +-- if c then +-- if default and c == inheritance then +-- if current ~= default then +-- head = insert_node_before(head,stack,copy_node(nsdata[default])) +-- current = default +-- done = true +-- end +-- elseif current ~= c then +-- head = insert_node_before(head,stack,copy_node(nsdata[c])) +-- current = c +-- done = true +-- end +-- elseif default and inheritance then +-- if current ~= default then +-- head = insert_node_before(head,stack,copy_node(nsdata[default])) +-- current = default +-- done = true +-- end +-- elseif current > 0 then +-- head = insert_node_before(head,stack,copy_node(nsnone)) +-- current = 0 +-- done = true +-- end +-- -- end of check +-- elseif id == glue_code then +-- local content = stack.leader +-- if content then +-- -- begin of check +-- local c = stack[attribute] +-- if c then +-- if default and c == inheritance then +-- if current ~= default then +-- head = insert_node_before(head,stack,copy_node(nsdata[default])) +-- current = default +-- done = true +-- end +-- elseif current ~= c then +-- head = insert_node_before(head,stack,copy_node(nsdata[c])) +-- current = c +-- done = true +-- end +-- -- begin special to this check +-- local savedcurrent = current +-- local ci = content.id +-- if ci == hlist_code or ci == vlist_code then +-- -- else we reset inside a box unneeded, okay, the downside is +-- -- that we trigger color in each repeated box, so there is room +-- -- for improvement here +-- current = 0 +-- end +-- -- begin nested -- +-- local ok = false +-- if nstrigger and stack[nstrigger] then +-- local outer = stack[attribute] +-- if outer ~= inheritance then +-- stack.leader, ok = process(namespace,attribute,content,inheritance,outer) +-- else +-- stack.leader, ok = process(namespace,attribute,content,inheritance,default) +-- end +-- else +-- stack.leader, ok = process(namespace,attribute,content,inheritance,default) +-- end +-- -- end nested -- +-- done = done or ok +-- current = savedcurrent +-- -- end special to this check +-- elseif default and inheritance then +-- if current ~= default then +-- head = insert_node_before(head,stack,copy_node(nsdata[default])) +-- current = default +-- done = true +-- end +-- elseif current > 0 then +-- head = insert_node_before(head,stack,copy_node(nsnone)) +-- current = 0 +-- done = true +-- end +-- -- end of check +-- end +-- elseif id == hlist_code or id == vlist_code then +-- local content = stack.list +-- if content then +-- -- begin nested -- +-- local ok +-- if nstrigger and stack[nstrigger] then +-- local outer = stack[attribute] +-- if outer ~= inheritance then +-- stack.list, ok = process(namespace,attribute,content,inheritance,outer) +-- else +-- stack.list, ok = process(namespace,attribute,content,inheritance,default) +-- end +-- else +-- stack.list, ok = process(namespace,attribute,content,inheritance,default) +-- end +-- -- end nested -- +-- done = done or ok +-- end +-- elseif id == rule_code then +-- if stack.width ~= 0 then +-- -- begin of check +-- local c = stack[attribute] +-- if c then +-- if default and c == inheritance then +-- if current ~= default then +-- head = insert_node_before(head,stack,copy_node(nsdata[default])) +-- current = default +-- done = true +-- end +-- elseif current ~= c then +-- head = insert_node_before(head,stack,copy_node(nsdata[c])) +-- current = c +-- done = true +-- end +-- elseif default and inheritance then +-- if current ~= default then +-- head = insert_node_before(head,stack,copy_node(nsdata[default])) +-- current = default +-- done = true +-- end +-- elseif current > 0 then +-- head = insert_node_before(head,stack,copy_node(nsnone)) +-- current = 0 +-- done = true +-- end +-- -- end of check +-- end +-- end +-- stack = stack.next +-- end +-- return head, done +-- end + local function process(namespace,attribute,head,inheritance,default) -- one attribute - local stack, done = head, false + local stack = head + local done = false + local check = false + local leader = nil while stack do local id = stack.id - -- we need to deal with literals too (reset as well as oval) - -- if id == glyph_code or (id == whatsit_code and stack.subtype == pdfliteral_code) or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code - if id == glyph_code -- or id == disc_code - or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code - local c = has_attribute(stack,attribute) + if id == glyph_code then + check = true + elseif id == glue_code then + leader = stack.leader + if leader then + check = true + end + elseif id == hlist_code or id == vlist_code then + local content = stack.list + if content then + -- begin nested -- + local ok + if nstrigger and stack[nstrigger] then + local outer = stack[attribute] + if outer ~= inheritance then + stack.list, ok = process(namespace,attribute,content,inheritance,outer) + else + stack.list, ok = process(namespace,attribute,content,inheritance,default) + end + else + stack.list, ok = process(namespace,attribute,content,inheritance,default) + end + -- end nested -- + done = done or ok + end + elseif id == rule_code then + check = stack.width ~= 0 + end + -- much faster this way than using a check() and nested() function + if check then + local c = stack[attribute] if c then if default and c == inheritance then if current ~= default then @@ -226,33 +581,31 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr current = c done = true end - -- here ? compare selective - if id == glue_code then --leader - -- same as *list - local content = stack.leader - if content then - local savedcurrent = current - local ci = content.id - if ci == hlist_code or ci == vlist_code then - -- else we reset inside a box unneeded, okay, the downside is - -- that we trigger color in each repeated box, so there is room - -- for improvement here - current = 0 - end - local ok = false - if nstrigger and has_attribute(stack,nstrigger) then - local outer = has_attribute(stack,attribute) - if outer ~= inheritance then - stack.leader, ok = process(namespace,attribute,content,inheritance,outer) - else - stack.leader, ok = process(namespace,attribute,content,inheritance,default) - end + if leader then + local savedcurrent = current + local ci = leader.id + if ci == hlist_code or ci == vlist_code then + -- else we reset inside a box unneeded, okay, the downside is + -- that we trigger color in each repeated box, so there is room + -- for improvement here + current = 0 + end + -- begin nested -- + local ok = false + if nstrigger and stack[nstrigger] then + local outer = stack[attribute] + if outer ~= inheritance then + stack.leader, ok = process(namespace,attribute,leader,inheritance,outer) else - stack.leader, ok = process(namespace,attribute,content,inheritance,default) + stack.leader, ok = process(namespace,attribute,leader,inheritance,default) end - current = savedcurrent - done = done or ok + else + stack.leader, ok = process(namespace,attribute,leader,inheritance,default) end + -- end nested -- + done = done or ok + current = savedcurrent + leader = false end elseif default and inheritance then if current ~= default then @@ -265,22 +618,7 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr current = 0 done = true end - elseif id == hlist_code or id == vlist_code then - local content = stack.list - if content then - local ok = false - if nstrigger and has_attribute(stack,nstrigger) then - local outer = has_attribute(stack,attribute) - if outer ~= inheritance then - stack.list, ok = process(namespace,attribute,content,inheritance,outer) - else - stack.list, ok = process(namespace,attribute,content,inheritance,default) - end - else - stack.list, ok = process(namespace,attribute,content,inheritance,default) - end - done = done or ok - end + check = false end stack = stack.next end @@ -295,88 +633,271 @@ states.process = process -- state changes while the main state stays the same (like two glyphs following -- each other with the same color but different color spaces e.g. \showcolor) +-- local function selective(namespace,attribute,head,inheritance,default) -- two attributes +-- local stack, done = head, false +-- while stack do +-- local id = stack.id +-- -- we need to deal with literals too (reset as well as oval) +-- -- if id == glyph_code or (id == whatsit_code and stack.subtype == pdfliteral_code) or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code +-- if id == glyph_code -- or id == disc_code +-- or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code +-- local c = stack[attribute] +-- if c then +-- if default and c == inheritance then +-- if current ~= default then +-- local data = nsdata[default] +-- head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector])) +-- current = default +-- done = true +-- end +-- else +-- local s = stack[nsselector] +-- if current ~= c or current_selector ~= s then +-- local data = nsdata[c] +-- head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector])) +-- current = c +-- current_selector = s +-- done = true +-- end +-- end +-- elseif default and inheritance then +-- if current ~= default then +-- local data = nsdata[default] +-- head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector])) +-- current = default +-- done = true +-- end +-- elseif current > 0 then +-- head = insert_node_before(head,stack,copy_node(nsnone)) +-- current, current_selector, done = 0, 0, true +-- end +-- if id == glue_code then -- leader +-- -- same as *list +-- local content = stack.leader +-- if content then +-- local savedcurrent = current +-- local ci = content.id +-- if ci == hlist_code or ci == vlist_code then +-- -- else we reset inside a box unneeded, okay, the downside is +-- -- that we trigger color in each repeated box, so there is room +-- -- for improvement here +-- current = 0 +-- end +-- local ok = false +-- if nstrigger and stack[nstrigger] then +-- local outer = stack[attribute] +-- if outer ~= inheritance then +-- stack.leader, ok = selective(namespace,attribute,content,inheritance,outer) +-- else +-- stack.leader, ok = selective(namespace,attribute,content,inheritance,default) +-- end +-- else +-- stack.leader, ok = selective(namespace,attribute,content,inheritance,default) +-- end +-- current = savedcurrent +-- done = done or ok +-- end +-- end +-- elseif id == hlist_code or id == vlist_code then +-- local content = stack.list +-- if content then +-- local ok = false +-- if nstrigger and stack[nstrigger] then +-- local outer = stack[attribute] +-- if outer ~= inheritance then +-- stack.list, ok = selective(namespace,attribute,content,inheritance,outer) +-- else +-- stack.list, ok = selective(namespace,attribute,content,inheritance,default) +-- end +-- else +-- stack.list, ok = selective(namespace,attribute,content,inheritance,default) +-- end +-- done = done or ok +-- end +-- end +-- stack = stack.next +-- end +-- return head, done +-- end + +-- local function selective(namespace,attribute,head,inheritance,default) -- two attributes +-- local stack, done = head, false + +-- local function check() +-- local c = stack[attribute] +-- if c then +-- if default and c == inheritance then +-- if current ~= default then +-- local data = nsdata[default] +-- head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector])) +-- current = default +-- done = true +-- end +-- else +-- local s = stack[nsselector] +-- if current ~= c or current_selector ~= s then +-- local data = nsdata[c] +-- head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector])) +-- current = c +-- current_selector = s +-- done = true +-- end +-- end +-- elseif default and inheritance then +-- if current ~= default then +-- local data = nsdata[default] +-- head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector])) +-- current = default +-- done = true +-- end +-- elseif current > 0 then +-- head = insert_node_before(head,stack,copy_node(nsnone)) +-- current, current_selector, done = 0, 0, true +-- end +-- return c +-- end + +-- local function nested(content) +-- if nstrigger and stack[nstrigger] then +-- local outer = stack[attribute] +-- if outer ~= inheritance then +-- return selective(namespace,attribute,content,inheritance,outer) +-- else +-- return selective(namespace,attribute,content,inheritance,default) +-- end +-- else +-- return selective(namespace,attribute,content,inheritance,default) +-- end +-- end + +-- while stack do +-- local id = stack.id +-- if id == glyph_code then +-- check() +-- elseif id == glue_code then +-- local content = stack.leader +-- if content and check() then +-- -- local savedcurrent = current +-- -- local ci = content.id +-- -- if ci == hlist_code or ci == vlist_code then +-- -- -- else we reset inside a box unneeded, okay, the downside is +-- -- -- that we trigger color in each repeated box, so there is room +-- -- -- for improvement here +-- -- current = 0 +-- -- end + +-- local ok = false +-- stack.leader, ok = nested(content) +-- done = done or ok + +-- -- current = savedcurrent +-- end +-- elseif id == hlist_code or id == vlist_code then +-- local content = stack.list +-- if content then + +-- local ok = false +-- stack.list, ok = nested(content) +-- done = done or ok + +-- end +-- elseif id == rule_code then +-- if stack.width ~= 0 then +-- check() +-- end +-- end +-- stack = stack.next +-- end +-- return head, done +-- end + local function selective(namespace,attribute,head,inheritance,default) -- two attributes - local stack, done = head, false + local stack = head + local done = false + local check = false + local leader = nil while stack do local id = stack.id - -- we need to deal with literals too (reset as well as oval) - -- if id == glyph_code or (id == whatsit_code and stack.subtype == pdfliteral_code) or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code - if id == glyph_code -- or id == disc_code - or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code - local c = has_attribute(stack,attribute) + if id == glyph_code then + check = true + elseif id == glue_code then + leader = stack.leader + if leader then + check = true + end + elseif id == hlist_code or id == vlist_code then + local content = stack.list + if content then + local ok = false + -- begin nested + if nstrigger and stack[nstrigger] then + local outer = stack[attribute] + if outer ~= inheritance then + stack.list, ok = selective(namespace,attribute,content,inheritance,outer) + else + stack.list, ok = selective(namespace,attribute,content,inheritance,default) + end + else + stack.list, ok = selective(namespace,attribute,content,inheritance,default) + end + -- end nested + done = done or ok + end + elseif id == rule_code then + check = stack.width ~= 0 + end + + if check then + local c = stack[attribute] if c then if default and c == inheritance then if current ~= default then local data = nsdata[default] - head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector])) + head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector])) current = default done = true end else - local s = has_attribute(stack,nsselector) + local s = stack[nsselector] if current ~= c or current_selector ~= s then local data = nsdata[c] - head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector])) + head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector])) current = c current_selector = s done = true end end - elseif default and inheritance then - if current ~= default then - local data = nsdata[default] - head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector])) - current = default - done = true - end - elseif current > 0 then - head = insert_node_before(head,stack,copy_node(nsnone)) - current, current_selector, done = 0, 0, true - end - if id == glue_code then -- leader - -- same as *list - local content = stack.leader - if content then - local savedcurrent = current - local ci = content.id - if ci == hlist_code or ci == vlist_code then - -- else we reset inside a box unneeded, okay, the downside is - -- that we trigger color in each repeated box, so there is room - -- for improvement here - current = 0 - end + if leader then local ok = false - if nstrigger and has_attribute(stack,nstrigger) then - local outer = has_attribute(stack,attribute) + -- begin nested + if nstrigger and stack[nstrigger] then + local outer = stack[attribute] if outer ~= inheritance then - stack.leader, ok = selective(namespace,attribute,content,inheritance,outer) + stack.leader, ok = selective(namespace,attribute,leader,inheritance,outer) else - stack.leader, ok = selective(namespace,attribute,content,inheritance,default) + stack.leader, ok = selective(namespace,attribute,leader,inheritance,default) end else - stack.leader, ok = selective(namespace,attribute,content,inheritance,default) + stack.leader, ok = selective(namespace,attribute,leader,inheritance,default) end - current = savedcurrent + -- end nested done = done or ok + leader = false end - end - elseif id == hlist_code or id == vlist_code then - local content = stack.list - if content then - local ok = false - if nstrigger and has_attribute(stack,nstrigger) then - local outer = has_attribute(stack,attribute) - if outer ~= inheritance then - stack.list, ok = selective(namespace,attribute,content,inheritance,outer) - else - stack.list, ok = selective(namespace,attribute,content,inheritance,default) - end - else - stack.list, ok = selective(namespace,attribute,content,inheritance,default) + elseif default and inheritance then + if current ~= default then + local data = nsdata[default] + head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector])) + current = default + done = true end - done = done or ok + elseif current > 0 then + head = insert_node_before(head,stack,copy_node(nsnone)) + current, current_selector, done = 0, 0, true end + check = false end + stack = stack.next end return head, done @@ -387,48 +908,109 @@ states.selective = selective -- Ideally the next one should be merged with the previous but keeping it separate is -- safer. We deal with two situations: efficient boxwise (layoutareas) and mixed layers -- (as used in the stepper). In the stepper we cannot use the box branch as it involves --- paragraph lines and then getsmixed up. A messy business (esp since we want to be +-- paragraph lines and then gets mixed up. A messy business (esp since we want to be -- efficient). +-- +-- Todo: make a better stacker. Keep track (in attribute) about nesting level. Not +-- entirely trivial and a generic solution is nicer (compares to the exporter). + +-- local function stacked(namespace,attribute,head,default) -- no triggering, no inheritance, but list-wise +-- local stack, done = head, false +-- local current, depth = default or 0, 0 +-- +-- local function check() +-- local a = stack[attribute] +-- if a then +-- if current ~= a then +-- head = insert_node_before(head,stack,copy_node(nsdata[a])) +-- depth = depth + 1 +-- current, done = a, true +-- end +-- elseif default > 0 then +-- -- +-- elseif current > 0 then +-- head = insert_node_before(head,stack,copy_node(nsnone)) +-- depth = depth - 1 +-- current, done = 0, true +-- end +-- return a +-- end +-- +-- while stack do +-- local id = stack.id +-- if id == glyph_code then +-- check() +-- elseif id == glue_code then +-- local content = stack.leader +-- if content and check() then +-- local ok = false +-- stack.leader, ok = stacked(namespace,attribute,content,current) +-- done = done or ok +-- end +-- elseif id == hlist_code or id == vlist_code then +-- local content = stack.list +-- if content then +-- -- the problem is that broken lines gets the attribute which can be a later one +-- if nslistwise then +-- local a = stack[attribute] +-- if a and current ~= a and nslistwise[a] then -- viewerlayer / needs checking, see below +-- local p = current +-- current, done = a, true +-- head = insert_node_before(head,stack,copy_node(nsdata[a])) +-- stack.list = stacked(namespace,attribute,content,current) +-- head, stack = insert_node_after(head,stack,copy_node(nsnone)) +-- current = p +-- else +-- local ok = false +-- stack.list, ok = stacked(namespace,attribute,content,current) +-- done = done or ok +-- end +-- else +-- local ok = false +-- stack.list, ok = stacked(namespace,attribute,content,current) +-- done = done or ok +-- end +-- end +-- elseif id == rule_code then +-- if stack.width ~= 0 then +-- check() +-- end +-- end +-- stack = stack.next +-- end +-- while depth > 0 do +-- head = insert_node_after(head,stack,copy_node(nsnone)) +-- depth = depth - 1 +-- end +-- return head, done +-- end local function stacked(namespace,attribute,head,default) -- no triggering, no inheritance, but list-wise - local stack, done = head, false - local current, depth = default or 0, 0 + local stack = head + local done = false + local current = default or 0 + local depth = 0 + local check = false + local leader = false while stack do local id = stack.id - if id == glyph_code or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code - local c = has_attribute(stack,attribute) - if c then - if current ~= c then - head = insert_node_before(head,stack,copy_node(nsdata[c])) - depth = depth + 1 - current, done = c, true - end - if id == glue_code then - local content = stack.leader - if content then -- unchecked - local ok = false - stack.leader, ok = stacked(namespace,attribute,content,current) - done = done or ok - end - end ---~ elseif default then - elseif default > 0 then - -- - elseif current > 0 then - head = insert_node_before(head,stack,copy_node(nsnone)) - depth = depth - 1 - current, done = 0, true + if id == glyph_code then + check = true + elseif id == glue_code then + leader = stack.leader + if leader then + check = true end elseif id == hlist_code or id == vlist_code then local content = stack.list if content then -- the problem is that broken lines gets the attribute which can be a later one if nslistwise then - local c = has_attribute(stack,attribute) - if c and current ~= c and nslistwise[c] then -- viewerlayer + local a = stack[attribute] + if a and current ~= a and nslistwise[a] then -- viewerlayer / needs checking, see below local p = current - current, done = c, true - head = insert_node_before(head,stack,copy_node(nsdata[c])) + current, done = a, true + head = insert_node_before(head,stack,copy_node(nsdata[a])) stack.list = stacked(namespace,attribute,content,current) head, stack = insert_node_after(head,stack,copy_node(nsnone)) current = p @@ -443,18 +1025,196 @@ local function stacked(namespace,attribute,head,default) -- no triggering, no in done = done or ok end end + elseif id == rule_code then + check = stack.width ~= 0 end + + if check then + local a = stack[attribute] + if a then + if current ~= a then + head = insert_node_before(head,stack,copy_node(nsdata[a])) + depth = depth + 1 + current, done = a, true + end + if leader then + local ok = false + stack.leader, ok = stacked(namespace,attribute,content,current) + done = done or ok + leader = false + end + elseif default > 0 then + -- + elseif current > 0 then + head = insert_node_before(head,stack,copy_node(nsnone)) + depth = depth - 1 + current, done = 0, true + end + check = false + end + stack = stack.next end while depth > 0 do head = insert_node_after(head,stack,copy_node(nsnone)) - depth = depth -1 + depth = depth - 1 end return head, done end states.stacked = stacked +-- experimental + +-- local function stacker(namespace,attribute,head,default) -- no triggering, no inheritance, but list-wise +-- nsbegin() +-- local current, previous, done, okay = head, head, false, false +-- local attrib = default or unsetvalue +-- +-- local function check() +-- local a = current[attribute] or unsetvalue +-- if a ~= attrib then +-- local n = nsstep(a) +-- if n then +-- -- !!!! TEST CODE !!!! +-- -- head = insert_node_before(head,current,copy_node(nsdata[tonumber(n)])) -- a +-- head = insert_node_before(head,current,n) -- a +-- end +-- attrib, done, okay = a, true, true +-- end +-- return a +-- end +-- +-- while current do +-- local id = current.id +-- if id == glyph_code then +-- check() +-- elseif id == glue_code then +-- local content = current.leader +-- if content and check() then +-- -- tricky as a leader has to be a list so we cannot inject before +-- local _, ok = stacker(namespace,attribute,content,attrib) +-- done = done or ok +-- end +-- elseif id == hlist_code or id == vlist_code then +-- local content = current.list +-- if not content then +-- -- skip +-- elseif nslistwise then +-- local a = current[attribute] +-- if a and attrib ~= a and nslistwise[a] then -- viewerlayer +-- done = true +-- head = insert_node_before(head,current,copy_node(nsdata[a])) +-- current.list = stacker(namespace,attribute,content,a) +-- head, current = insert_node_after(head,current,copy_node(nsnone)) +-- else +-- local ok = false +-- current.list, ok = stacker(namespace,attribute,content,attrib) +-- done = done or ok +-- end +-- else +-- local ok = false +-- current.list, ok = stacker(namespace,attribute,content,default) +-- done = done or ok +-- end +-- elseif id == rule_code then +-- if current.width ~= 0 then +-- check() +-- end +-- end +-- previous = current +-- current = current.next +-- end +-- if okay then +-- local n = nsend() +-- if n then +-- -- !!!! TEST CODE !!!! +-- -- head = insert_node_after(head,previous,copy_node(nsdata[tostring(n)])) +-- head = insert_node_after(head,previous,n) +-- end +-- end +-- return head, done +-- end + +local function stacker(namespace,attribute,head,default) -- no triggering, no inheritance, but list-wise + nsbegin() + local current = head + local previous = head + local done = false + local okay = false + local attrib = default or unsetvalue + local check = false + local leader = false + while current do + local id = current.id + if id == glyph_code then + check = true + elseif id == glue_code then + leader = current.leader + if leader then + check = true + end + elseif id == hlist_code or id == vlist_code then + local content = current.list + if not content then + -- skip + elseif nslistwise then + local a = current[attribute] + if a and attrib ~= a and nslistwise[a] then -- viewerlayer + done = true + head = insert_node_before(head,current,copy_node(nsdata[a])) + current.list = stacker(namespace,attribute,content,a) + head, current = insert_node_after(head,current,copy_node(nsnone)) + else + local ok = false + current.list, ok = stacker(namespace,attribute,content,attrib) + done = done or ok + end + else + local ok = false + current.list, ok = stacker(namespace,attribute,content,default) + done = done or ok + end + elseif id == rule_code then + check = current.width ~= 0 + end + + if check then + local a = current[attribute] or unsetvalue + if a ~= attrib then + local n = nsstep(a) + if n then + -- !!!! TEST CODE !!!! + -- head = insert_node_before(head,current,copy_node(nsdata[tonumber(n)])) -- a + head = insert_node_before(head,current,n) -- a + end + attrib, done, okay = a, true, true + if leader then + -- tricky as a leader has to be a list so we cannot inject before + local _, ok = stacker(namespace,attribute,leader,attrib) + done = done or ok + leader = false + end + end + check = false + end + + previous = current + current = current.next + end + if okay then + local n = nsend() + if n then + -- !!!! TEST CODE !!!! + -- head = insert_node_after(head,previous,copy_node(nsdata[tostring(n)])) + head = insert_node_after(head,previous,n) + end + end + return head, done +end + +states.stacker = stacker + -- -- -- statistics.register("attribute processing time", function() |