最近,我在使用 LaTeX 时遇到了一个令人头痛的问题(实际上我使用 XeLaTeX 进行编译,但我认为这个问题是独立的),原因是我在加载数学字体之前无意中尝试修改它的尺寸。
我的期望应该是什么?
- LaTeX 应该已经加载它了。
TikZ (pgf)
应该已经加载了。\fontdimen
应该已经加载了。\textfont2
应该已经加载了。- 用户应该已经加载它了。(我以前从未被要求做这样的事情。据我所知,没有任何地方记录我必须这样做。)
根据这个特定问题的答案,我想确定标准化的编程实践。LaTeX 和软件包编写者的标准实际上是什么(软件包是否应始终包含字体检查)?是否应针对步骤 1 至 4 中的任何步骤报告错误?
日志中的失败消息:
!Font \nullfont has only 7 fontdimen parameters.
我知道这条消息的意思。pgf
(TikZ
)在执行键之前切换到数学模式baseline
,其中包括对尚未加载的字体(数学字体)的修改。我知道自从实施 LaTeX2e 以来,字体不再加载,直到需要它们时.fontspec
立即加载字体(如果我错了请纠正我)。
Ijon Tichy 对 LaTeX2e 自 LaTeX 2.09 以来的变化发表了强有力的言论(这让我和同事笑了。这家伙肯定知道自己在说什么!):
您必须知道,当首次使用字体时,将从 LaTeX 的 NFSS2 和 LaTeX2e 中提取的字体首先被加载。以前,还有 LaTeX 2.09,据我所知还有其他人。通过 bzw 格式的 \font-Anweisungen 可以直接写入字体。请参阅文档进度。接下来可以解决与旧 LaTeX-2.09 版本相关的问题,这些新 LaTeX 将被使用。
翻译: 必须注意的是,自 NFSS2 以来,或者最近自 LaTeX2e 以来,LaTeX 中的 tfm 字体文件仅在首次需要时加载。据我所知,LaTeX 2.09 中的实现方式与 LaTeX2e 中的实现方式不同。在 LaTeX 2.09 中,字体直接通过格式中的 \font 指令以及文档前言加载。因此,使用 LaTeX 2.09 编码样式的软件包可能会在 LaTeX2e 中导致问题。
示例代码
\documentclass{article}
\usepackage{tikz} % Absolute positioning, advanced vector graphics
\newcommand{\ampel}[1]{% input: color
\begin{tikzpicture}[baseline=-\the\dimexpr\fontdimen22\textfont2\relax] %<- Magical vertical alignment code that gives LaTeX a hiccup.
\node[yshift=.4mm,align=center,fill=#1, shape=circle] (O)at (0,0) {};
\end{tikzpicture}
}%
\begin{document}
\ampel{green!70!black}
\end{document}
解决方法
可以明确加载数学字体。
- 添加
$\null$
于\begin{document}
在序言中添加以下内容:
\makeatletter \AtBeginDocument{\sbox\@tempboxa{$\null$}} \makeatother
明确检查数学字体(参见 egreg 的答案)
\makeatletter \AtBeginEnvironment{tikzpicture}{\check@mathfonts} \makeatother
我想在缩小问题范围的同时补充一些我的发现。我有同一份文档的两个版本,一个用德语写成,另一个用英语写成。英语版排版很好。德语版排版不行。我发现英语版\url{}
中有一个脚注,其中包括 ,而德语版中却注释掉了。这\url
发生在第一次\ampel
调用之前。这意味着\url{}
加载了数学字体。
答案1
在使用之前\textfont2
,您必须确保它已被定义,只有在 LaTeX 排版了至少一个公式(即使是一个空公式)之后,当前字体大小。这是因为它想要支持任意字体大小的数学运算,同时也避免浪费数学组。
在当前条件下,实际负责定义数学字体的命令是\check@mathfonts
:
\documentclass{article}
\usepackage{tikz}
\usepackage{etoolbox}
\makeatletter
\AtBeginEnvironment{tikzpicture}{\check@mathfonts}
\makeatother
\newcommand{\ampel}[1]{% input: color
\begin{tikzpicture}[baseline=-\the\dimexpr\fontdimen22\textfont2\relax]
\node[yshift=.4mm,align=center,fill=#1, shape=circle] (O)at (0,0) {};
\end{tikzpicture}%
}
\begin{document}
X\ampel{green!70!black}X
\Huge
X\ampel{green!70!black}X
\end{document}
使用execute at begin picture
并不好,因为可选参数被评估前图片开始,钩子被检查。不,如果您打算更改文档中的字体大小,仅\sbox0{$$}
在文档开头执行(添加无关紧要)是不够的:例如,您可能会进入一个部分标题(前面有,但这是另一回事):尝试使用该方法,第二种情况下的结果,在之后,会出现错误。\null
\ampel
\protect
\Huge
答案2
如果我可以根据 Joseph Wright 对 egreg 的回答的评论来贡献自己的答案的话:
谁负责在 LaTeX(或 XeLaTeX)中加载字体?(如果是我的,我怎么知道哪些字体?)
- 加载字体通常是 LaTeX 或包的责任。
- 当使用 TeX 原语时,这是用户的责任。
\textfont2
是原始的,因此必须实施检查由用户查看字体是否已加载。