LaTeX 字体配置
LaTeX说到底还是一个排版系统,字体是排版关注的核心内容之一,但是由于历史原因,字体系统在设计和使用中混乱不堪, 深究起来就是巨坑,这里简单整理一下LaTeX在中文排版时的字体配置相关知识。
由于版权原因,Tex Live虽然已经打包了很多内容,但是并不会包括一些常见的中文字体,需要用户自行配置处理。 由于本文中的命令需要直接或间接依赖fontspec宏包,它是一个基于XeLaTeX和LuaLaTeX的字体配置宏包,因此不支持pdfLaTeX, 这个宏包可能会影响数学字体,在使用时可以传入no-math选项。 本文只考虑ctex宏包,在Windows/Linux系统的中文字体排版,并且只使用XeLaTeX。
本文主要参考ctex用户文档,以及LaTeX 中文字体配置基础指南
中文字体常识
与书法字体不同,中文印刷/显示字体主要有以下几种:
- 楷体:源自实际书写中的楷体得到的字体
- 宋体:从唐宋直到明清,印刷行业对字体从楷体进行的简化,典型的特点是横平竖直,并且有尖角等辅助结构。(与宋朝没什么特别关系,主要定型于明朝,在清朝被改称宋体,在日本被称为明体)
- 仿宋:因为宋体不美观,在民国时期参考宋朝古籍重新设计的字体,相当于在宋体的基础上向楷体进行的复古潮,例如横平竖直不再是严格的,而是略微倾斜等
- 黑体:计算机时代,适合显示屏呈现的字体,特点是横竖笔画粗细均匀,并且没有多余的笔画
时至今日,宋体仍然是公文报刊和书籍等的正文部分的主流字体,有很多原因:历史习惯;长时间阅读时,宋体字相对不易疲劳;在字体风格上,宋体代表着文化和传统。 计算机和手机上显示的默认都是黑体:Windows使用的是著名的微软雅黑(版权是方正的,不可以用来商用),安卓使用的是开源的思源黑体,这也有很多原因:早期显示器分辨率差,宋体等的细节无法呈现,而黑体的可读性更高;在字体风格上,黑体体现着现代和科技感。
在英文字体中,通常会按照衬线和无衬线来分类,区别是核心笔画之外是否含有装饰性的笔画,将概念迁移到中文字体中,宋体就是典型的衬线字体,而黑体是典型的无衬线字体。 英文字体中还有等宽字体的概念,等宽字体保证每一个字母都显示相同的显示宽度,这在代码编写和表格排版等情景中很常见,将概念迁移到中文字体中,通常对应为所谓的等线字体。
在Windows系统中,默认会安装并使用如下字体:
- 黑体:SimHei
- 宋体(中易宋体):SimSun
- 新宋体:NSimSun
- 仿宋:FangSong
- 楷体:KaiTi
- 仿宋GB2312:FangSongGB2312
- 楷体GB2312:KaiTiGB2312
- 微软雅黑:Microsoft YaHei
在安装了office之后还会多出一些字体,例如
- 隶书:LiSu
- 幼圆:YouYuan
- 华文系列:华文细黑:STXihei,华文楷体:STKaiti,华文宋体:STSong,华文中宋:STZhongsong,华文仿宋:STFangsong,华文行楷:STXingkai,等等。
- 方正舒体:FZShuTi,方正姚体:FZYaoti
ctex字体配置常识
ctex是一个统一的中文排版宏包,涉及到默认中文字体,中文标点,中文间空格的处理等排版细节, 它针对不同编译器自动选择不同的底层中文支持方案(CJK,xeCJK,luatexja等), 针对不同平台会自动选择不同的默认字体,如下图所示(表格取自ctex宏包手册)
其中对于系统的判定比较简单:它可以判断出是否是Windows或macOS系统,对于其它情形全部视作Linux系统。 对于编译器只关注XeLaTeX。
关于中易字库:中易宋体(SimSun.ttc)(属于宋体,衬线体)是中易公司开发的一套字体,在微软雅黑(微软委托方正公司开发)出现之前是Windows默认中文字体,但是目前的Windows默认字体为微软雅黑(msyh.ttf)(属于黑体,无衬线体)。由于历史原因,Windows最新系统中仍然会附带中易宋体,并且在Windows简体中文环境下会直接显示为“宋体”,这很容易导致歧义。
关于fandol字库:这是一套由马起园、苏杰、黄晨成等人开发的开源中文字体。由于开发字体的公司已经破产,因此字体的商用版权存在争议。在Linux系统被默认使用,但是fandol字体的效果和完整性并不好,例如它缺少浛这个非生僻字,在编译后的PDF中会显示为方框,并给出警告。
查看当前texlive可以识别的所有中文字体(在Linux和Windows均可以使用)
1
fc-list -f "%{family}\n" :lang=zh > zhfont.txt
可用如下命令刷新texlive的字体缓存(在Linux和Windows均可以使用,可能需要sudo
)
1
fc-cache -fsv
ctex在内部定义了一系列字体配置文件,位于TexLive安装根目录中的texmf-dist/tex/latex/ctex/fontset
子目录,其下有八个字体定义文件,对应了不同的字体预设方案:
- ctex-fontset-adobe.def (adobe字体方案)
- ctex-fontset-fandol.def
- ctex-fontset-founder.def (方正founder字体方案)
- ctex-fontset-mac.def
- ctex-fontset-macnew.def
- ctex-fontset-macold.def
- ctex-fontset-ubuntu.def
- ctex-fontset-windows.def
在导入ctex宏包或者ctexart文档类时可以使用选项fontset=windows
来指定选择其中一种预设方案,例如
1
2
3
4
5
6
7\documentclass[fontset=windows]{ctexart}
...
% or
\documentclass{article}
\usepackage[fontset=windows]{ctex}
...
其中:
- 如果fontset选项缺省,ctex就会根据当前的系统来判断,通常会默认选择windows或fandol方案。
- 如果拒绝使用这些默认方案,可以指定
fontset=none
,然后自行配置中文字体方案,具体命令见下文。 - 即使采用了这些默认方案,仍然可以用下面的自定义命令来改变使用的字体。
ctex默认配置解析
对几个默认方案进行解析,移除了注释后的源文件全文如下
1 | %% ctex-fontset-windows.def |
1 | %% ctex-fontset-fandol.def |
1 | %% ctex-fontset-founder.def |
这些默认配置方案的核心部分其实只有三行代码(剩下的内容是处理标点等排版细节,并且定义了一些字体族和命令,例如\songti
等,便于调整局部的字体)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23%% ctex-fontset-windows.def
% 中文默认字体:(中易)宋体,粗体以黑体代替,斜体以楷书代替
\setCJKmainfont { simsun.ttc }[ BoldFont = simhei.ttf, ItalicFont = simkai.ttf ]
% 中文无衬线字体:微软雅黑,粗体为对应的微软雅黑粗体
\setCJKsansfont { msyh.\c__ctex_msyh_suffix_tl }[ BoldFont = msyhbd.\c__ctex_msyh_suffix_tl ]
% 中文等宽字体:仿宋
\setCJKmonofont { simfang.ttf }
%% ctex-fontset-fandol.def
% 中文默认字体:Fandol 宋体,粗体为对应的粗体,斜体为 Fandol 楷体
\setCJKmainfont { FandolSong-Regular.otf }[ cmap = UniGB-UTF16-H,BoldFont = FandolSong-Bold.otf,ItalicFont = FandolKai-Regular.otf ]
% 中文无衬线字体:Fandol 黑体,粗体为对应的粗体
\setCJKsansfont { FandolHei-Regular.otf }[ cmap = UniGB-UTF16-H, BoldFont = FandolHei-Bold.otf ]
% 中文等宽字体:Fandol 仿宋
\setCJKmonofont { FandolFang-Regular.otf }[ cmap = UniGB-UTF16-H ]
%% ctex-fontset-founder.def
% 中文默认字体:方正书宋_GBK(FZSSK.TTF),粗体为方正小标宋_GBK(FZXBSK.TTF),斜体为方正楷体_GBK(FZKTK.TTF)
\setCJKmainfont { FZShuSong-Z01 }[ BoldFont = FZXiaoBiaoSong-B05, ItalicFont = FZKai-Z03 ]
% 中文无衬线字体:方正细黑一_GBK(FZXH1K.TTF),粗体为方正黑体_GBK(FZHTK.TTF)
\setCJKsansfont { FZXiHeiI-Z08 } [ BoldFont = FZHei-B01 ]
% 中文等宽字体:方正仿宋_GBK(FZFSK.TTF)
\setCJKmonofont { FZFangSong-Z02 }
值得注意的是:
- 中文字体通常不会附带自身的粗体或斜体变式,因此在windows字体方案中,采用黑体作为宋体的粗体,这是比较奇怪的行为,因为宋体加粗后应该是“加粗的宋体”才合适,就像fandol字体方案一样。普遍采用楷体作为宋体的斜体。
- fandol字体方案经常会出现如下警告,这种警告通常是不影响正常编译的,除了看起来比较烦人之外没什么影响
1
2Font "FandolSong-Regular" does not contain requested
(fontspec) Script "CJK".
ctex字体配置命令
通过对默认字体方案的解析可知,ctex中文字体配置的核心为如下三条命令(这几个命令实际是xeCJK宏包提供的)
1
2
3
4
5
6% 中文默认字体
\setCJKmainfont{<font name>}[<font features>]
% 中文无衬线字体
\setCJKsansfont{<font name>}[<font features>]
% 中文等宽字体
\setCJKmonofont{<font name>}[<font features>]
其中必选项为字体名称,可选项通常用来指定对应的粗体和斜体版本。(旧版本的可选项位置在必选项之前,最新版本更改了顺序如上,但是仍然兼容旧版本的写法)
通常还会附带定义一些字体族 1
2
3
4
5
6
7\setCJKfamilyfont { zhsong } { SimSun }
\setCJKfamilyfont { zhhei } { SimHei }
\setCJKfamilyfont { zhfs } { FangSong }
\setCJKfamilyfont { zhkai } { KaiTi }
\setCJKfamilyfont { zhyahei } { Microsoft~YaHei } [ BoldFont = *~Bold ]
\setCJKfamilyfont { zhli } { LiSu }
\setCJKfamilyfont { zhyou } { YouYuan }
此时可以使用下面的命令,这里加上括号可以限制作用范围,否则设置一直有效,直到下一次改变为止。
1
{\CJKfamily{zhkai} 中文字体(楷书)}
进一步的,还会将其封装为自定义命令(两种方式均可,第一种方式是ctex采用的,命令由xparse宏包提供)
1
2
3
4
5
6
7
8
9
10
11
12
13
14\NewDocumentCommand \songti { } { \CJKfamily { zhsong } }
\NewDocumentCommand \heiti { } { \CJKfamily { zhhei } }
\NewDocumentCommand \fangsong { } { \CJKfamily { zhfs } }
\NewDocumentCommand \kaishu { } { \CJKfamily { zhkai } }
\NewDocumentCommand \lishu { } { \CJKfamily { zhli } }
\NewDocumentCommand \youyuan { } { \CJKfamily { zhyou } }
\NewDocumentCommand \yahei { } { \CJKfamily { zhyahei } }
% or
\newcommand *{ \songti }{ \CJKfamily { zhsong }}
\newcommand *{ \heiti }{ \CJKfamily { zhhei }}
\newcommand *{ \kaishu }{ \CJKfamily { zhkai }}
\newcommand *{ \fangsong }{ \CJKfamily { zhfs }}
...
此时就可以使用\kaishu
等命令更加便捷地切换局部的字体,例如
1
2
3{\kaishu 这是楷体。}
{\fangsong 这是仿宋。}
下面的自定义配置方案会保证\songti
,\heiti
,\kaishu
和\fangsong
这四个最基础的字体命令始终可以直接使用。
自定义字体配置
ctex采用的默认中文字体要么比较垃圾(例如fandol),要么不是完全开源的(例如中易宋体),甚至微软雅黑也不能商用, 因此在自行配置字体时普遍会选择设计更加优秀的,并且完全开源的字体(对于Windows必须将字体全局安装),主流的是以下两个方案:
- 思源字体系列(完全开源)
- 方正字体系列(仅有四个开源字体)
方正字体
方正仅有的四个开源字体如下,注意直接在官网下载的话,需要选择GBK编码的文件:
- 方正书宋:FZSSK.TTF,FZShuSong-Z01
- 方正黑体:FZHTK.TTF,FZHei-B01
- 方正楷体:FZKTK.TTF,FZKai-Z03
- 方正仿宋:FZFSK.TTF,FZFangSong-Z02
注意到ctex默认的founder方正字体方案中,并不仅仅是这几种字体,还有额外的非开源方正字体,并且在Windows系统上通常不会默认安装,因此在Windows上直接使用fontset=founder会因为缺字体而编译失败。
在安装了四种开源字体之后,方正开源字体配置如下(与ctex默认的founder方案相似但不一样,使用了更少的方正字体)
1
2
3
4
5
6
7
8
9
10
11
12
13\setCJKmainfont{FZShuSong-Z01}[BoldFont={FZHei-B01},ItalicFont={FZKai-Z03}]
\setCJKsansfont{FZHei-B01}
\setCJKmonofont{FZFangSong-Z02}
\setCJKfamilyfont{zhsong}{FZShuSong-Z01}
\setCJKfamilyfont{zhhei}{FZHei-B01}
\setCJKfamilyfont{zhkai}{FZKai-Z03}
\setCJKfamilyfont{zhfs}{FZFangSong-Z02}
\newcommand*{\songti}{\CJKfamily{zhsong}}
\newcommand*{\heiti}{\CJKfamily{zhhei}}
\newcommand*{\kaishu}{\CJKfamily{zhkai}}
\newcommand*{\fangsong}{\CJKfamily{zhfs}}
另一种方正开源字体配置如下(参考ElegantLaTeX),更改了无衬线字体为楷书,并设置了相应的粗体
1
2
3
4
5
6
7
8
9
10
11
12
13\setCJKmainfont{FZShuSong-Z01}[BoldFont={FZHei-B01},ItalicFont={FZKai-Z03}]
\setCJKsansfont[BoldFont={FZHei-B01}]{FZKai-Z03}
\setCJKmonofont[BoldFont={FZHei-B01}]{FZFangSong-Z02}
\setCJKfamilyfont{zhsong}{FZShuSong-Z01}
\setCJKfamilyfont{zhhei}{FZHei-B01}
\setCJKfamilyfont{zhkai}{FZKai-Z03}[BoldFont={FZHei-B01}]
\setCJKfamilyfont{zhfs}{FZFangSong-Z02}[BoldFont={FZHei-B01}]
\newcommand*{\songti}{\CJKfamily{zhsong}}
\newcommand*{\heiti}{\CJKfamily{zhhei}}
\newcommand*{\kaishu}{\CJKfamily{zhkai}}
\newcommand*{\fangsong}{\CJKfamily{zhfs}}
思源字体
思源字体由Adobe和Google联合开发,包括思源宋体和思源黑体两款字体,各有七个字重:ExtraLight、Light、Normal、Regular、Medium、Bold 和 Heavy。
Adobe将其命名为思源字体,英文名分别为Source Han Serif
和Source Han Sans
,字体仓库分别为Source Han
Serif和Source Han
Sans。
Google则将其命名为Noto
CJK字体,英文名分别为Noto Serif CJK
和Noto Sans CJK
,字体仓库为Noto CJK
。除了思源宋体和思源黑体,Noto
CJK系列还有一套等宽的中文字体(只有两个字重),名为Noto Sans Mono CJK
。
这一系列字体文件的名称非常繁杂(因为是两家合作,并且需要考虑不同语言和地区习惯),可能使用如下的缩写表示:
- 语言特定版本 (Language-specific Fonts)
- SC - 简体中文
- TC - 繁体中文—台湾地区写法标准
- HC - 繁体中文—香港地区写法标准
- J - 日文
- K - 韩文
- 地区子集版本 (Region-specific Subset Fonts)
- CN - 中国大陆
- TW - 台湾地区
- HK - 香港地区
- JP - 日本
- KR - 韩国
当前的个人选择的是将简体中文SC后缀的两个字体各两个版本都下载安装到本地,每一个都包括7个不同字重的.otf文件,再加上一套等宽字体。 下载链接见各自仓库的Release页面
- 思源宋体一 Source Han Serif SC
- 思源黑体一 Source Han Sans SC
- 思源宋体二 Noto Serif CJK SC
- 思源黑体二 Noto Sans CJK SC
- 思源等宽字体 Noto Sans Mono CJK SC
使用思源字体时,很可能因为字体名称的异常导致编译失败,因为这套开源字体的名称过于复杂了,安装的字体和使用的字体可能后缀差了一点点,比如SC和CN分别代表简体中文和中国大陆,两者字体几乎一样,但是严格来说是不一样的字体。 按道理来说,应该有一个名为Source Han Mono的等宽字体与Noto Sans Mono对应,但是Adobe并没有发布单独的版本,只有一个没有维护的Github仓库,里面是所有字体的大杂烩,而且需要自行编译。
配置例如 1
2
3\setCJKmainfont{Noto Serif CJK SC}
\setCJKsansfont{Noto Sans CJK SC}
\setCJKmonofont{Noto Sans Mono CJK SC}
注意这里没有字体命令例如\kaishu
等,因为思源字体只有宋体和黑体以及等线体,并且有完整的字重分类。
参考方案
参考方案一(混合使用方正和思源字体) 1
2
3
4
5
6% 中文默认字体:方正书宋_GBK,粗体为思源宋体半粗体,斜体为方正楷体_GBK
\setCJKmainfont{FZShuSong-Z01}[BoldFont={Source Han Serif SC SemiBold}, ItalicFont=FZKai-Z03]
% 中文无衬线字体:方正黑体_GBK,粗体为思源黑体中粗体
\setCJKsansfont{FZHei-B01}[BoldFont={Source Han Sans SC Medium}]
% 中文等宽字体:方正仿宋_GBK
\setCJKmonofont{FZFangSong-Z02}
参考方案二(ustcthesis) 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33% 注意 Noto CJK 的 regular 字重名字不带“Regular”。
\setCJKmainfont{Noto Serif CJK SC}[
UprightFont = * Light,
BoldFont = * Bold,
ItalicFont = FandolKai-Regular,
ItalicFeatures = {Extension = .otf},
Script = CJK,
]%
\setCJKsansfont{Noto Sans CJK SC}[
BoldFont = * Medium,
Script = CJK,
]%
\setCJKmonofont{Noto Sans Mono CJK SC}[
Script = CJK,
]%
\setCJKfamilyfont{zhsong}{Noto Serif CJK SC}[
UprightFont = * Light,
UprightFont = * Bold,
Script = CJK,
]%
\setCJKfamilyfont{zhhei}{Noto Sans CJK SC}[
BoldFont = * Medium,
Script = CJK,
]%
\setCJKfamilyfont{zhfs}{FandolFang}[
Extension = .otf,
UprightFont = *-Regular,
]%
\setCJKfamilyfont{zhkai}{FandolKai}[
Extension = .otf,
UprightFont = *-Regular,
]%
参考方案三(LaTeX工作室) 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36\setCJKmainfont{Source Han Serif CN}
[
UprightFont = *-Regular,
BoldFont = *-Bold,
ItalicFont = *-Regular,
BoldItalicFont = *-Bold
]
\setCJKsansfont{Noto Sans CJK SC}
[
UprightFont = *-Regular,
BoldFont = *-Bold,
ItalicFont = *-Regular,
BoldItalicFont = *-Bold
]
\setCJKmonofont{Noto Sans Mono CJK SC}
[
UprightFont = *-Regular,
BoldFont = *-Bold,
AutoFakeSlant = 0.2
]
\setCJKfamilyfont{zhsong}{Source Han Serif CN}
[
UprightFont = *-Regular,
BoldFont = *-Bold,
ItalicFont = *-Regular,
BoldItalicFont = *-Bold
]
\setCJKfamilyfont{zhhei}{Noto Sans CJK SC}
[
UprightFont = *-Regular,
BoldFont = *-Bold,
ItalicFont = *-Regular,
BoldItalicFont = *-Bold
]
\setCJKfamilyfont{zhxh}{Noto Sans CJK SC Light}
自定义方案
记录一下我自己使用的几个方案,只是定义了最核心的三个字体,不包括其它字体命令的定义,第一个纯方正的方案在beamer上的效果也挺好。
1 | \setCJKmainfont{FZShuSong-Z01}[BoldFont={FZHei-B01},ItalicFont={FZKai-Z03}] |
1 | \setCJKmainfont{Noto Serif CJK SC}[ |
1 | \setCJKmainfont{Source Han Serif SC}[ |
英文正文字体
在LaTeX的article等基本文档类中,默认的英文字体为Computer Modern Roman。
一个常见的英文字体为Times New Roman,在很长时间内它是 Windows 平台上 Word 的默认西文字体,与LaTeX的英文字体不同,并且该字体不能免费商用。
英文字体的配置命令包括如下三条: 1
2
3
4
5
6% 英文默认字体
\setmainfont{<font name>}[<font features>]
% 英文无衬线字体
\setsansfont{<font name>}[<font features>]
% 英文等宽字体
\setmonofont{<font name>}[<font features>]
例如 1
2
3\setmainfont{Noto Serif Light}
\setsansfont{Noto Sans}
\setmonofont[Scale=MatchLowercase]{Noto Mono}
再例如 1
2
3\setmainfont{TeX Gyre Termes}
\usepackage{unicode-math} % 需要 unicode-math 宏包
\setmathfont{TeX Gyre Termes Math}
这个还顺便改变了数学字体。
有的人喜欢花里胡哨的英文字体,例如calligra
,需要导入同名的package,例如{\Huge\calligra fenglielie}
的效果为
关于英文字体的配置只是记录一下,我并不打算改变默认的英文和数学字体,看着挺顺眼的。
英文编程字体
另外补充记录一下在编程中经常使用的英文字体,对编程字体的常见要求包括:字体等宽,辨识度高(数字0和大小写字母Oo,大写I,数字1,大小写字母Ll容易区分)。
常见的英文编程字体包括:
- Courier New:(Windows自带)Windows的缺省等宽字体,简称CN,这个字体在Windows早期就存在,因此是很多软件的默认字体,但是它的字形太细了,不适合现在的显示屏和审美
- Consolas:(Windows自带)相当于是Courier New的升级字体,与CN相比字形更窄,能够在较少的空间显示更多的内容。Consolas是VS系列的默认字体,也是VSCode的默认字体
- Cascadia:(Windows自带前两个)相当于为新的windows
terminal配套提供的一套字体,包括几个版本
- Cascadia Code
标准版,支持连字,例如箭头
->
和大于等于号>=
- Cascadia Mono 不支持连字的版本,Windows在终端默认使用的等宽字体
- Cascadia (Code|Mono) PL 是支持 PowerLine 符号的版本,Windows不会默认安装
- Cascadia Code
标准版,支持连字,例如箭头
- Monaco:苹果出品的号称最好的编程字体
- Source Code Pro:Adobe开发的字体,与Source Hans CJK风格相似
- Noto Mono:Google开发的一整套集齐各种语言的等宽字体,完整版很大
- Fira Code:Mozilla 委托设计的开源字体族Fira的扩展,支持连字,经常被网上推荐使用
- Nerd Fonts:这是一组字体,特点是将常见的图标例如Font
Awesome结合到字体中,因此可以在命令行支持各种炫酷主题的显示效果,而一般的字体可能出现缺失图标无法正常显示的问题。其中经常被推荐的字体是Meslo
Nerd
Font,在终端可以选择
MesloLGM Nerd Font
作为主要的英文字体
注意,是否显示连字,除了字体本身是否支持,还和编辑器的选项有关,例如VSCode有相关选项可以禁止连字。