summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/node-aux.lua
diff options
context:
space:
mode:
authorContext Git Mirror Bot <phg42.2a@gmail.com>2016-01-12 17:15:07 +0100
committerContext Git Mirror Bot <phg42.2a@gmail.com>2016-01-12 17:15:07 +0100
commit8d8d528d2ad52599f11250cfc567fea4f37f2a8b (patch)
tree94286bc131ef7d994f9432febaf03fe23d10eef8 /tex/context/base/mkiv/node-aux.lua
parentf5aed2e51223c36c84c5f25a6cad238b2af59087 (diff)
downloadcontext-8d8d528d2ad52599f11250cfc567fea4f37f2a8b.tar.gz
2016-01-12 16:26:00
Diffstat (limited to 'tex/context/base/mkiv/node-aux.lua')
-rw-r--r--tex/context/base/mkiv/node-aux.lua545
1 files changed, 545 insertions, 0 deletions
diff --git a/tex/context/base/mkiv/node-aux.lua b/tex/context/base/mkiv/node-aux.lua
new file mode 100644
index 000000000..38df55eef
--- /dev/null
+++ b/tex/context/base/mkiv/node-aux.lua
@@ -0,0 +1,545 @@
+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 nuts = nodes.nuts
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+local vianuts = nuts.vianuts
+
+local getbox = nuts.getbox
+local getnext = nuts.getnext
+local getid = nuts.getid
+local getsubtype = nuts.getsubtype
+local getlist = nuts.getlist
+local getfont = nuts.getfont
+local getchar = nuts.getchar
+local getattr = nuts.getattr
+local getfield = nuts.getfield
+
+local setfield = nuts.setfield
+local setattr = nuts.setattr
+local setlink = nuts.setlink
+local setlist = nuts.setlist
+local setnext = nuts.setnext
+local setprev = nuts.setprev
+
+local traverse_nodes = nuts.traverse
+local traverse_id = nuts.traverse_id
+local free_node = nuts.free
+local hpack_nodes = nuts.hpack
+local unset_attribute = nuts.unset_attribute
+local first_glyph = nuts.first_glyph
+local copy_node = nuts.copy
+local copy_node_list = nuts.copy_list
+local find_tail = nuts.tail
+local insert_node_after = nuts.insert_after
+local isnode = nuts.is_node
+local getbox = nuts.getbox
+
+local nodes_traverse_id = nodes.traverse_id
+local nodes_first_glyph = nodes.first_glyph
+
+local nodepool = nuts.pool
+local new_glue = nodepool.glue
+local new_glyph = nodepool.glyph
+
+local unsetvalue = attributes.unsetvalue
+
+local current_font = font.current
+
+local texsetbox = tex.setbox
+
+local report_error = logs.reporter("node-aux:error")
+
+-- At some point we figured that copying before using was the safest bet
+-- when dealing with boxes at the tex end. This is because tex also needs
+-- to manage the grouping (i.e. savestack). However, there is an easy
+-- solution that keeps the tex end happy as tex.setbox deals with this. The
+-- overhead of one temporary list node is neglectable.
+--
+-- function tex.takebox(id)
+-- local box = tex.getbox(id)
+-- if box then
+-- local copy = node.copy(box)
+-- local list = box.list
+-- copy.list = list
+-- box.list = nil
+-- tex.setbox(id,nil)
+-- return copy
+-- end
+-- end
+
+local function takebox(id)
+ local box = getbox(id)
+ if box then
+ local copy = copy_node(box)
+ local list = getlist(box)
+ if list then
+ setlist(copy,list)
+ setlist(box,nil)
+ end
+ texsetbox(id,nil)
+ return copy
+ end
+end
+
+function nodes.takebox(id)
+ local b = takebox(id)
+ if b then
+ return tonode(b)
+ end
+end
+
+nuts.takebox = takebox
+tex.takebox = nodes.takebox -- sometimes more clear
+
+-- so far
+
+local function repackhlist(list,...)
+ local temp, b = hpack_nodes(list,...)
+ list = getlist(temp)
+ setlist(temp)
+ free_node(temp)
+ return list, b
+end
+
+nuts.repackhlist = repackhlist
+
+function nodes.repackhlist(list,...)
+ local list, b = repackhlist(tonut(list),...)
+ return tonode(list), b
+end
+
+local function set_attributes(head,attr,value)
+ for n in traverse_nodes(head) do
+ setattr(n,attr,value)
+ local id = getid(n)
+ if id == hlist_node or id == vlist_node then
+ set_attributes(getlist(n),attr,value)
+ end
+ end
+end
+
+local function set_unset_attributes(head,attr,value)
+ for n in traverse_nodes(head) do
+ if not getattr(n,attr) then
+ setattr(n,attr,value)
+ end
+ local id = getid(n)
+ if id == hlist_code or id == vlist_code then
+ set_unset_attributes(getlist(n),attr,value)
+ end
+ end
+end
+
+local function unset_attributes(head,attr)
+ for n in traverse_nodes(head) do
+ setattr(n,attr,unsetvalue)
+ local id = getid(n)
+ if id == hlist_code or id == vlist_code then
+ unset_attributes(getlist(n),attr)
+ end
+ end
+end
+
+-- for old times sake
+
+nuts.setattribute = nuts.setattr nodes.setattribute = nodes.setattr
+nuts.getattribute = nuts.getattr nodes.getattribute = nodes.getattr
+nuts.unsetattribute = nuts.unset_attribute nodes.unsetattribute = nodes.unset_attribute
+nuts.has_attribute = nuts.has_attribute nodes.has_attribute = nodes.has_attribute
+nuts.firstglyph = nuts.first_glyph nodes.firstglyph = nodes.first_glyph
+
+nuts.setattributes = set_attributes nodes.setattributes = vianuts(set_attributes)
+nuts.setunsetattributes = set_unset_attributes nodes.setunsetattributes = vianuts(set_unset_attributes)
+nuts.unsetattributes = unset_attributes nodes.unsetattributes = vianuts(unset_attributes)
+
+-- history:
+--
+-- local function glyph_width(a)
+-- local ch = chardata[getfont(a)][getchar(a)]
+-- return (ch and ch.width) or 0
+-- end
+--
+-- local function glyph_total(a)
+-- local ch = chardata[getfont(a)][getchar(a)]
+-- return (ch and (ch.height+ch.depth)) or 0
+-- end
+--
+-- local function non_discardable(a) -- inline
+-- return getid(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
+--
+-- if not node.end_of_math then
+-- function node.end_of_math(n)
+-- for n in traverse_id(math_code,getnext(next)) do
+-- return n
+-- end
+-- end
+-- end
+--
+-- nodes.endofmath = node.end_of_math
+--
+-- local function firstline(n)
+-- while n do
+-- local id = getid(n)
+-- if id == hlist_code then
+-- if getsubtype(n) == line_code then
+-- return n
+-- else
+-- return firstline(getlist(n))
+-- end
+-- elseif id == vlist_code then
+-- return firstline(getlist(n))
+-- end
+-- n = getnext(n)
+-- end
+-- end
+--
+-- nodes.firstline = firstline
+
+function nuts.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.firstcharacter(n,untagged) -- tagged == subtype > 255
+-- if untagged then
+-- return nodes_first_glyph(n)
+-- else
+-- for g in nodes_traverse_id(glyph_code,n) do
+-- return g
+-- end
+-- end
+-- end
+
+local function firstcharinbox(n)
+ local l = getlist(getbox(n))
+ if l then
+ for g in traverse_id(glyph_code,l) do
+ return getchar(g)
+ end
+ end
+ return 0
+end
+
+nuts .firstcharinbox = firstcharinbox
+nodes.firstcharinbox = firstcharinbox -- hm, ok ?
+nodes.firstcharacter = vianuts(firstcharacter)
+
+interfaces.implement {
+ name = "buildtextaccent",
+ arguments = "integer",
+ actions = function(n) -- Is this crap really used? Or was it an experiment?
+ local char = firstcharinbox(n)
+ if char > 0 then
+ -- context.accent(false,char)
+ context([[\accent%s\relax]],char)
+ end
+ end
+}
+
+-- 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 getid(fnt) == glyph_code then -- so it has to be a real node
+ fnt, template = nil, tonut(fnt)
+ 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)
+ setvalue(n,"char",s)
+ else
+ n = new_glyph(fnt,s)
+ end
+ if attr then -- normally false when template
+ -- setfield(n,"attr",copy_node_list(attr))
+ setfield(n,"attr",attr)
+ end
+ if head then
+ insert_node_after(head,tail,n)
+ else
+ head = n
+ end
+ tail = n
+ end
+ return head, tail
+end
+
+nuts.tonodes = tonodes
+
+nodes.tonodes = function(str,fnt,attr)
+ local head, tail = tonodes(str,fnt,attr)
+ return tonode(head), tonode(tail)
+end
+
+-- 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 = h
+-- tail = t
+-- else
+-- setfield(tail,"next",h)
+-- setfield(h,"prev",t)
+-- tail = 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
+-- setfield(tail,"next",h)
+-- setfield(h,"prev",t)
+-- tail = 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
+-- tail = find_tail(n)
+-- elseif getid(n) == 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,getid(l) == attributelist_code and "!" or ">",l)
+-- end
+-- os.exit()
+-- else
+-- setfield(tail,"next",n)
+-- setfield(n,"prev",tail)
+-- if getnext(n) then
+-- tail = find_tail(n)
+-- else
+-- tail = n
+-- end
+-- end
+-- else
+-- -- permitting nil is convenient
+-- end
+-- end
+-- return head, tail
+-- end
+
+local function link(list,currentfont,currentattr,head,tail) -- an oldie, might be replaced
+ for i=1,#list do
+ local n = list[i]
+ if n then
+ local tn = type(n)
+ if 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
+ setnext(tail,h)
+ setprev(h,t)
+ tail = 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
+ elseif not head then
+ head = n
+ tail = find_tail(n)
+ elseif getid(n) == 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,getid(l) == attributelist_code and "!" or ">",l)
+ end
+ os.exit()
+ else
+ setlink(tail,n)
+ if getnext(n) then
+ tail = find_tail(n)
+ else
+ tail = n
+ end
+ end
+ else
+ -- permitting nil is convenient
+ end
+ end
+ return head, tail
+end
+
+nuts.link = link
+
+nodes.link = function(list,currentfont,currentattr,head,tail)
+ local head, tail = link(list,currentfont,currentattr,tonut(head),tonut(tail))
+ return tonode(head), tonode(tail)
+end
+
+local function locate(start,wantedid,wantedsubtype)
+ for n in traverse_nodes(start) do
+ local id = getid(n)
+ if id == wantedid then
+ if not wantedsubtype or getsubtype(n) == wantedsubtype then
+ return n
+ end
+ elseif id == hlist_code or id == vlist_code then
+ local found = locate(getlist(n),wantedid,wantedsubtype)
+ if found then
+ return found
+ end
+ end
+ end
+end
+
+nuts.locate = locate
+
+function nodes.locate(start,wantedid,wantedsubtype)
+ local found = locate(tonut(start),wantedid,wantedsubtype)
+ return found and tonode(found)
+end
+
+-- I have no use for this yet:
+--
+-- \skip0=10pt plus 2pt minus 2pt
+-- \cldcontext{"\letterpercent p",tex.stretch_amount(tex.skip[0],1000)} -- 14.30887pt
+--
+-- local gluespec_code = nodes.nodecodes.gluespec
+--
+-- function tex.badness_to_ratio(badness)
+-- return (badness/100)^(1/3)
+-- end
+--
+-- function tex.stretch_amount(skip,badness) -- node no nut
+-- if skip.id == gluespec_code then
+-- return skip.width + (badness and (badness/100)^(1/3) or 1) * skip.stretch
+-- else
+-- return 0
+-- end
+-- end