Hi LuaTeX developers,
first of all, thank you very much for all your work on this and the
great OpenType support and possibility of fixing internals using Lua code!
In the following document, the math subscripts are so close to the
following characters that they sometimes overlap:
\documentclass{article}
\usepackage{unicode-math}
\def\supp{{\rm supp}}
\begin{document}
$$
I(P_X,P_{Y|X}) = \sum_{(X,Y) \in \supp P_{XY}}
P_{XY}(X,Y) \log_2 \frac{P_{XY}(X,Y)}{P_X(X) P_Y(Y)}.
$$
\end{document}
The problem cannot be fixed by simply adding spacing, e.g. \Uordopenspacing,
because the space is different per character. We need italics correction,
in all circumstances where an italic symbol is last in the subscript and
something follows the noad. By the manual, Section 7.6.4 this is not
applied to subscripts, but only the base characters.
Setting \mathitalicsmode=1 to force it changes nothing, because italics
correction is then only applied in the subscript to the characters
before the last one. Maybe luatex assumes the last character to be
followed by nothing, because in the mlist of the subscript follows
nothing even if after the whole noad follows something.
Setting \mathitalicsmode=1 and adding manual 0-kerns (like \/) helps.
This is implemented by the following lua code:
\directlua{
ty = node.types()
sub_addkern = function(sub)
scan_sub_addkern(sub)
local kern = node.new("kern")
if ty[sub.id] == "math_char" or ty[sub.id] == "math_char_text" then
local old = node.new("noad", 0)
old.nucleus = sub
sub = node.new("sub_mlist")
sub.head = old
node.insert_after(sub.head, old, kern)
elseif ty[sub.id] == "sub_box" or ty[sub.id] == "sub_mlist" then
local tail = node.tail(sub.head)
if not (ty[tail.id] == "kern") then
node.insert_after(sub.head, tail, kern)
end
end
return sub
end
scan_sub_addkern = function(n)
if n.head then
n.head = scan_all_sub_addkern(n.head)
end
if n.sub then
n.sub = sub_addkern(n.sub)
end
if n.nucleus then
scan_sub_addkern(n.nucleus)
end
if n.num then
scan_sub_addkern(n.num)
end
if n.denom then
scan_sub_addkern(n.denom)
end
end
scan_all_sub_addkern = function(head)
for n in node.traverse(head) do
scan_sub_addkern(n)
end
return head
end
luatexbase.add_to_callback("pre_mlist_to_hlist_filter", scan_all_sub_addkern,
"default mlist_to_hlist + italics-corrected subscript")
}
XeTeX does this right out of the box.
Best,
Johannes