diff options
Diffstat (limited to 'otfl-node-res.lua')
-rw-r--r-- | otfl-node-res.lua | 186 |
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) |