众所周知,TeX 以自动化方式提供了出色的数学格式化功能。然而,有些地方存在明显的缺陷,人们要么接受,要么根据具体情况手动改进。
在这方面,最大的问题之一是 TeX 对子公式的处理(即括号组内的材料,例如和索引,以及任何顶层组)。TeX 总是将此类子公式设置为自然宽度,即使整个公式会受到严重的拉伸或收缩。例如,请考虑以下(不太合理)示例:
\documentclass{article}
\newlength\x
\begin{document}
\newcommand\formula{$ a+\mathbf{b+c}+d+e+f = \sum_{i=1}^{n-x-y-z} x_{i+j}$}
\settowidth\x{\formula}
\hbox to \x{\formula} % natural width
\addtolength\x{-20pt}
\hbox to \x{\formula} % now shrink it a lot
\addtolength\x{100pt}
\hbox to \x{\formula} % now stretch a lot in the opposite direction
\end{document}
这里的公式在下标和上标中有许多明显的子公式,但为了说明起见,我还通过添加了一个子公式\mathbf
。当然,以这种方式使用\mathbf
是错误的!!!(它不应该应用于多个符号),但我相信你会在文档中找到它。无论如何,{b+c}
在这里都会有同样的效果。现在你认为如果我们运行这个会发生什么?
这:
可以看出,当公式的其余部分受到拉伸或收缩时,自然“盒装”的子公式是非常错误的。
直到最近,TeX 引擎的后继者才解决了这个问题。随着 LuaTeX 开放了 TeX 的很多内部功能,我曾希望情况会有所不同。然而,在研究手册后,我的结论是,这个领域(至少到目前为止)尚未得到解决(或考虑)。
据我所知,在 LuaTeX 中解决此问题的唯一方法是使用回调mlist_to_hlist
。然而,这实际上意味着替换整个数学排版算法,这当然可以解决问题,但是……但需要的不是这个(因为该算法的 99% 都接近完美),而是增加支持,而不仅仅是将子公式框在其自然宽度上。
文字太长了...下面是简短的问题:
- 这个分析正确吗,还是我忽略了什么?
- 以防有人知道:是否有计划调查子公式问题并最终为其提供支持?(它没有列在数学的“待办事项”中)
如果有人怀疑我谈论“这个子公式问题”就好像它是一个已知的东西……它是的,它早在E-TeX:未来 TeX 扩展指南当时进行了一些彻底的(如果不是激烈的)讨论。
答案1
看起来答案如下:
- 该问题(在 TeX 原始程序中已经存在)尚未被包括 LuaTeX 在内的任何 TeX 后继者解决或处理。
LuaTeX 确实可以替代全部数学处理由私有代码完成,但这更像是“拆掉房子再建新房”,并没有真正保证。毕竟 TeX 的算法在大多数方面都非常棒。很遗憾,但也许可以理解,因为它需要拆开数学格式化程序的处理逻辑并重新组织它,才能改进其中的一小部分。
答案2
这是一个老问题,但我偶然发现了它,我认为现在可能有办法让它发挥作用,使用 luametatex 引擎*. 这是通过拆箱来完成的。(这不适用于平方根、分数或下标/上标。)我们首先看一下图片。
这里,
- 只需设置即可
\hbox{word word $a + {\bf b + c} + \left(d + e\right) + f + \sqrt{g + h} + \frac{a + b}{c + d} = \sum_{i=1}^{n-x-y-z} x_{i+j}$ word word}
。 - 设置为
\hbox spread 4cm {word word $a + {\bf b + c} + \left(d + e\right) + f + \sqrt{g + h} + \frac{a + b}{c + d} = \sum_{i=1}^{n-x-y-z} x_{i+j}$ word word}
。请注意,扩展在粗体部分不起作用。但它在围栏部分内起作用。如上所述,它不适用于平方根、分数或指数。 - 设置为
\hbox spread 4cm {word word $a + \mathatom unpack \mathordinarycode {\bf b + c} + \left(d + e\right) + f + \sqrt{g + h} + \frac{a + b}{c + d} = \sum_{i=1}^{n-x-y-z} x_{i+j}$ word word}
。因此,粗体部分也会被展开。它被解包,然后被打包为一个 ord。 - 设置为
\hbox spread 4cm{word word $a + \mathbf{b + c} + \left(d + e\right) + f + \sqrt{g + h} + \frac{a + b}{c + d} = \sum_{i=1}^{n-x-y-z} x_{i+j}$ word word}
。这表明解包和重新打包是在 中完成的\mathbf
。 - 设置为
\hbox spread -2cm{word word $a + \mathbf{b + c} + \left(d + e\right) + f + \sqrt{g + h} + \frac{a + b}{c + d} = \sum_{i=1}^{n-x-y-z} x_{i+j}$ word word}
。我们看到东西也可以打包在一起。 - 设置为
\hbox spread 4cm{word word $a + \mathatom unpack leftclass \mathordinarycode rightclass \mathbinarycode {\bf c + d} + \left(d + e\right) + f + \sqrt{g + h} + \frac{a + b}{c + d} = \sum_{i=1}^{n-x-y-z} x_{i+j}$ word word}
。这不是我们想要的,但它表明,当我们重新打包时,我们可以说盒子在左边和右边的行为应该有所不同。在其他情况下可能有用。在这里,表现得像一个二进制的右边,使加号变成一个 ord,并且那里的间距是错误的。
拆包和重新打包的一个好处是,可以有多行公式,这些公式会在围栏内中断。示例(改编自这个老问题):
此公式设置为
\defineformula[XYZ][
split=text,
textalign=slanted,
spaceinbetween=.5\lineheight,
strut=yes,
distance=1em,
]
\startXYZformula[margin=3em]
s_{i}^{G}
=
\min
\left\{
\sqrt{
\min\left[(x_{i}^{G} - x)^2, (w_{T} - x_{i}^{G} - x)^2\right] + y
}
,\breakhere
\sqrt{
\min\left[(x_{i}^{G} - x)^2, (w_{T} - x_{i}^{G} - x)^2\right]
+
\min\left[(y_{i}^{G} - y)^2, (h_{T} - y_{i}^{G} - y)^2\right]
}
\right\}
\stopXYZformula
*事实上,\mathbf{b + c}
在 luatex 上下文中也可以工作。但解包机制是 luametatex 中的新机制。我没有安装 mkii,所以我不知道它是否也在 pdftex 上下文中工作。
答案3
有一种方法可以做到这一点,unicode-math
因为 Unicode 数学中的粗体字母是相同字体的不同字母,而不是不同字体的字母:
\documentclass{article}
\usepackage{unicode-math}
\setmathfont{XITS Math}
\newlength\x
\begin{document}
\newcommand\formula{$ a+