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 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 |