为什么 \leaders 和 \mkern 在不同的字体大小下工作异常?

为什么 \leaders 和 \mkern 在不同的字体大小下工作异常?

抱歉,我很难为这个问题确定一个好的标题。

最小测试代码:

\documentclass{minimal}
\usepackage{lipsum}
\begin{document}
foo
{\fontsize{18}{18}\leaders\hbox{$\mkern 10000mu.\mkern 10000mu$}\hfill}
bar

\lipsum
\end{document}

如果我编译这个,bar结果\lipsum就消失了。这太神奇了。而且,

  • 如果我用 15 或 20 替换参数\fontsize,一切都正确!

  • 如果我替换\hbox{$\mkern 10000mu.\mkern 10000mu$}为其他内容,例如删除一个\mkern 10000mu,结果可能也正确。

我知道这\fontsize会改变单位长度。但我完全不明白发生了什么。

以下是 Plain TeX 的一个例子:

% fine
% Width of hbox less than \maxdimen
a\leaders\hbox{\kern8000pt.\kern8000pt}\hfill b

text text
\vfill\eject

% BAD: text after the leaders is gone
% Width of hbox more than \maxdimen
a\leaders\hbox{\kern10000pt.\kern10000pt}\hfill b

text text
\vfill\eject

% fine?
% Width of hbox more than \maxdimen
a\leaders\hbox{\kern12000pt.\kern12000pt}\hfill b

text text
\vfill\eject

\bye

我想知道为什么 20000pt 宽度的框会产生错误输出,而 24000pt 宽度的框似乎正确。我知道这是溢出,因此不可能是 TeX 的错误,但发生了什么?


背景

该代码来自tocloft包。现在我相信这是 的一个错误tocloft。在 中tocloft,它定义了

\providecommand{\cftdotfill}[1]{%
  \leaders\hbox{$\m@th\mkern #1 mu\hbox{\cftdot}\mkern #1 mu$}\hfill}

并且\cftnodots10000。然后这个测试文件失败:

\documentclass{article}
\usepackage{tocloft}
\renewcommand{\cftsecleader}{\fontsize{16}{19}\cftdotfill{\cftnodots}}
\usepackage{lipsum}

\begin{document}

\contentsline{section}{TEST}{1}

\lipsum
\end{document}

\cftdotfill我可以通过重新定义为来修复该错误

\renewcommand{\cftdotfill}[1]{%
  \leaders\hbox to #1\p@{\hss\cftdot\hss}\hfill}

但这个虫子还是让我震惊。

答案1

宽度

\hbox{$\mkern10000mu.\mkern10000mu$}

当 LaTeX 使用的字体为 14.4pt 时,其宽度为 16003.67247pt;而当您要求 17.28pt 大小时,框的宽度将变为 19204.52904pt,这超过了所有宽度,\maxdimen所以一切都出错了。

请注意\fontsize{18}{18}\selectfont\selectfont公式开始时隐式完成)选择标准字体,字体大小为 17.8pt。

当您要求 15pt 时,选择的字体为 14.4pt。

很奇怪,这种\fontsize{20}{20}行为是正常的(框宽 23050.07462pt)。但我认为这只是好奇而已。

我想说这是一个疏忽托克洛夫特

如果我加载现代(具有可缩放字体),常规和歪斜之间的界限是 14.68181pt = 962187sp;而 14.68182pt = 962188sp 时的行为很奇怪。

当字体大小达到 19.85608pt = 1301288sp 时,该行为仍然很奇怪,当字体大小达到 19.85609pt = 1301289sp 时,该行为恢复正常。

tocloft 的解决方法

避免该问题的一种方法是重新定义\cftnodots

\renewcommand\cftnodots{100mu\gobbleeight}
\newcommand\gobbleeight[8]{}

这样,\cftdotfill{\cftnodots}将扩展至

\leaders\hbox{$\m@th\mkern \cftnodots mu\hbox{\cftdot}\mkern \cftnodots mu$}\hfill

第一个\mkern将扩大第一个\cftnodots,结果为

\mkern100mu\gobbleeight mu\hbox{\cftdot}\mkern \cftnodots mu

并计算参数,我们发现最终得到

\leaders\hbox{$\m@th\mkern100mu$}\hfill

它不打印任何内容(实际上一些框只包含空白,但这比不可预测的行为要好)。代码托克洛夫特应该被修复。

相关内容