在这本书的第 14 页TeXbook,练习 4.3 是
定义一个控制序列
\ic
,使得'\ic c
'将字符的斜体校正c
放入 TeX 的寄存器中\dimen0
。
答案是\def\ic#1{\setbox0=\hbox{#1\/}\dimen0=\wd0\setbox0=\hbox{#1}\advance\dimen0 by -\wd0}
我知道了\def\ic#1{<stuff>}
定义一个包含内容的命令。但是中\ic
的内容如何理解?我甚至不知道这个练习讲的是什么。在这个练习中, 的作用是什么?为什么要这样做?{<stuff>}
\def\ic#1{\setbox0=\hbox{#1\/}\dimen0=\wd0\setbox0=\hbox{#1}\advance\dimen0 by -\wd0}
\dimen0
其他编程语言中,语句比较长的时候经常会断句,断句的时候会有分隔符,比如Perl的分号,Python的tab,TeX好像没有分隔符?
这也行得通吗?\def\ic#1{\setbox0=\hbox{#1\/}\dimen0=\wd0\setbox1=\hbox{#1}\advance\dimen0 by -\wd1}
答案1
这回答了问题的早期版本,其中明确指出了 OP 希望了解 Knuth 在电子书. 它没有解释如何利用当前的 TeX 安装来最好地确定字符的斜体校正。
买者自负 ...
\def\ic#1{\setbox0=\hbox{#1\/}\dimen0=\wd0\setbox0=\hbox{#1}\advance\dimen0 by -\wd0}
Knuth 的基本策略是:找到字符的宽度加上其斜体校正,然后减去不带斜体校正的字符的宽度,以获得其斜体校正的宽度。
#1\/
斜体校正后的字符是
\hbox{#1\/}
放入水平框(即,就像在水平模式下排版,但没有排版任何内容)
\setbox0=\hbox{#1\/}
框 0(只是一个框)设置为等于水平框。
\dimen0=\wd0
将尺寸寄存器设置\dimen0
为等于框 0 的宽度。因此,这包含字符的宽度加上其斜体校正。
\hbox{#1}
将角色放入水平框中,仅此而已
\setbox0=\hbox{#1}
并将框 0 设置为等于这个水平框。
\wd0
框 0 的宽度,现在是没有斜体校正的字符的宽度。
\advance\dimen0 by -\wd0
从维度寄存器中存储的值中减去该值\dimen0
。因此\dimen0
现在包含
width of character + width of italic correction - width of character
因此
\def\ic#1{\setbox0=\hbox{#1\/}\dimen0=\wd0\setbox0=\hbox{#1}\advance\dimen0 by -\wd0}
表示将斜体校正\ic#1
的宽度存储到尺寸寄存器中。#1
\dimen0
或者更准确地说,中的值\dimen0
将近似于当前上下文中的斜体校正#1
。实际值将取决于字体、大小等,但它也只是近似值,因为 TeX 的计算只是近似值。通常,它们对于排版来说足够准确,但有时差异会成为问题。
答案2
在编写 TeXBook 时,为了获取字符的高度、宽度或斜体校正等指标,您需要将它们设置在一个盒子中并测量盒子大小,但 e-Tex 已经存在几十年了,并且可以通过原始长度命令直接访问这些长度,而这些命令不需要盒子分配,因此您可以直接将它们用作长度\typeout
等\setlength
。
\documentclass{article}
\begin{document}
\itshape
\typeout{\the\fontcharic\font`c}
\setlength{\dimen0}{\fontcharic\font`c}
\typeout{\the\dimen0}
\typeout{\the\fontcharic\font`f}
\setlength{\dimen0}{\fontcharic\font`f}
\typeout{\the\dimen0}
\end{document}
在分配给 a 之后,显示当前(斜体)字体中的c
和的斜体校正f
\typeout
\dimen0
它会产生一个日志:
0.56528pt
0.56528pt
2.11945pt
2.11945pt
答案3
我们从结尾开始。为什么\dimen0
?因为它是一个可以存储长度的寄存器。在实际应用中,它将是一个正确分配和命名的寄存器,但出于练习的目的,它\dimen0
与其他寄存器一样好。
为什么语句没有终止?因为没有像其他解释型语言(如 Perl 或 Python)那样的语句。TeX 语言主要旨在排版文本例如,使用分号表示“终止语句”会导致歧义,即如何解释这种符号:它是文本分号还是语句终止符?
在 Metafont 的姊妹语言中,分号用于终止语句,该语言的目的不是排版,而是构建字体。你必须接受 TeX 语言是诡异的。
现在,让我们看看提出的解决方案,即
\def\ic#1{\setbox0=\hbox{#1\/}\dimen0=\wd0
\setbox0=\hbox{#1}\advance\dimen0 by -\wd0 }
Knuth 的风格非常紧凑,他努力将代码压缩到尽可能少的行中。但你可以自己将“语句”拆分成更易读的块:
\def\ic#1{%
\setbox0=\hbox{#1\/}%
\dimen0=\wd0
\setbox0=\hbox{#1}%
\advance\dimen0 by -\wd0
}
注意行尾是否存在%
,你应该训练在必要时放置它们,在不需要时省略它们:请记住,除非用 掩盖,否则行尾算作空格%
。
这个想法是测量包含参数以及斜体校正(最后一个字符)的框的宽度并将其存储在中\dimen0
。然后测量没有斜体校正的相同文本,并从当前的值中减去宽度\dimen0
。
不将%
其视为语句终止符!它不是。为什么我没有在行尾使用它\dimen0=\wd0
?因为\wd
希望在它后面看到一个整数,而 TeX 会在数字序列后寻找空格以知道它何时结束,并在此过程中执行宏扩展;规则将忽略尾随空格。引用自第 208 页
为了获得最佳效果,总是在数字常量后面加一个空格;这个空格告诉 TeX 该常量已经完整,并且这样的空格永远不会“到达”输出。