Enforce TeX like spacing
This commit is contained in:
parent
ba219a05bb
commit
98fd0a477a
@ -20,6 +20,8 @@ local function invert_table(t)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local noad_names = node.subtypes'noad'
|
local noad_names = node.subtypes'noad'
|
||||||
|
|
||||||
|
--[[ We could determine the noad subtypes dynamically:
|
||||||
local noad_sub = invert_table(noad_names)
|
local noad_sub = invert_table(noad_names)
|
||||||
local noad_ord = noad_sub.ord
|
local noad_ord = noad_sub.ord
|
||||||
local noad_op = noad_sub.opdisplaylimits
|
local noad_op = noad_sub.opdisplaylimits
|
||||||
@ -34,6 +36,60 @@ local noad_inner = noad_sub.inner
|
|||||||
local noad_under = noad_sub.under
|
local noad_under = noad_sub.under
|
||||||
local noad_over = noad_sub.over
|
local noad_over = noad_sub.over
|
||||||
local noad_vcenter = noad_sub.vcenter
|
local noad_vcenter = noad_sub.vcenter
|
||||||
|
-- But the spacing table depends on their specific values anyway, so we just verify the values
|
||||||
|
]]
|
||||||
|
local noad_ord, noad_op, noad_oplimits, noad_opnolimits = 0, 1, 2, 3
|
||||||
|
local noad_bin, noad_rel, noad_open, noad_close, noad_punct = 4, 5, 6, 7, 8
|
||||||
|
local noad_inner, noad_under, noad_over, noad_vcenter = 9, 10, 11, 12
|
||||||
|
|
||||||
|
for i, n in ipairs{'ord', 'opdisplaylimits', 'oplimits', 'opnolimits', 'bin',
|
||||||
|
'rel', 'open', 'close', 'punct', 'inner', 'under', 'over', 'vcenter'} do
|
||||||
|
assert(noad_names[i-1] == n)
|
||||||
|
end
|
||||||
|
-- Attention, the spacing_table is indexed by subtype+1 since 1-based tables are faster in Lua
|
||||||
|
local spacing_table = {
|
||||||
|
{0 , '0.167em', '0.167em', '0.167em', '0.222em', '0.278em', 0 , 0 , 0 , '0.167em', 0 , 0 , 0 , },
|
||||||
|
{'0.167em', '0.167em', '0.167em', '0.167em', nil , '0.278em', 0 , 0 , 0 , '0.167em', '0.167em', '0.167em', '0.167em', },
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
{'0.222em', '0.222em', '0.222em', '0.222em', nil , nil , '0.222em', nil , nil , '0.222em', '0.222em', '0.222em', '0.222em', },
|
||||||
|
{'0.278em', '0.278em', '0.278em', '0.278em', nil , 0 , '0.278em', 0 , 0 , '0.278em', '0.278em', '0.278em', '0.278em', },
|
||||||
|
{0 , 0 , 0 , 0 , nil , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , },
|
||||||
|
{0 , '0.167em', '0.167em', '0.167em', '0.222em', '0.278em', 0 , 0 , 0 , '0.167em', 0 , 0 , 0 , },
|
||||||
|
{'0.167em', '0.167em', '0.167em', '0.167em', nil , '0.167em', '0.167em', '0.167em', '0.167em', '0.167em', '0.167em', '0.167em', '0.167em', },
|
||||||
|
{'0.167em', '0.167em', '0.167em', '0.167em', '0.222em', '0.278em', '0.167em', 0 , '0.167em', '0.167em', '0.167em', '0.167em', '0.167em', },
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
}
|
||||||
|
local spacing_table_script = {
|
||||||
|
{0 , '0.167em', '0.167em', '0.167em', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , },
|
||||||
|
{'0.167em', '0.167em', '0.167em', '0.167em', nil , 0 , 0 , 0 , 0 , 0 , '0.167em', '0.167em', '0.167em', },
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
{0 , 0 , 0 , 0 , nil , nil , 0 , nil , nil , 0 , 0 , 0 , 0 , },
|
||||||
|
{0 , 0 , 0 , 0 , nil , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , },
|
||||||
|
{0 , 0 , 0 , 0 , nil , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , },
|
||||||
|
{0 , '0.167em', '0.167em', '0.167em', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , },
|
||||||
|
{0 , 0 , 0 , 0 , nil , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , },
|
||||||
|
{0 , '0.167em', '0.167em', '0.167em', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , },
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
}
|
||||||
|
do -- Fill the blanks
|
||||||
|
local st, sts = spacing_table, spacing_table_script
|
||||||
|
|
||||||
|
local st_op, sts_op = st[noad_op+1], sts[noad_op+1]
|
||||||
|
st[noad_oplimits+1], sts[noad_oplimits+1] = st_op, sts_op
|
||||||
|
st[noad_opnolimits+1], sts[noad_opnolimits+1] = st_op, sts_op
|
||||||
|
|
||||||
|
local st_ord, sts_ord = st[noad_ord+1], sts[noad_ord+1]
|
||||||
|
st[noad_under+1], sts[noad_under+1] = st_ord, sts_ord
|
||||||
|
st[noad_over+1], sts[noad_over+1] = st_ord, sts_ord
|
||||||
|
st[noad_vcenter+1], sts[noad_vcenter+1] = st_ord, sts_ord
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
local radical_sub = node.subtypes'radical'
|
local radical_sub = node.subtypes'radical'
|
||||||
local fence_sub = node.subtypes'fence'
|
local fence_sub = node.subtypes'fence'
|
||||||
@ -268,8 +324,8 @@ local function radical_to_table(radical, sub, cur_style)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function fraction_to_table(fraction, sub, cur_style)
|
local function fraction_to_table(fraction, sub, cur_style)
|
||||||
local num, core = kernel_to_table(fraction.num, sup_style(cur_style))
|
local num, core = kernel_to_table(fraction.num, cur_style + 2 - cur_style//6*2)
|
||||||
local denom = kernel_to_table(fraction.denom, sub_style(cur_style))
|
local denom = kernel_to_table(fraction.denom, cur_style//2*2 + 3 - cur_style//6*2)
|
||||||
local left = delim_to_table(fraction.left)
|
local left = delim_to_table(fraction.left)
|
||||||
local right = delim_to_table(fraction.right)
|
local right = delim_to_table(fraction.right)
|
||||||
local mfrac = {[0] = 'mfrac',
|
local mfrac = {[0] = 'mfrac',
|
||||||
@ -375,24 +431,25 @@ function nodes_to_table(head, cur_style)
|
|||||||
local t = {[0] = 'mrow'}
|
local t = {[0] = 'mrow'}
|
||||||
local result = t
|
local result = t
|
||||||
local nonscript
|
local nonscript
|
||||||
local core, mn = space_like
|
local core, last_noad, last_core, mn = space_like, nil, nil, nil
|
||||||
for n, id, sub in node.traverse(head) do
|
for n, id, sub in node.traverse(head) do
|
||||||
local new_core, new_mn
|
local new_core, new_mn, new_node, new_noad
|
||||||
local props = properties[n]
|
local props = properties[n]
|
||||||
props = props and props.mathml_table
|
props = props and props.mathml_table
|
||||||
if props then
|
if props then
|
||||||
t[#t+1], new_core = props, user_provided
|
new_node, new_core = props, user_provided
|
||||||
elseif id == noad_t then
|
elseif id == noad_t then
|
||||||
local substr = noad_sub[sub]
|
|
||||||
local new_n
|
local new_n
|
||||||
new_n, new_core, new_mn = noad_to_table(n, sub, cur_style, mn)
|
new_n, new_core, new_mn = noad_to_table(n, sub, cur_style, mn)
|
||||||
if new_mn == false then
|
if new_mn == false then
|
||||||
t[#t], new_mn = new_n, nil
|
t[#t], new_mn = new_n, nil
|
||||||
else
|
else
|
||||||
t[#t+1] = new_n -- might be nil
|
new_node = new_n -- might be nil
|
||||||
end
|
end
|
||||||
|
new_noad = sub
|
||||||
elseif id == accent_t then
|
elseif id == accent_t then
|
||||||
t[#t+1], new_core = accent_to_table(n, sub, cur_style)
|
new_node, new_core = accent_to_table(n, sub, cur_style)
|
||||||
|
new_noad = noad_ord
|
||||||
elseif id == style_t then
|
elseif id == style_t then
|
||||||
if sub ~= cur_style then
|
if sub ~= cur_style then
|
||||||
if #t == 0 then
|
if #t == 0 then
|
||||||
@ -412,37 +469,59 @@ function nodes_to_table(head, cur_style)
|
|||||||
new_core = space_like
|
new_core = space_like
|
||||||
elseif id == choice_t then
|
elseif id == choice_t then
|
||||||
local size = cur_style//2
|
local size = cur_style//2
|
||||||
t[#t+1], new_core = nodes_to_table(n[size == 0 and 'display'
|
new_node, new_core = nodes_to_table(n[size == 0 and 'display'
|
||||||
or size == 1 and 'text'
|
or size == 1 and 'text'
|
||||||
or size == 2 and 'script'
|
or size == 2 and 'script'
|
||||||
or size == 3 and 'scriptscript'
|
or size == 3 and 'scriptscript'
|
||||||
or assert(false)], 2*size), space_like
|
or assert(false)], 2*size), space_like
|
||||||
elseif id == radical_t then
|
elseif id == radical_t then
|
||||||
t[#t+1], new_core = radical_to_table(n, sub, cur_style)
|
new_node, new_core = radical_to_table(n, sub, cur_style)
|
||||||
|
new_noad = noad_ord
|
||||||
elseif id == fraction_t then
|
elseif id == fraction_t then
|
||||||
t[#t+1], new_core = fraction_to_table(n, sub, cur_style)
|
new_node, new_core = fraction_to_table(n, sub, cur_style)
|
||||||
|
new_noad = noad_inner
|
||||||
elseif id == fence_t then
|
elseif id == fence_t then
|
||||||
t[#t+1], new_core = fence_to_table(n, sub, cur_style)
|
new_node, new_core = fence_to_table(n, sub, cur_style)
|
||||||
|
local class = n.class
|
||||||
|
new_noad = class >= 0 and class or sub == fence_sub.left and noad_open or noad_close
|
||||||
elseif id == kern_t then
|
elseif id == kern_t then
|
||||||
if not nonscript then
|
if not nonscript then
|
||||||
t[#t+1], new_core = space_to_table(n.kern, sub, cur_style)
|
new_node, new_core = space_to_table(n.kern, sub, cur_style)
|
||||||
end
|
end
|
||||||
elseif id == glue_t then
|
elseif id == glue_t then
|
||||||
if cur_style >= 4 or not nonscript then
|
if cur_style >= 4 or not nonscript then
|
||||||
if sub == 98 then -- TODO magic number
|
if sub == 98 then -- TODO magic number
|
||||||
nonscript = true
|
nonscript = true
|
||||||
else
|
else
|
||||||
t[#t+1], new_core = space_to_table(n.width, sub, cur_style)
|
new_node, new_core = space_to_table(n.width, sub, cur_style)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif id == rule_t then
|
elseif id == rule_t then
|
||||||
t[#t+1], new_core = rule_to_table(n, sub, cur_style)
|
new_node, new_core = rule_to_table(n, sub, cur_style)
|
||||||
-- elseif id == disc_t then -- Uncommon, does not play nicely with math mode and no sensible mapping anyway
|
-- elseif id == disc_t then -- Uncommon, does not play nicely with math mode and no sensible mapping anyway
|
||||||
end -- The other possible ids are whatsit, penalty, adjust, ins, mark. Ignore them.
|
end -- The other possible ids are whatsit, penalty, adjust, ins, mark. Ignore them.
|
||||||
nonscript = nil
|
nonscript = nil
|
||||||
if core and new_core ~= space_like then
|
if core and new_core ~= space_like then
|
||||||
core = core == space_like and new_core or nil
|
core = core == space_like and new_core or nil
|
||||||
end
|
end
|
||||||
|
if new_node then
|
||||||
|
if new_noad then
|
||||||
|
local space = last_noad and (cur_style >= 4 and spacing_table_script or spacing_table)[last_noad + 1][new_noad + 1] or 0
|
||||||
|
if assert(space) ~= 0 then
|
||||||
|
if new_core and new_core[0] == 'mo' then
|
||||||
|
new_core.lspace = space
|
||||||
|
elseif last_core and last_core[0] == 'mo' then
|
||||||
|
last_core.rspace = space
|
||||||
|
else
|
||||||
|
t[#t+1] = {[0] = 'mspace', width = space} -- TODO Move into operators whenever possible
|
||||||
|
end
|
||||||
|
end
|
||||||
|
last_noad, last_core = new_noad, new_core
|
||||||
|
elseif new_node[0] ~= 'mspace' or new_node.mathbackground then
|
||||||
|
last_core = nil
|
||||||
|
end
|
||||||
|
t[#t+1] = new_node
|
||||||
|
end
|
||||||
mn = new_mn
|
mn = new_mn
|
||||||
end
|
end
|
||||||
-- In TeX, groups are never space like
|
-- In TeX, groups are never space like
|
||||||
|
Loading…
Reference in New Issue
Block a user