请解释一下 bytefield、unicode-math 和 mathtools 之间的奇怪交互

请解释一下 bytefield、unicode-math 和 mathtools 之间的奇怪交互

bytefieldmathtools与和结合使用时会产生不同的结果unicode-math 一起使用时。这是我的“好” MWE:

% !TEX TS-program = XeLaTeX
\documentclass[a4paper]{article}
%\usepackage{mathtools}    % This breaks things
%\usepackage{unicode-math} % when used with this
\usepackage{bytefield}
\begin{document}
\begin{bytefield}{16}
  \bitheader{0,15}\\
  \begin{rightwordgroup}{Header}    
  \bitbox{16}{Without}\\
  \bitbox{16}{Etc}
  \end{rightwordgroup}\\
\end{bytefield}
\end{document}

如果我按原样运行它,我会得到:

好结果

现在,如果我取消注释两个都标记的线,支架的对齐变得不稳定:

在此处输入图片描述

两者unicode-math任一mathtools 独自的不会产生这种效果。

请问有什么想法吗?


amsmath正如@Qrrbrbirlbel 所说,您可以通过交换来获得完全相同的行为mathtools

答案1

编辑2:完全重写,并对所有复杂之处进行基本完整的解释。

这是因为XeTeX 如何决定使用哪种 fontdimen 参数的复杂性,正如 Heiko 在回答该问题时指出的那样。在另一个回答中,Khaled Hosny 确认细节存在错误。

要使括号垂直居中,bytefield请将表示数学轴位置的\fontdimen22设置\textfont2为 0pt。这对于旧式字体非常有效,但对于 OpenType 字体则不然,因为 OpenType 字体有许多其他参数可供使用(并且参数的顺序不同)。

如果unicode-math没有加载,则使用的字体是旧式字体,并使用正确的 fontdimen 参数。

如果unicode-math加载了,那么数学字体就是 OpenType 字体(默认情况下latinmodern-math.otf),因此我们可能会遇到问题,但 XeTeX 能够重新映射 fontdimen 参数以使 TeX(和bytefield)满意。这需要在检索值和存储值时进行映射。到目前为止,一切(?)都运行良好。

现在让我们把话题转到一边。当将数学列表转换为框时(如 TeXbook 附录 G 中所述),(Xe)TeX 会查看各种数学字体的 fontdimen 参数,最重要的是\textfont2(以及\script(script)font2,以及\...font3类似物)。嗯,实际上,我不确定 XeTeX 会查看哪些参数。当然,它需要根据字体类型考虑不同的参数,而 Khaled Hosny 似乎在说,最后定义的字体会经过测试以确定它是 OpenType 还是旧式字体。这是一个错误。

只要我们不在数学模式中加载任何其他字体,最后定义的字体就有正确的类型,并且正确的 fontdimen 参数(设置为 0pt)用于放置数学轴。如中的示例我上面提到的问题如图所示,将一些文本存储在框中,即使不对框进行任何操作,也不执行任何 (TeX) 分配,也会对设置数学材料产生影响。考虑到错误的性质,我们可以预料到,“框中的文本”设置的字体会影响外部结果,因为它会改变最后一种字体是 OpenType 还是旧式字体。

现在,amsmath在哪里出现?它定义了\resetMathstrut@,重建一个高度和深度等于一条线的框(类似于\strut,但用于数学模式),并在 处调用该函数\every@math@size(不确定具体何时调用,但在数学模式中的某个地方)。定义不是很清楚,但让我解释一下。

\def\resetMathstrut@
  {%
    \setbox \z@ \hbox
      {%
        \mathchardef \@tempa \mathcode `\(\relax
        \def \@tempb ##1"##2##3{\the \textfont "##3\char "}%
        \expandafter \@tempb \meaning \@tempa \relax
      }%
    \ht \Mathstrutbox@ \ht \z@
    \dp \Mathstrutbox@ \dp \z@
  }

代码将包含括号的水平框存储到框中\z@(0 的“简写”),然后将的高度和深度设置为新框 的高度\ht和深度,使该框的垂直尺寸与括号相同。括号是如何排版的?嗯,由于 TeX 显示标记的方式(即和十六进制数字……代码会因数学活动括号而失败?),的数学代码被转换为十六进制。然后加载数字(十六进制),即 的数学字体(从十六进制数字中提取),并排版该字体中作为右括号的字符(再次使用数学代码的一部分)。在这个过程中,没有进入数学模式,但在框内选择了数学字体。\dp\Mathstrutbox@\z@(\meaning\mathchar\@tempa\mathchar"amsmath\textfont##3(

现在我们准备好了。amsmath加载时,unicode-math会进行额外的重新定义,特别是\resetMathstrut@,这会变成

\def\resetMathstrut@
  {%
    \setbox \z@ \hbox {$($}%
    \ht \Mathstrutbox@ \ht \z@
    \dp \Mathstrutbox@ \dp \z@
  }

该定义要简单得多,并且与版本基本相同amsmath:用数学字体排版括号,并使用其高度和深度来设置的尺寸\Mathstrutbox@。天真地说,唯一可能发生的情况是\everymath令牌寄存器(由 LaTeX 重命名为\frozen@everymath)包含全局分配,这与周围的数学发生冲突(好吧,\everyhbox也可以发挥作用,但实际上没有)。这将是 LaTeX 中的一个错误。但 LaTeX 已被广泛使用,并且代码现在对嵌套数学模式具有很强的鲁棒性(对此有有趣的评论)。因此我有点困惑,当我发现即使在内部数学模式之前清空也无法解决干扰时,source2e我更加困惑。\frozen@everymath

当然,读完上述内容,精明的读者可以猜到发生了什么,比我快十几个小时:嵌套数学运算不应该对周围的数学列表产生任何影响,但由于 XeTeX 错误,它混淆了 fontdimen 参数。

由于我不完全了解 XeTeX 行为的细节,我不确定我之前提出的修复方法(恢复加载\resetMathstrut@后的旧定义unicode-math)是否在所有情况下都有效或恰好有效。我不知道是否可以修补bytefield或任何其他宏以使您的文档正常工作。根据 XeTeX 所做测试的细节以及字体,可能无法在宏级别纠正行为。

与此同时,这里有一个可能有效的代码,可以\resetMathstrut@先保存unicode-math,然后再恢复。

\documentclass[a4paper]{article}
\usepackage{fixltx2e}
\usepackage{mathtools}
\makeatletter
\let\oldresetMathstrut@\resetMathstrut@
\makeatother
\usepackage{unicode-math}
\makeatletter
\let\resetMathstrut@\oldresetMathstrut@
\makeatother
\usepackage{bytefield}
\begin{document}
\begin{bytefield}{16}
  \bitheader{0,15}\\
  \begin{rightwordgroup}{Header}
  \bitbox{16}{Without}\\
  \bitbox{16}{Etc}
  \end{rightwordgroup}\\
\end{bytefield}
\end{document}

相关内容