定义一个控制序列 \ic,使得'\ic c'将字符 c 的斜体校正放入 TeX 的寄存器 \dimen0

定义一个控制序列 \ic,使得'\ic c'将字符 c 的斜体校正放入 TeX 的寄存器 \dimen0

在这本书的第 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 该常量已经完整,并且这样的空格永远不会“到达”输出。

相关内容