抱歉,我很难为这个问题确定一个好的标题。
最小测试代码:
\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}
并且\cftnodots
是10000
。然后这个测试文件失败:
\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
它不打印任何内容(实际上一些框只包含空白,但这比不可预测的行为要好)。代码托克洛夫特应该被修复。