上标可以位于大括号的很远处,某些字体的情况比其他字体更远。我正在寻找一种基于 Lua 的解决方案来调整分隔符上数学上标的字距。
以下是拉丁现代语中上标放置较宽的一个例子。括号越大,效果越明显。
在另一个线程中,Mico 给出了一个调整上标和下标位置的 Lua 解决方案,当分隔符大小已知时,可以直接使用该方法(见下文)。但是,许多 LaTeX 环境(例如 pmatrix)会自动生成分隔符,因此可能无法预先知道分隔符大小。在这些情况下,在较大尺寸上有效的字距调整可能会在较小尺寸上失败。似乎更好的解决方案是询问“哪个特定字形被上标?”
以下是显示结果的 MWE。对于已知的分隔符大小,可以得到良好的结果,但对于变量大小(尤其是最后一个嵌套示例),结果并不理想!
% !TEX TS-program = lualatex
\documentclass[11pt]{article}
\usepackage{luacode, mathtools, unicode-math}
\usepackage{mleftright}
%% Adapted from Mico's answer here:
%% https://tex.stackexchange.com/questions/432200/ugly-horizontal-spacing-with-some-symbol-subscript-superscript-combinations
\begin{luacode}
function suppl_math_kerning ( s )
-- \Bigr)
s = s:gsub ("(\\Bigr%))%s-%^%s-(%b{})", "%1^{\\mkern-4mu %2}" )
s = s:gsub ("(\\Bigr%))%s-%^%s-(%w)" , "%1^{\\mkern-4mu %2}" )
-- \biggr)
s = s:gsub ("(\\biggr%))%s-%^%s-(%b{})", "%1^{\\mkern-5mu %2}" )
s = s:gsub ("(\\biggr%))%s-%^%s-(%w)" , "%1^{\\mkern-5mu %2}" )
-- \Biggr)
s = s:gsub ("(\\Biggr%))%s-%^%s-(%b{})", "%1^{\\mkern-6.5mu %2}" )
s = s:gsub ("(\\Biggr%))%s-%^%s-(%w)" , "%1^{\\mkern-6.5mu %2}" )
-- \mright)
s = s:gsub ("(\\mright%))%s-%^%s-(%b{})", "%1^{\\mkern-6mu %2}" )
s = s:gsub ("(\\mright%))%s-%^%s-(%w)" , "%1^{\\mkern-6mu %2}" )
-- pmatrix*
s = s:gsub ("(\\end{pmatrix%*})%s-%^%s-(%w)" , "%1^{\\mkern-5mu %2 }" )
s = s:gsub ("(\\end{pmatrix%*})%s-%^%s-(%b{})", "%1^{\\mkern-5mu %2 }" )
return s
end
\end{luacode}
\newcommand\SupplKernOn{\directlua{luatexbase.add_to_callback ("process_input_buffer" , suppl_math_kerning , "suppl_math_kerning" ) }}
\newcommand\SupplKernOff{\directlua{luatexbase.remove_from_callback ("process_input_buffer" , "suppl_math_kerning" ) }}
%% End adapted code
\begin{document}
\SupplKernOn
\[ \verb|\Bigr):| \quad\cos\Bigl(\frac{a}{b}\Bigr)^2 \qquad
\verb|\biggr):| \quad\cos\biggl(\frac{a^2}{b_1}\biggr)^2 \qquad
\verb|\Biggr):| \quad\cos\Biggl(\frac{a^2}{b_1}\Biggr)^2\]
\[ \verb|\end{pmatrix*}:| \quad \begin{pmatrix*}[r] 1 & 0 \\0 & 1 \\ -1 & 0 \end{pmatrix*}^T
\begin{pmatrix*}[r] 1 & 1 & 0 \\- 1 & 1 & 1 \end{pmatrix*}^T \]
\[ \verb|\mright):|\quad\cos\mleft(\frac{a_1}{\mleft(b_1+c_1\mright)^2}\mright)^{t_r} \]
\end{document}
因此,我有两个问题:
- 我的 MWE 中的 Lua 方法来处理定界符大小未知且可变的情况吗?
- 是否可以创建一个适当的字距调整功能,通过
fonts.handlers.otf.addfeature
根据所调用的特定分隔符字形调整上标的字距,例如,按照 Thérèse 在此主题。我想知道是否可以为几个特定的括号字形定义一组特定的字距,或者上标过程本身是否会使这变得不可能。
答案1
因为你在评论中询问,所以我向你介绍了如何做到这一点的蓝图。这远未完成,而且只处理\left...\right
。
让我简单解释一下,为什么它只处理\left...\right
。该\left...\right
对是总是a sub_mlist
,并且\right
原子始终是此子列表中的最后一个元素。因此,如果子列表有上标,我可以简单地扫描是否有右围栏(我甚至不必检查它是否是最后一个,因为它是保证最后)。我找不到栅栏缩放的存储位置,因此目前所有正确的栅栏都会获得相同的字距调整量,无论其大小如何。此外,我还没有调整包含的 mathchar()
与]
)的字距调整,但这很容易做到。
太棒了,太简单了。有了\big
和 的朋友和 ,它就变得更加复杂了\mleft...\mright
。对于 来说,情况最糟糕,\big
因为普通的 LaTeX 和 AMSmath 之间的实现不同。
% plain LaTeX (actually inherited from Plain TeX)
\def\big#1{{\hbox{$\left#1\vbox to8.5\p@{}\right.\n@space$}}}
% amsmath
\renewcommand{\big}{\bBigg@\@ne}
\def\bBigg@#1#2{%
{\@mathmeasure\z@{\nulldelimiterspace\z@}%
{\left#2\vcenter to#1\big@size{}\right.}%
\box\z@}}
\def\@mathmeasure#1#2#3{\setbox#1\hbox{\frozen@everymath\@emptytoks
\m@th$#2#3$}}
两者都将栅栏打包到一个框中,但 LaTeX 使用\vbox
,而 AMSmath 使用\vcenter
,因此生成的 mlist 看起来会有所不同。嵌套的 hlist 只会增加复杂性。遍历列表时,您必须将 hlist 中存在嵌套栅栏的事实传播到周围的 mlist。
\documentclass[11pt]{article}
\usepackage{luacode, mathtools, unicode-math}
\begin{luacode*}
local noad_id = node.id("noad")
local fence_id = node.id("fence")
local subtypes = { fence = table.swapped(node.subtypes("fence")) }
local pt = 2^16
local sublist_has_sup = {}
function kern_right_fence(head, level)
for v in node.traverse(head) do
if v.id == noad_id and v.nucleus and v.nucleus.list then
-- Descend into sublists
sublist_has_sup[level] = v.sup and true or false
kern_right_fence(v.nucleus.list, level+1)
sublist_has_sup[level] = false
elseif v.id == fence_id and v.subtype == subtypes.fence.right and sublist_has_sup[level-1] then
-- For a fence with a superscript insert kern
local kern = node.new("kern")
kern.kern = 10*pt
node.insert_after(head, v, kern)
end
end
return head
end
luatexbase.add_to_callback("mlist_to_hlist",
function(head, style, penalties)
print("===mlist_to_hlist===")
head = kern_right_fence(head, 0)
return node.mlist_to_hlist(head, style, penalties)
end
,"kern right fence")
\end{luacode*}
\begin{document}
\[ \left(y\right)^2 \]
\[ \begin{pmatrix*}[r] 1 & 0 \\0 & 1 \\ -1 & 0 \end{pmatrix*}^T \]
\end{document}
为了便于说明,我在这里插入了巨大的正字距。