diff options
Diffstat (limited to 'tex/context/base/node-fin.lua')
| -rw-r--r-- | tex/context/base/node-fin.lua | 302 | 
1 files changed, 125 insertions, 177 deletions
| diff --git a/tex/context/base/node-fin.lua b/tex/context/base/node-fin.lua index 8476b47a6..63a5ef83e 100644 --- a/tex/context/base/node-fin.lua +++ b/tex/context/base/node-fin.lua @@ -8,54 +8,36 @@ if not modules then modules = { } end modules ['node-fin'] = {  -- this module is being reconstructed  -- local functions, only slightly slower --- --- leaders are also triggers  local next, type, format = next, type, string.format  local attributes, nodes, node = attributes, nodes, node -local nuts               = nodes.nuts -local tonode             = nuts.tonode -local tonut              = nuts.tonut - -local getfield           = nuts.getfield -local getnext            = nuts.getnext -local getprev            = nuts.getprev -local getid              = nuts.getid -local getlist            = nuts.getlist -local getleader          = nuts.getleader -local getattr            = nuts.getattr - -local setfield           = nuts.setfield -local setattr            = nuts.setattr - -local copy_node          = nuts.copy -local insert_node_before = nuts.insert_before -local insert_node_after  = nuts.insert_after +local copy_node       = node.copy +local find_tail       = node.slide -local nodecodes          = nodes.nodecodes -local whatcodes          = nodes.whatcodes +local nodecodes       = nodes.nodecodes +local whatcodes       = nodes.whatcodes -local glyph_code         = nodecodes.glyph -local disc_code          = nodecodes.disc -local glue_code          = nodecodes.glue -local rule_code          = nodecodes.rule -local whatsit_code       = nodecodes.whatsit -local hlist_code         = nodecodes.hlist -local vlist_code         = nodecodes.vlist +local glyph_code      = nodecodes.glyph +local disc_code       = nodecodes.disc +local glue_code       = nodecodes.glue +local rule_code       = nodecodes.rule +local whatsit_code    = nodecodes.whatsit +local hlist_code      = nodecodes.hlist +local vlist_code      = nodecodes.vlist -local pdfliteral_code    = whatcodes.pdfliteral +local pdfliteral_code = whatcodes.pdfliteral -local states             = attributes.states -local numbers            = attributes.numbers -local a_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 loadstripped       = utilities.lua.loadstripped -local unsetvalue         = attributes.unsetvalue +local starttiming     = statistics.starttiming +local stoptiming      = statistics.stoptiming +local loadstripped    = utilities.lua.loadstripped +local unsetvalue      = attributes.unsetvalue  -- these two will be like trackers @@ -120,14 +102,11 @@ function nodes.installattributehandler(plugin)      return loadstripped(template)()  end --- for the moment: - -local function copied(n) -    return copy_node(tonut(n)) -end -  -- the injectors +local insert_node_before = node.insert_before +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 @@ -153,25 +132,23 @@ end  function states.finalize(namespace,attribute,head) -- is this one ok?      if current > 0 and nsnone then -        head = tonut(head) -        local id = getid(head) +        local id = head.id          if id == hlist_code or id == vlist_code then -            local list = getlist(head) +            local list = head.list              if list then -                list = insert_node_before(list,list,copied(nsnone)) -- two return values -                setfield(head,"list",list) +                head.list = insert_node_before(list,list,copy_node(nsnone))              end          else -            head = insert_node_before(head,head,copied(nsnone)) +            head = insert_node_before(head,head,copy_node(nsnone))          end -        return tonode(head), true, true +        return head, true, true      end      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 getsubtype(stack) == pdfliteral_code) or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then +-- 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  = head @@ -179,57 +156,53 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr      local check  = false      local leader = nil      while stack do -        local id = getid(stack) +        local id = stack.id          if id == glyph_code then              check = true          elseif id == glue_code then -            leader = getleader(stack) +            leader = stack.leader              if leader then                  check = true              end          elseif id == hlist_code or id == vlist_code then -            local content = getlist(stack) +            local content = stack.list              if content then                  -- begin nested -- -                if nstrigger and getattr(stack,nstrigger) then -                    local outer = getattr(stack,attribute) +                local ok +                if nstrigger and stack[nstrigger] then +                    local outer = stack[attribute]                      if outer ~= inheritance then -                        local list, ok = process(namespace,attribute,content,inheritance,outer) -                        setfield(stack,"list",list) -                        done = done or ok +                        stack.list, ok = process(namespace,attribute,content,inheritance,outer)                      else -                        local list, ok = process(namespace,attribute,content,inheritance,default) -                        setfield(stack,"list",list) -                        done = done or ok +                        stack.list, ok = process(namespace,attribute,content,inheritance,default)                      end                  else -                    local list, ok = process(namespace,attribute,content,inheritance,default) -                    setfield(stack,"list",list) -                    done = done or ok +                    stack.list, ok = process(namespace,attribute,content,inheritance,default)                  end                  -- end nested -- +                done = done or ok              end          elseif id == rule_code then -            check = getfield(stack,"width") ~= 0 +            check = stack.width ~= 0          end          -- much faster this way than using a check() and nested() function          if check then -            local c = getattr(stack,attribute) +            local c = stack[attribute]              if c then                  if default and c == inheritance then                      if current ~= default then -                        head = insert_node_before(head,stack,copied(nsdata[default])) +                        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,copied(nsdata[c])) +                    head = insert_node_before(head,stack,copy_node(nsdata[c]))                      current = c                      done = true                  end                  if leader then                      local savedcurrent = current -                    local ci = getid(leader) +                    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 @@ -237,48 +210,41 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr                          current = 0                      end                      -- begin nested -- -                    if nstrigger and getattr(stack,nstrigger) then -                        local outer = getattr(stack,attribute) +                    local ok = false +                    if nstrigger and stack[nstrigger] then +                        local outer = stack[attribute]                          if outer ~= inheritance then -                            local list, ok = process(namespace,attribute,leader,inheritance,outer) -                            setfield(stack,"leader",list) -                            done = done or ok +                            stack.leader, ok = process(namespace,attribute,leader,inheritance,outer)                          else -                            local list, ok = process(namespace,attribute,leader,inheritance,default) -                            setfield(stack,"leader",list) -                            done = done or ok +                            stack.leader, ok = process(namespace,attribute,leader,inheritance,default)                          end                      else -                        local list, ok = process(namespace,attribute,leader,inheritance,default) -                        setfield(stack,"leader",list) -                        done = done or ok +                        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 -                    head = insert_node_before(head,stack,copied(nsdata[default])) +                    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,copied(nsnone)) +                head = insert_node_before(head,stack,copy_node(nsnone))                  current = 0                  done = true              end              check = false          end -        stack = getnext(stack) +        stack = stack.next      end      return head, done  end -states.process = function(namespace,attribute,head,default) -    local head, done = process(namespace,attribute,tonut(head),default) -    return tonode(head), done -end +states.process = process  -- we can force a selector, e.g. document wide color spaces, saves a little  -- watch out, we need to check both the selector state (like colorspace) and @@ -292,103 +258,93 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at      local check  = false      local leader = nil      while stack do -        local id = getid(stack) +        local id = stack.id          if id == glyph_code then              check = true          elseif id == glue_code then -            leader = getleader(stack) +            leader = stack.leader              if leader then                  check = true              end          elseif id == hlist_code or id == vlist_code then -            local content = getlist(stack) +            local content = stack.list              if content then +                local ok = false                  -- begin nested -                if nstrigger and getattr(stack,nstrigger) then -                    local outer = getattr(stack,attribute) +                if nstrigger and stack[nstrigger] then +                    local outer = stack[attribute]                      if outer ~= inheritance then -                        local list, ok = selective(namespace,attribute,content,inheritance,outer) -                        setfield(stack,"list",list) -                        done = done or ok +                        stack.list, ok = selective(namespace,attribute,content,inheritance,outer)                      else -                        local list, ok = selective(namespace,attribute,content,inheritance,default) -                        setfield(stack,"list",list) -                        done = done or ok +                        stack.list, ok = selective(namespace,attribute,content,inheritance,default)                      end                  else -                    local list, ok = selective(namespace,attribute,content,inheritance,default) -                    setfield(stack,"list",list) -                    done = done or ok +                    stack.list, ok = selective(namespace,attribute,content,inheritance,default)                  end                  -- end nested +                done = done or ok              end          elseif id == rule_code then -            check = getfield(stack,"width") ~= 0 +            check = stack.width ~= 0          end          if check then -            local c = getattr(stack,attribute) +            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,copied(data[nsforced or getattr(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 = getattr(stack,nsselector) +                    local s = stack[nsselector]                      if current ~= c or current_selector ~= s then                          local data = nsdata[c] -                        head = insert_node_before(head,stack,copied(data[nsforced or getattr(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                  if leader then +                    local ok = false                      -- begin nested -                    if nstrigger and getattr(stack,nstrigger) then -                        local outer = getatribute(stack,attribute) +                    if nstrigger and stack[nstrigger] then +                        local outer = stack[attribute]                          if outer ~= inheritance then -                            local list, ok = selective(namespace,attribute,leader,inheritance,outer) -                            setfield(stack,"leader",list) -                            done = done or ok +                            stack.leader, ok = selective(namespace,attribute,leader,inheritance,outer)                          else -                            local list, ok = selective(namespace,attribute,leader,inheritance,default) -                            setfield(stack,"leader",list) -                            done = done or ok +                            stack.leader, ok = selective(namespace,attribute,leader,inheritance,default)                          end                      else -                        local list, ok = selective(namespace,attribute,leader,inheritance,default) -                        setfield(stack,"leader",list) -                        done = done or ok +                        stack.leader, ok = selective(namespace,attribute,leader,inheritance,default)                      end                      -- end nested -					leader = false +                    done = done or ok +                    leader = false                  end              elseif default and inheritance then                  if current ~= default then                      local data = nsdata[default] -                    head = insert_node_before(head,stack,copied(data[nsforced or getattr(stack,nsselector) or nsselector])) +                    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,copied(nsnone)) +                head = insert_node_before(head,stack,copy_node(nsnone))                  current, current_selector, done = 0, 0, true              end              check = false          end -        stack = getnext(stack) + +        stack = stack.next      end      return head, done  end -states.selective = function(namespace,attribute,head,default) -    local head, done = selective(namespace,attribute,tonut(head),default) -    return tonode(head), done -end +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 @@ -407,80 +363,76 @@ local function stacked(namespace,attribute,head,default) -- no triggering, no in      local check   = false      local leader  = false      while stack do -        local id = getid(stack) +        local id = stack.id          if id == glyph_code then              check = true          elseif id == glue_code then -            leader = getleader(stack) +            leader = stack.leader              if leader then                  check = true              end          elseif id == hlist_code or id == vlist_code then -            local content = getlist(stack) +            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 = getattr(stack,attribute) +                    local a = stack[attribute]                      if a and current ~= a and nslistwise[a] then -- viewerlayer / needs checking, see below                          local p = current -                        current = a -                        head = insert_node_before(head,stack,copied(nsdata[a])) -                        local list = stacked(namespace,attribute,content,current) -- two return values -                        setfield(stack,"list",list) -                        done = true -                        head, stack = insert_node_after(head,stack,copied(nsnone)) +                        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 list, ok = stacked(namespace,attribute,content,current) -                        setfield(stack,"list",list) -- only if ok +                        local ok = false +                        stack.list, ok = stacked(namespace,attribute,content,current)                          done = done or ok                      end                  else -                    local list, ok = stacked(namespace,attribute,content,current) -                    setfield(stack,"list",list) -- only if ok +                    local ok = false +                    stack.list, ok = stacked(namespace,attribute,content,current)                      done = done or ok                  end              end          elseif id == rule_code then -            check = getfield(stack,"width") ~= 0 +            check = stack.width ~= 0          end          if check then -            local a = getattr(stack,attribute) +            local a = stack[attribute]              if a then                  if current ~= a then -                    head = insert_node_before(head,stack,copied(nsdata[a])) +                    head = insert_node_before(head,stack,copy_node(nsdata[a]))                      depth = depth + 1                      current, done = a, true                  end                  if leader then -                    local list, ok = stacked(namespace,attribute,content,current) -                    setfield(stack,"leader",list) -- only if ok +                    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,copied(nsnone)) +                head = insert_node_before(head,stack,copy_node(nsnone))                  depth = depth - 1                  current, done = 0, true              end              check = false          end -        stack = getnext(stack) + +        stack = stack.next      end      while depth > 0 do -        head = insert_node_after(head,stack,copied(nsnone)) +        head = insert_node_after(head,stack,copy_node(nsnone))          depth = depth - 1      end      return head, done  end -states.stacked = function(namespace,attribute,head,default) -    local head, done = stacked(namespace,attribute,tonut(head),default) -    return tonode(head), done -end +states.stacked = stacked  -- experimental @@ -494,53 +446,52 @@ local function stacker(namespace,attribute,head,default) -- no triggering, no in      local check    = false      local leader   = false      while current do -        local id = getid(current) +        local id = current.id          if id == glyph_code then              check = true          elseif id == glue_code then -            leader = getleader(current) +            leader = current.leader              if leader then                  check = true              end          elseif id == hlist_code or id == vlist_code then -            local content = getlist(current) +            local content = current.list              if not content then                  -- skip              elseif nslistwise then -                local a = getattr(current,attribute) +                local a = current[attribute]                  if a and attrib ~= a and nslistwise[a] then -- viewerlayer -                    head = insert_node_before(head,current,copied(nsdata[a])) -                    local list = stacker(namespace,attribute,content,a) -                    setfield(current,"list",list)                      done = true -                    head, current = insert_node_after(head,current,copied(nsnone)) +                    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 list, ok = stacker(namespace,attribute,content,attrib) -                    setfield(current,"list",list) +                    local ok = false +                    current.list, ok = stacker(namespace,attribute,content,attrib)                      done = done or ok                  end              else -                local list, ok = stacker(namespace,attribute,content,default) -                setfield(current,"list",list) +                local ok = false +                current.list, ok = stacker(namespace,attribute,content,default)                  done = done or ok              end          elseif id == rule_code then -            check = getfield(current,"width") ~= 0 +            check = current.width ~= 0          end          if check then -            local a = getattr(current,attribute) or unsetvalue +            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,copied(nsdata[tonumber(n)])) -- a -                    head = insert_node_before(head,current,tonut(n)) -- a +                 -- 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 list, ok = stacker(namespace,attribute,leader,attrib) +                    local _, ok = stacker(namespace,attribute,leader,attrib)                      done = done or ok                      leader = false                  end @@ -549,23 +500,20 @@ local function stacker(namespace,attribute,head,default) -- no triggering, no in          end          previous = current -        current = getnext(current) +        current = current.next      end      if okay then          local n = nsend()          if n then               -- !!!! TEST CODE !!!! -         -- head = insert_node_after(head,previous,copied(nsdata[tostring(n)])) -            head = insert_node_after(head,previous,tonut(n)) +         -- 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 = function(namespace,attribute,head,default) -    local head, done = stacker(namespace,attribute,tonut(head),default) -    return tonode(head), done -end +states.stacker = stacker  -- -- -- | 
