把正文换成 Times,数学部分却仍是 Computer Modern——在 LaTeX 里挑选 数学字体 时人人都会先撞上这个问题。更麻烦的还在后头。载入 mathptmx,以为整篇文档已经统一成 Times,再用 pdffonts 检查这份 PDF:CMEX10 依然被嵌入其中。求和号和积分号至今仍是高德纳的字体。本页把 pdfLaTeX 的数学字体宏包(newtxmath、mathpazo、fourier、kpfonts 等)与 XeLaTeX、LuaLaTeX 上的 unicode-math 加 \setmathfont 放在一起比较,每次都数一数究竟有哪些字体真的进了 PDF。数学字母表命令(\mathbb、\bm 之类)另有专页;这里要回答的是如何为整篇文档挑定数学书体。
换了正文字体,数学并不会跟着换
在 LaTeX 中,正文字体与数学模式字体由 完全独立的两套体系 管理。所以用一行 \usepackage{...} 换掉正文书体后,变量、运算符和下标在你另行指定之前依旧是 Computer Modern。这是设计,而非疏忽。数学字体必须携带正文字体根本没有的信息——符号的高度与数学轴位置、让根号和括号能够加长的「延伸部件」、下标下移的距离、分数线的粗细,共几十个尺寸。你无法直接拿正文书体来排数学。因此更换数学书体,实际上是 取来一套专为此打造的字体。
究竟嵌入了什么 —— 用 pdffonts 数一数
一个数学字体宏包究竟有没有真正替换 Computer Modern,数一数 PDF 中嵌入的字体就一清二楚。把文件交给 Poppler 的 pdffonts(多数环境里随 poppler-utils 提供)即可。用 TeX Live 2024 的 pdfLaTeX 编译同一份短文档——一行正文,加上一个含积分、求和、希腊小写与希腊大写的行间公式——结果整齐地分成三类:彻底替换的(newtx、newpx、fourier、kpfonts、mathdesign)、留下 Computer Modern 的(mathptmx、mathpazo、eulervm),以及什么都不做时理所当然的全篇 Computer Modern。
# the only honest way to check which math font you actually shipped
pdflatex paper.tex
pdffonts paper.pdf
# name type emb sub uni
# ------------------------------------ ----------------- --- --- ---
# QSPJFW+NimbusRomNo9L-Regu Type 1 yes yes yes
# CZKGAS+CMR10 Type 1 yes yes yes <- still Computer Modern
# UYVLXV+CMEX10 Type 1 yes yes yes <- the big operators| 载入什么 | pdffonts 报告的数学侧字体 | CM 是否残留 |
|---|---|---|
(none) | CMR10 CMMI10 CMSY7 CMEX10 CMMI7 CMR7 | 全是 CM;默认的 Computer Modern math |
mathptmx | NimbusRomNo9L StandardSymL CMR10 CMSY10 CMMI10 CMEX10 | 会。+ 与 = 来自 CMR10,\sum、\int 来自 CMEX10 |
mathpazo | URWPalladioL PazoMath CMR10 CMSY10 CMEX10 | 会;大型运算符仍是 CMEX10 |
newtxmath | NewTXMI txsys txmiaX txexs NewTXMI7 | 不会。正文侧得到的是 TeXGyreTermesX-Regular |
newpxmath | NewPXMI pxsys pxmiaX txexs | 不会;扩展字体与 newtx 用的是同一个 txexs,嵌入的子集完全相同 |
fourier | Fourier-Math-Symbols / -Extension / -Letters | 不会;正文为 Utopia。真正的一行搞定 |
kpfonts | Kp-Regular Kp-Italic Kp-Ex Kp-Sy | 不会;正文和数学全是 Kp 一族 |
eulervm | EURM10 EUFM10 EUEX10 加 CMR10 CMR7 | 会;字母、符号与大型运算符都换成 Euler,只有 operators 族(数字、直立罗马体)沿用正文书体 |
mathdesign | 完整的 MathDesign-CH-Regular 一套 | 不会;用 [charter] 时正文是 CharterBT |
传统方式 —— 在 pdfLaTeX 下把正文与数学配对
pdfLaTeX 下更换数学书体的标准做法,是 成对载入正文宏包与数学宏包。今天最容易推荐的是 newtx 系列:把 \usepackage{newtxtext} 与 \usepackage{newtxmath} 并排写上,就得到 Times 风格的正文与相配的数学。不过与名字相反,newtxtext 嵌入的并非 Times 本身,而是 TeX Gyre Termes 的扩展版——pdffonts 显示为 TeXGyreTermesX-Regular。Palatino 则用 mathpazo,或者 newpxtext 加 newpxmath。想用 Charter 的话请注意:并不存在 xcharter-math.sty ——在 pdfLaTeX 下它是作为选项调用的,写成 \usepackage[xcharter]{newtxmath};而 OpenType 版的 XCharter-Math.otf 要通过下一节的 \setmathfont 使用。同样的写法还能配合 libertine、libertinus、cochineal、erewhon、stix2、noto 等众多正文书体,这正是 newtxmath 的长处。
若想用一行同时换掉正文和数学,fourier(Utopia 正文加 Fourier 数学)与 kpfonts(Kepler 一族)是稳妥之选;上文实测中两者都没有留下任何一个 Computer Modern 字体。要提防的错误,是把 只管正文的宏包 当成数学宏包。例如在 pdfLaTeX 下载入 libertinus,数学仍然是 CM:PDF 里 LibertinusSerif-Regular 与 CMMI10、CMR10、CMEX10 并存。这一项实测记录在西文字体那一页。另一个经典事故是 把不成对的正文与数学混在一起。让 newtxtext(Times 风)搭配 newpxmath(Palatino 风),两套字体都能正常工作,但纸面上字宽与灰度都对不齐,看着别扭。
% --- Times-like text and matching math (the easy recommendation) ---
\usepackage{newtxtext}
\usepackage{newtxmath}
% --- Palatino text and math, in one package ---
% \usepackage{mathpazo}
% --- one line for both, with no Computer Modern left behind ---
% \usepackage{fourier} % Utopia text + Fourier math
% \usepackage{kpfonts} % the Kepler family
% --- match math to another text face through newtxmath ---
% \usepackage{libertinus}
% \usepackage[libertinus]{newtxmath}现代方式 —— unicode-math 与 \setmathfont
在 XeLaTeX 或 LuaLaTeX 上,只要载入 unicode-math 并写一行 \setmathfont{…},就能用 一个 OpenType 数学字体 排出全部数学内容,把成堆的宏包一扫而空。引擎限制是实打实的:在 pdfLaTeX 下写 \usepackage{unicode-math} 会停在 ! Package unicode-math Error: Cannot be run with pdftex!,随后是 (unicode-math) Use XeLaTeX or LuaLaTeX instead.。让它成立的是 OpenType 的 MATH 表——字体文件内部的一个标准化区块,装着 TeX 排数学所需的全部尺寸:分数线粗细、下标下移量、根号上方的留白、可伸缩括号如何由部件拼接。正因为这些信息住在字体里,换字体就等于连排版参数一起换。若完全不指定字体,默认载入的是 Latin Modern Math。
载入顺序上有一颗地雷。若在 unicode-math 之后 载入 amssymb,就会得到 四条同样形态的错误,以 ! LaTeX Error: Command \eth already defined. 打头,接着是 \smallsetminus、\digamma、\backepsilon(在 TeX Live 2024 上实测)。原因是 unicode-math 已经从 Unicode 一侧先行定义了这些符号,而 amssymb 试图重新定义时发生冲突。把顺序倒过来,写成 amsmath → amssymb → unicode-math,同一份文档就能毫无错误地通过。记住「unicode-math 永远放在字体相关宏包 之后」,大部分事故都能避免。
| OpenType 数学字体 | 性格及与之相配的正文书体 |
|---|---|
Latin Modern Math | Computer Modern 系谱;默认载入。搭配 Latin Modern Roman |
TeX Gyre Termes Math | Times 风;搭配 TeX Gyre Termes。另有 Pagella、Bonum、Schola、DejaVu 版 |
STIX Two Math | 面向科学出版,收录极广;搭配 STIX Two Text。macOS 自带该字体 |
Libertinus Math | Libertinus Serif 的数学配套——这是 pdfLaTeX 给不了的组合 |
XCharter-Math | Charter 系。并无 xcharter-math.sty;通过 \setmathfont 使用其 OTF |
NewCMMath-Regular | New Computer Modern 的数学版;保留 CM 外观而覆盖面广得多 |
Fira Math | 无衬线数学字体;在幻灯片和海报中让数学与正文一致时很有用 |
Asana-Math | 偏 Palatino 的数学字体;与 STIX 衍生的 XITS 同为老将 |
The font "Latin Modern Math" cannot be found —— XeLaTeX 与 LuaLaTeX 的差别
同一句 \setmathfont{Latin Modern Math},在 LuaLaTeX 下通过,在 XeLaTeX 下却以 ! Package fontspec Error: The font "Latin Modern Math" cannot be found. 失败——这是在装有 TeX Live 2024 的 macOS 上实测的结果。原因在于两个引擎解析字体名的方式不同。LuaTeX 可以在 TeX 自己的目录树(TDS)中按名字查找,而 XeTeX 要询问 操作系统的字体数据库,因此随 TeX Live 附带却未在系统中注册的字体就可能「找不到」。同一测试中只有 STIX Two Math 在 XeLaTeX 下也能解析,正是因为 macOS 系统自带该字体。各引擎的名称解析差异在 fontspec 那页有详细说明,这里只给出对策:改用文件名指定(\setmathfont{latinmodern-math.otf})、加上 [Path=…],或者 改用 LuaLaTeX。
% compile with lualatex (or xelatex, but see the note on name lookup)
\documentclass{article}
\usepackage{amsmath}
\usepackage{amssymb} % must come BEFORE unicode-math
\usepackage{unicode-math} % always after the font packages
\setmainfont{TeX Gyre Termes} % text, via fontspec
\setmathfont{TeX Gyre Termes Math} % the matching OpenType math font
% \setmathfont{latinmodern-math.otf} % by file name, if lookup by name fails
\begin{document}
\[ f(x) = \int_{-\infty}^{\infty} \hat f(\xi)\, e^{2\pi i x \xi}\, d\xi. \]
\end{document}只从另一套字体取一部分 —— range=
当你选定的数学字体缺少某些字符时,\setmathfont 的 range= 选项 可以只从另一套字体补上缺的那部分。range= 接受 Unicode 范围、range=\int 这样的单个符号、range=\symbb(也可写作 range=bb)这样的 字母样式,以及 range=bfit/{greek,Greek} 这样样式与字符集的组合。效果是可以测量的:在以 Latin Modern Math 为主字体的基础上加上 \setmathfont{STIX Two Math}[range=\symbb],pdffonts 会同时报告 LatinModernMath-Regular 和 STIXTwoMath-Regular,后者只携带那几个黑板粗体字母。由于只载入所需的槽位,这样混用并不会让 PDF 明显变大。唯一的前提是 必须先按常规方式指定主数学字体。
\usepackage{amsmath}
\usepackage{unicode-math}
\setmathfont{Latin Modern Math} % the main math font
\setmathfont{STIX Two Math}[range=\symbb] % blackboard bold only
\setmathfont{TeX Gyre Termes Math}[range=bfit/{greek,Greek}] % bold-italic Greek only到底该选哪一种 —— 让正文与数学「成对」
建议可以浓缩成一条:把正文字体与数学字体作为「一对」来选。无论用哪个引擎,这条原则都不动摇。什么都不做,你得到的是 Computer Modern(pdfLaTeX)或 Latin Modern Math(unicode-math 的默认),二者都足够好看;除非投稿规范点名了书体,否则没有更换的理由。若在 pdfLaTeX 下更换,请挑选彼此配套的组合——Times 用 newtxtext 加 newtxmath,Palatino 用 mathpazo 或 newpx 系,Utopia 用 fourier,Kepler 用 kpfonts。在 XeLaTeX 或 LuaLaTeX 下,按 amsmath → amssymb → unicode-math 的顺序载入,并给 \setmainfont 和 \setmathfont 传入 同一家族的名字。最后,在把文件发出去之前务必用 pdffonts 核对一遍。你以为交出去的字体,未必就是真正交出去的字体 ——这正是本页的起点。
- 什么都不做时,得到的是 Computer Modern(pdfLaTeX)或 Latin Modern Math(
unicode-math默认)。没有规范要求时无需更换。 - 在 pdfLaTeX 下更换:使用成对的宏包。Times 用
newtxtext加newtxmath,Palatino 用mathpazo;想一行搞定就用fourier或kpfonts。 - 在 XeLaTeX 或 LuaLaTeX 下:按
amsmath→amssymb→unicode-math的顺序载入,并让\setmainfont与\setmathfont属于同一家族。 - 不要 把不成对的正文与数学混用(Times 正文配 Palatino 数学)。不会报错,但纸面上看得出来。
- 最后务必 用
pdffonts检查嵌入结果。mathptmx和mathpazo会留下CMEX10。