summaryrefslogtreecommitdiff
path: root/tex/context/base/node-aux.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/node-aux.lua')
-rw-r--r--tex/context/base/node-aux.lua778
1 files changed, 389 insertions, 389 deletions
diff --git a/tex/context/base/node-aux.lua b/tex/context/base/node-aux.lua
index 21737a43b..e3fc7ad6f 100644
--- a/tex/context/base/node-aux.lua
+++ b/tex/context/base/node-aux.lua
@@ -1,389 +1,389 @@
-if not modules then modules = { } end modules ['node-aux'] = {
- version = 1.001,
- comment = "companion to node-ini.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- todo: n1 .. n2 : __concat metatable
-
-local type, tostring = type, tostring
-
-local nodes, node = nodes, node
-
-local utfvalues = utf.values
-
-local nodecodes = nodes.nodecodes
-
-local glyph_code = nodecodes.glyph
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
-local attributelist_code = nodecodes.attributelist -- temporary
-local math_code = nodecodes.math
-
-local nodepool = nodes.pool
-
-local new_glue = nodepool.glue
-local new_glyph = nodepool.glyph
-
-local traverse_nodes = node.traverse
-local traverse_id = node.traverse_id
-local free_node = node.free
-local hpack_nodes = node.hpack
-local unset_attribute = node.unset_attribute
-local first_glyph = node.first_glyph or node.first_character
-local copy_node = node.copy
-local copy_node_list = node.copy_list
-local slide_nodes = node.slide
-local insert_node_after = node.insert_after
-local isnode = node.is_node
-
-local unsetvalue = attributes.unsetvalue
-
-local current_font = font.current
-
-local texbox = tex.box
-
-local report_error = logs.reporter("node-aux:error")
-
-function nodes.repackhlist(list,...)
---~ nodes.showsimplelist(list)
- local temp, b = hpack_nodes(list,...)
- list = temp.list
- temp.list = nil
- free_node(temp)
- return list, b
-end
-
-local function set_attributes(head,attr,value)
- for n in traverse_nodes(head) do
- n[attr] = value
- local id = n.id
- if id == hlist_node or id == vlist_node then
- set_attributes(n.list,attr,value)
- end
- end
-end
-
-local function set_unset_attributes(head,attr,value)
- for n in traverse_nodes(head) do
- if not n[attr] then
- n[attr] = value
- end
- local id = n.id
- if id == hlist_code or id == vlist_code then
- set_unset_attributes(n.list,attr,value)
- end
- end
-end
-
-local function unset_attributes(head,attr)
- for n in traverse_nodes(head) do
- n[attr] = unsetvalue
- local id = n.id
- if id == hlist_code or id == vlist_code then
- unset_attributes(n.list,attr)
- end
- end
-end
-
-nodes.setattribute = node.set_attribute
-nodes.getattribute = node.has_attribute
-nodes.unsetattribute = node.unset_attribute
-nodes.has_attribute = node.has_attribute
-
-nodes.firstglyph = first_glyph
-nodes.setattributes = set_attributes
-nodes.setunsetattributes = set_unset_attributes
-nodes.unsetattributes = unset_attributes
-
--- function nodes.is_skipable(a,id) -- skipable nodes at the margins during character protrusion
--- return (
--- id ~= glyph_node
--- or id == ins_node
--- or id == mark_node
--- or id == adjust_node
--- or id == penalty_node
--- or (id == glue_node and a.spec.writable)
--- or (id == disc_node and a.pre == nil and a.post == nil and a.replace == nil)
--- or (id == math_node and a.surround == 0)
--- or (id == kern_node and (a.kern == 0 or a.subtype == NORMAL))
--- or (id == hlist_node and a.width == 0 and a.height == 0 and a.depth == 0 and a.list == nil)
--- or (id == whatsit_node and a.subtype ~= pdf_refximage_node and a.subtype ~= pdf_refxform_node)
--- )
--- end
-
--- history:
---
---
--- local function glyph_width(a)
--- local ch = chardata[a.font][a.char]
--- return (ch and ch.width) or 0
--- end
---
--- local function glyph_total(a)
--- local ch = chardata[a.font][a.char]
--- return (ch and (ch.height+ch.depth)) or 0
--- end
---
--- local function non_discardable(a) -- inline
--- return a.id < math_node -- brrrr
--- end
---
--- local function calculate_badness(t,s)
--- if t == 0 then
--- return 0
--- elseif s <= 0 then
--- return INF_BAD
--- else
--- local r
--- if t <= 7230584 then
--- r = t * 297 / s
--- elseif s >= 1663497 then
--- r = t / floor(s / 297)
--- else
--- r = t
--- end
--- r = floor(r)
--- if r > 1290 then
--- return INF_BAD
--- else
--- return floor((r * r * r + 0x20000) / 0x40000) -- 0400000 / 01000000
--- end
--- end
--- end
---
--- left-overs
---
--- local function round_xn_over_d(x, n, d)
--- local positive -- was x >= 0
--- if x >= 0 then
--- positive = true
--- else
--- x = -x
--- positive = false
--- end
--- local t = floor(x % 0x8000) * n -- 0100000
--- local f = floor(t / 0x8000) -- 0100000
--- local u = floor(x / 0x8000) * n + f -- 0100000
--- local v = floor(u % d) * 0x8000 + f -- 0100000
--- if floor(u / d) >= 0x8000 then -- 0100000
--- report_parbuilders('arith_error')
--- else
--- u = 0x8000 * floor(u / d) + floor(v / d) -- 0100000
--- end
--- v = floor(v % d)
--- if 2*v >= d then
--- u = u + 1
--- end
--- if positive then
--- return u
--- else
--- return -u
--- end
--- end
-
-function nodes.firstcharacter(n,untagged) -- tagged == subtype > 255
- if untagged then
- return first_glyph(n)
- else
- for g in traverse_id(glyph_code,n) do
- return g
- end
- end
-end
-
-function nodes.firstcharinbox(n)
- local l = texbox[n].list
- if l then
- for g in traverse_id(glyph_code,l) do
- return g.char
- end
- end
- return 0
-end
-
-if not node.end_of_math then
- function node.end_of_math(n)
- for n in traverse_id(math_code,n.next) do
- return n
- end
- end
-end
-
-nodes.endofmath = node.end_of_math
-
--- local function firstline(n)
--- while n do
--- local id = n.id
--- if id == hlist_code then
--- if n.subtype == line_code then
--- return n
--- else
--- return firstline(n.list)
--- end
--- elseif id == vlist_code then
--- return firstline(n.list)
--- end
--- n = n.next
--- end
--- end
-
--- nodes.firstline = firstline
-
--- this depends on fonts, so we have a funny dependency ... will be
--- sorted out .. we could make tonodes a plugin into this
-
-local function tonodes(str,fnt,attr) -- (str,template_glyph) -- moved from blob-ini
- if not str or str == "" then
- return
- end
- local head, tail, space, fnt, template = nil, nil, nil, nil, nil
- if not fnt then
- fnt = current_font()
- elseif type(fnt) ~= "number" and fnt.id == "glyph" then
- fnt, template = nil, fnt
- -- else
- -- already a number
- end
- for s in utfvalues(str) do
- local n
- if s == 32 then
- if space then
- n = copy_node(space)
- elseif fonts then -- depedency
- local parameters = fonts.hashes.identifiers[fnt].parameters
- space = new_glue(parameters.space,parameters.space_stretch,parameters.space_shrink)
- n = space
- end
- elseif template then
- n = copy_node(template)
- n.char = s
- else
- n = new_glyph(fnt,s)
- end
- if attr then -- normally false when template
- n.attr = copy_node_list(attr)
- end
- if head then
- insert_node_after(head,tail,n)
- else
- head = n
- end
- tail = n
- end
- return head, tail
-end
-
-nodes.tonodes = tonodes
-
-local function link(list,currentfont,currentattr,head,tail)
- for i=1,#list do
- local n = list[i]
- if n then
- local tn = isnode(n)
- if not tn then
- local tn = type(n)
- if tn == "number" then
- if not currentfont then
- currentfont = current_font()
- end
- local h, t = tonodes(tostring(n),currentfont,currentattr)
- if not h then
- -- skip
- elseif not head then
- head, tail = h, t
- else
- tail.next, h.prev, tail = h, t, t
- end
- elseif tn == "string" then
- if #tn > 0 then
- if not currentfont then
- currentfont = current_font()
- end
- local h, t = tonodes(n,currentfont,currentattr)
- if not h then
- -- skip
- elseif not head then
- head, tail = h, t
- else
- tail.next, h.prev, tail = h, t, t
- end
- end
- elseif tn == "table" then
- if #tn > 0 then
- if not currentfont then
- currentfont = current_font()
- end
- head, tail = link(n,currentfont,currentattr,head,tail)
- end
- end
- elseif not head then
- head = n
- if n.next then
- tail = slide_nodes(n)
- else
- tail = n
- end
- elseif n.id == attributelist_code then
- -- weird case
- report_error("weird node type in list at index %s:",i)
- for i=1,#list do
- local l = list[i]
- report_error("%3i: %s %S",i,l.id == attributelist_code and "!" or ">",l)
- end
- os.exit()
- else
- tail.next = n
- n.prev = tail
- if n.next then
- tail = slide_nodes(n)
- else
- tail = n
- end
- end
- else
- -- permitting nil is convenient
- end
- end
- return head, tail
-end
-
-nodes.link = link
-
-local function locate(start,wantedid,wantedsubtype)
- for n in traverse_nodes(start) do
- local id = n.id
- if id == wantedid then
- if not wantedsubtype or n.subtype == wantedsubtype then
- return n
- end
- elseif id == hlist_code or id == vlist_code then
- local found = locate(n.list,wantedid,wantedsubtype)
- if found then
- return found
- end
- end
- end
-end
-
-nodes.locate = locate
-
-function nodes.concat(list)
- local head, tail
- for i=1,#list do
- local li = list[i]
- if not li then
- -- skip
- elseif head then
- tail.next = li
- li.prev = tail
- tail = li.next and slide_nodes(li) or li
- else
- head = li
- tail = li.next and slide_nodes(li) or li
- end
- end
- return head, tail
-end
+if not modules then modules = { } end modules ['node-aux'] = {
+ version = 1.001,
+ comment = "companion to node-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: n1 .. n2 : __concat metatable
+
+local type, tostring = type, tostring
+
+local nodes, node = nodes, node
+
+local utfvalues = utf.values
+
+local nodecodes = nodes.nodecodes
+
+local glyph_code = nodecodes.glyph
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local attributelist_code = nodecodes.attributelist -- temporary
+local math_code = nodecodes.math
+
+local nodepool = nodes.pool
+
+local new_glue = nodepool.glue
+local new_glyph = nodepool.glyph
+
+local traverse_nodes = node.traverse
+local traverse_id = node.traverse_id
+local free_node = node.free
+local hpack_nodes = node.hpack
+local unset_attribute = node.unset_attribute
+local first_glyph = node.first_glyph or node.first_character
+local copy_node = node.copy
+local copy_node_list = node.copy_list
+local slide_nodes = node.slide
+local insert_node_after = node.insert_after
+local isnode = node.is_node
+
+local unsetvalue = attributes.unsetvalue
+
+local current_font = font.current
+
+local texbox = tex.box
+
+local report_error = logs.reporter("node-aux:error")
+
+function nodes.repackhlist(list,...)
+--~ nodes.showsimplelist(list)
+ local temp, b = hpack_nodes(list,...)
+ list = temp.list
+ temp.list = nil
+ free_node(temp)
+ return list, b
+end
+
+local function set_attributes(head,attr,value)
+ for n in traverse_nodes(head) do
+ n[attr] = value
+ local id = n.id
+ if id == hlist_node or id == vlist_node then
+ set_attributes(n.list,attr,value)
+ end
+ end
+end
+
+local function set_unset_attributes(head,attr,value)
+ for n in traverse_nodes(head) do
+ if not n[attr] then
+ n[attr] = value
+ end
+ local id = n.id
+ if id == hlist_code or id == vlist_code then
+ set_unset_attributes(n.list,attr,value)
+ end
+ end
+end
+
+local function unset_attributes(head,attr)
+ for n in traverse_nodes(head) do
+ n[attr] = unsetvalue
+ local id = n.id
+ if id == hlist_code or id == vlist_code then
+ unset_attributes(n.list,attr)
+ end
+ end
+end
+
+nodes.setattribute = node.set_attribute
+nodes.getattribute = node.has_attribute
+nodes.unsetattribute = node.unset_attribute
+nodes.has_attribute = node.has_attribute
+
+nodes.firstglyph = first_glyph
+nodes.setattributes = set_attributes
+nodes.setunsetattributes = set_unset_attributes
+nodes.unsetattributes = unset_attributes
+
+-- function nodes.is_skipable(a,id) -- skipable nodes at the margins during character protrusion
+-- return (
+-- id ~= glyph_node
+-- or id == ins_node
+-- or id == mark_node
+-- or id == adjust_node
+-- or id == penalty_node
+-- or (id == glue_node and a.spec.writable)
+-- or (id == disc_node and a.pre == nil and a.post == nil and a.replace == nil)
+-- or (id == math_node and a.surround == 0)
+-- or (id == kern_node and (a.kern == 0 or a.subtype == NORMAL))
+-- or (id == hlist_node and a.width == 0 and a.height == 0 and a.depth == 0 and a.list == nil)
+-- or (id == whatsit_node and a.subtype ~= pdf_refximage_node and a.subtype ~= pdf_refxform_node)
+-- )
+-- end
+
+-- history:
+--
+--
+-- local function glyph_width(a)
+-- local ch = chardata[a.font][a.char]
+-- return (ch and ch.width) or 0
+-- end
+--
+-- local function glyph_total(a)
+-- local ch = chardata[a.font][a.char]
+-- return (ch and (ch.height+ch.depth)) or 0
+-- end
+--
+-- local function non_discardable(a) -- inline
+-- return a.id < math_node -- brrrr
+-- end
+--
+-- local function calculate_badness(t,s)
+-- if t == 0 then
+-- return 0
+-- elseif s <= 0 then
+-- return INF_BAD
+-- else
+-- local r
+-- if t <= 7230584 then
+-- r = t * 297 / s
+-- elseif s >= 1663497 then
+-- r = t / floor(s / 297)
+-- else
+-- r = t
+-- end
+-- r = floor(r)
+-- if r > 1290 then
+-- return INF_BAD
+-- else
+-- return floor((r * r * r + 0x20000) / 0x40000) -- 0400000 / 01000000
+-- end
+-- end
+-- end
+--
+-- left-overs
+--
+-- local function round_xn_over_d(x, n, d)
+-- local positive -- was x >= 0
+-- if x >= 0 then
+-- positive = true
+-- else
+-- x = -x
+-- positive = false
+-- end
+-- local t = floor(x % 0x8000) * n -- 0100000
+-- local f = floor(t / 0x8000) -- 0100000
+-- local u = floor(x / 0x8000) * n + f -- 0100000
+-- local v = floor(u % d) * 0x8000 + f -- 0100000
+-- if floor(u / d) >= 0x8000 then -- 0100000
+-- report_parbuilders('arith_error')
+-- else
+-- u = 0x8000 * floor(u / d) + floor(v / d) -- 0100000
+-- end
+-- v = floor(v % d)
+-- if 2*v >= d then
+-- u = u + 1
+-- end
+-- if positive then
+-- return u
+-- else
+-- return -u
+-- end
+-- end
+
+function nodes.firstcharacter(n,untagged) -- tagged == subtype > 255
+ if untagged then
+ return first_glyph(n)
+ else
+ for g in traverse_id(glyph_code,n) do
+ return g
+ end
+ end
+end
+
+function nodes.firstcharinbox(n)
+ local l = texbox[n].list
+ if l then
+ for g in traverse_id(glyph_code,l) do
+ return g.char
+ end
+ end
+ return 0
+end
+
+if not node.end_of_math then
+ function node.end_of_math(n)
+ for n in traverse_id(math_code,n.next) do
+ return n
+ end
+ end
+end
+
+nodes.endofmath = node.end_of_math
+
+-- local function firstline(n)
+-- while n do
+-- local id = n.id
+-- if id == hlist_code then
+-- if n.subtype == line_code then
+-- return n
+-- else
+-- return firstline(n.list)
+-- end
+-- elseif id == vlist_code then
+-- return firstline(n.list)
+-- end
+-- n = n.next
+-- end
+-- end
+
+-- nodes.firstline = firstline
+
+-- this depends on fonts, so we have a funny dependency ... will be
+-- sorted out .. we could make tonodes a plugin into this
+
+local function tonodes(str,fnt,attr) -- (str,template_glyph) -- moved from blob-ini
+ if not str or str == "" then
+ return
+ end
+ local head, tail, space, fnt, template = nil, nil, nil, nil, nil
+ if not fnt then
+ fnt = current_font()
+ elseif type(fnt) ~= "number" and fnt.id == "glyph" then
+ fnt, template = nil, fnt
+ -- else
+ -- already a number
+ end
+ for s in utfvalues(str) do
+ local n
+ if s == 32 then
+ if space then
+ n = copy_node(space)
+ elseif fonts then -- depedency
+ local parameters = fonts.hashes.identifiers[fnt].parameters
+ space = new_glue(parameters.space,parameters.space_stretch,parameters.space_shrink)
+ n = space
+ end
+ elseif template then
+ n = copy_node(template)
+ n.char = s
+ else
+ n = new_glyph(fnt,s)
+ end
+ if attr then -- normally false when template
+ n.attr = copy_node_list(attr)
+ end
+ if head then
+ insert_node_after(head,tail,n)
+ else
+ head = n
+ end
+ tail = n
+ end
+ return head, tail
+end
+
+nodes.tonodes = tonodes
+
+local function link(list,currentfont,currentattr,head,tail)
+ for i=1,#list do
+ local n = list[i]
+ if n then
+ local tn = isnode(n)
+ if not tn then
+ local tn = type(n)
+ if tn == "number" then
+ if not currentfont then
+ currentfont = current_font()
+ end
+ local h, t = tonodes(tostring(n),currentfont,currentattr)
+ if not h then
+ -- skip
+ elseif not head then
+ head, tail = h, t
+ else
+ tail.next, h.prev, tail = h, t, t
+ end
+ elseif tn == "string" then
+ if #tn > 0 then
+ if not currentfont then
+ currentfont = current_font()
+ end
+ local h, t = tonodes(n,currentfont,currentattr)
+ if not h then
+ -- skip
+ elseif not head then
+ head, tail = h, t
+ else
+ tail.next, h.prev, tail = h, t, t
+ end
+ end
+ elseif tn == "table" then
+ if #tn > 0 then
+ if not currentfont then
+ currentfont = current_font()
+ end
+ head, tail = link(n,currentfont,currentattr,head,tail)
+ end
+ end
+ elseif not head then
+ head = n
+ if n.next then
+ tail = slide_nodes(n)
+ else
+ tail = n
+ end
+ elseif n.id == attributelist_code then
+ -- weird case
+ report_error("weird node type in list at index %s:",i)
+ for i=1,#list do
+ local l = list[i]
+ report_error("%3i: %s %S",i,l.id == attributelist_code and "!" or ">",l)
+ end
+ os.exit()
+ else
+ tail.next = n
+ n.prev = tail
+ if n.next then
+ tail = slide_nodes(n)
+ else
+ tail = n
+ end
+ end
+ else
+ -- permitting nil is convenient
+ end
+ end
+ return head, tail
+end
+
+nodes.link = link
+
+local function locate(start,wantedid,wantedsubtype)
+ for n in traverse_nodes(start) do
+ local id = n.id
+ if id == wantedid then
+ if not wantedsubtype or n.subtype == wantedsubtype then
+ return n
+ end
+ elseif id == hlist_code or id == vlist_code then
+ local found = locate(n.list,wantedid,wantedsubtype)
+ if found then
+ return found
+ end
+ end
+ end
+end
+
+nodes.locate = locate
+
+function nodes.concat(list)
+ local head, tail
+ for i=1,#list do
+ local li = list[i]
+ if not li then
+ -- skip
+ elseif head then
+ tail.next = li
+ li.prev = tail
+ tail = li.next and slide_nodes(li) or li
+ else
+ head = li
+ tail = li.next and slide_nodes(li) or li
+ end
+ end
+ return head, tail
+end