diff options
Diffstat (limited to 'tex/context/base/node-aux.lua')
-rw-r--r-- | tex/context/base/node-aux.lua | 778 |
1 files changed, 389 insertions, 389 deletions
diff --git a/tex/context/base/node-aux.lua b/tex/context/base/node-aux.lua index e3fc7ad6f..21737a43b 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
|