summaryrefslogtreecommitdiff
path: root/otfl-node-res.lua
diff options
context:
space:
mode:
Diffstat (limited to 'otfl-node-res.lua')
-rw-r--r--otfl-node-res.lua186
1 files changed, 160 insertions, 26 deletions
diff --git a/otfl-node-res.lua b/otfl-node-res.lua
index 5398d84..2657dfa 100644
--- a/otfl-node-res.lua
+++ b/otfl-node-res.lua
@@ -7,7 +7,10 @@ if not modules then modules = { } end modules ['node-res'] = {
}
local gmatch, format = string.gmatch, string.format
-local copy_node, free_node, free_list, new_node = node.copy, node.free, node.flush_list, node.new
+local copy_node, free_node, free_list, new_node, node_type, node_id = node.copy, node.free, node.flush_list, node.new, node.type, node.id
+local tonumber, round = tonumber, math.round
+
+local glyph_node = node_id("glyph")
--[[ldx--
<p>The next function is not that much needed but in <l n='context'/> we use
@@ -25,16 +28,21 @@ for k, v in pairs(node.whatsits()) do
whatsits[k], whatsits[v] = v, k -- two way
end
-function nodes.register(n)
+local function register_node(n)
reserved[#reserved+1] = n
return n
end
+nodes.register = register_node
+
function nodes.cleanup_reserved(nofboxes) -- todo
nodes.tracers.steppers.reset() -- todo: make a registration subsystem
local nr, nl = #reserved, 0
for i=1,nr do
- free_node(reserved[i])
+ local ri = reserved[i]
+ -- if not (ri.id == glue_spec and not ri.is_writable) then
+ free_node(reserved[i])
+ -- end
end
if nofboxes then
local tb = tex.box
@@ -58,19 +66,37 @@ function nodes.usage()
return t
end
-local disc = nodes.register(new_node("disc"))
-local kern = nodes.register(new_node("kern",1))
-local penalty = nodes.register(new_node("penalty"))
-local glue = nodes.register(new_node("glue"))
-local glue_spec = nodes.register(new_node("glue_spec"))
-local glyph = nodes.register(new_node("glyph",0))
-local textdir = nodes.register(new_node("whatsit",whatsits.dir)) -- 7
-local rule = nodes.register(new_node("rule"))
-local latelua = nodes.register(new_node("whatsit",whatsits.late_lua)) -- 35
-local user_n = nodes.register(new_node("whatsit",whatsits.user_defined)) user_n.type = 100 -- 44
-local user_l = nodes.register(new_node("whatsit",whatsits.user_defined)) user_l.type = 110 -- 44
-local user_s = nodes.register(new_node("whatsit",whatsits.user_defined)) user_s.type = 115 -- 44
-local user_t = nodes.register(new_node("whatsit",whatsits.user_defined)) user_t.type = 116 -- 44
+local disc = register_node(new_node("disc"))
+local kern = register_node(new_node("kern",1))
+local penalty = register_node(new_node("penalty"))
+local glue = register_node(new_node("glue")) -- glue.spec = nil
+local glue_spec = register_node(new_node("glue_spec"))
+local glyph = register_node(new_node("glyph",0))
+local textdir = register_node(new_node("whatsit",whatsits.dir)) -- 7 (6 is local par node)
+local rule = register_node(new_node("rule"))
+local latelua = register_node(new_node("whatsit",whatsits.late_lua)) -- 35
+local user_n = register_node(new_node("whatsit",whatsits.user_defined)) user_n.type = 100 -- 44
+local user_l = register_node(new_node("whatsit",whatsits.user_defined)) user_l.type = 110 -- 44
+local user_s = register_node(new_node("whatsit",whatsits.user_defined)) user_s.type = 115 -- 44
+local user_t = register_node(new_node("whatsit",whatsits.user_defined)) user_t.type = 116 -- 44
+local left_margin_kern = register_node(new_node("margin_kern",0))
+local right_margin_kern = register_node(new_node("margin_kern",1))
+local lineskip = register_node(new_node("glue",1))
+local baselineskip = register_node(new_node("glue",2))
+local leftskip = register_node(new_node("glue",8))
+local rightskip = register_node(new_node("glue",9))
+local temp = register_node(new_node("temp",0))
+
+function nodes.zeroglue(n)
+ local s = n.spec
+ return not writable or (
+ s.width == 0
+ and s.stretch == 0
+ and s.shrink == 0
+ and s.stretch_order == 0
+ and s.shrink_order == 0
+ )
+end
function nodes.glyph(fnt,chr)
local n = copy_node(glyph)
@@ -78,48 +104,156 @@ function nodes.glyph(fnt,chr)
if chr then n.char = chr end
return n
end
+
function nodes.penalty(p)
local n = copy_node(penalty)
n.penalty = p
return n
end
+
function nodes.kern(k)
local n = copy_node(kern)
n.kern = k
return n
end
-function nodes.glue(width,stretch,shrink)
- local n, s = copy_node(glue), copy_node(glue_spec)
- s.width, s.stretch, s.shrink = width, stretch, shrink
- n.spec = s
- return n
-end
+
function nodes.glue_spec(width,stretch,shrink)
local s = copy_node(glue_spec)
s.width, s.stretch, s.shrink = width, stretch, shrink
return s
end
+
+local function someskip(skip,width,stretch,shrink)
+ local n = copy_node(skip)
+ if not width then
+ -- no spec
+ elseif tonumber(width) then
+ local s = copy_node(glue_spec)
+ s.width, s.stretch, s.shrink = width, stretch, shrink
+ n.spec = s
+ else
+ -- shared
+ n.spec = copy_node(width)
+ end
+ return n
+end
+
+function nodes.glue(width,stretch,shrink)
+ return someskip(glue,width,stretch,shrink)
+end
+function nodes.leftskip(width,stretch,shrink)
+ return someskip(leftskip,width,stretch,shrink)
+end
+function nodes.rightskip(width,stretch,shrink)
+ return someskip(rightskip,width,stretch,shrink)
+end
+function nodes.lineskip(width,stretch,shrink)
+ return someskip(lineskip,width,stretch,shrink)
+end
+function nodes.baselineskip(width,stretch,shrink)
+ return someskip(baselineskip,width,stretch,shrink)
+end
+
function nodes.disc()
return copy_node(disc)
end
+
function nodes.textdir(dir)
local t = copy_node(textdir)
t.dir = dir
return t
end
-function nodes.rule(w,h,d)
+
+function nodes.rule(width,height,depth,dir)
local n = copy_node(rule)
- if w then n.width = w end
- if h then n.height = h end
- if d then n.depth = d end
+ if width then n.width = width end
+ if height then n.height = height end
+ if depth then n.depth = depth end
+ if dir then n.dir = dir end
return n
end
+
function nodes.latelua(code)
local n = copy_node(latelua)
n.data = code
return n
end
+function nodes.leftmarginkern(glyph,width)
+ local n = copy_node(left_margin_kern)
+ if not glyph then
+ logs.fatal("nodes","invalid pointer to left margin glyph node")
+ elseif glyph.id ~= glyph_node then
+ logs.fatal("nodes","invalid node type %s for left margin glyph node",node_type(glyph))
+ else
+ n.glyph = glyph
+ end
+ if width then
+ n.width = width
+ end
+ return n
+end
+
+function nodes.rightmarginkern(glyph,width)
+ local n = copy_node(right_margin_kern)
+ if not glyph then
+ logs.fatal("nodes","invalid pointer to right margin glyph node")
+ elseif glyph.id ~= glyph_node then
+ logs.fatal("nodes","invalid node type %s for right margin glyph node",node_type(p))
+ else
+ n.glyph = glyph
+ end
+ if width then
+ n.width = width
+ end
+ return n
+end
+
+function nodes.temp()
+ return copy_node(temp)
+end
+--[[
+<p>At some point we ran into a problem that the glue specification
+of the zeropoint dimension was overwritten when adapting a glue spec
+node. This is a side effect of glue specs being shared. After a
+couple of hours tracing and debugging Taco and I came to the
+conclusion that it made no sense to complicate the spec allocator
+and settled on a writable flag. This all is a side effect of the
+fact that some glues use reserved memory slots (with the zeropoint
+glue being a noticeable one). So, next we wrap this into a function
+and hide it for the user. And yes, LuaTeX now gives a warning as
+well.</p>
+]]--
+
+if tex.luatexversion > 51 then
+
+ function nodes.writable_spec(n)
+ local spec = n.spec
+ if not spec then
+ spec = copy_node(glue_spec)
+ n.spec = spec
+ elseif not spec.writable then
+ spec = copy_node(spec)
+ n.spec = spec
+ end
+ return spec
+ end
+
+else
+
+ function nodes.writable_spec(n)
+ local spec = n.spec
+ if not spec then
+ spec = copy_node(glue_spec)
+ else
+ spec = copy_node(spec)
+ end
+ n.spec = spec
+ return spec
+ end
+
+end
+
local cache = { }
function nodes.usernumber(num)