是否有一个 LuaLaTeX 解决方案可以调整大分隔符上的上标字距?

是否有一个 LuaLaTeX 解决方案可以调整大分隔符上的上标字距?

上标可以位于大括号的很远处,某些字体的情况比其他字体更远。我正在寻找一种基于 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}

在此处输入图片描述

因此,我有两个问题:

  1. 我的 MWE 中的 Lua 方法来处理定界符大小未知且可变的情况吗?
  2. 是否可以创建一个适当的字距调整功能,通过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}

为了便于说明,我在这里插入了巨大的正字距。

在此处输入图片描述

相关内容