印刷或者排版领域,关于字体的东西是一笔糊涂账。这笔糊涂账从铅字时就开始了。在现在全是字体文件的时代,问题依然存在,简单的,大多是译名和基础概念上的问题;复杂的,多是技术问题,能解决的人非常少。
不过,就算混乱,两个人闲聊一会,大概也能互相了解个大概。所以模糊的东西模糊着说,不太有大的影响。是可以往细了讨论的,但是显得繁琐,甚至在某种程度上说是掌握了一些无用的知识。
从排版软件上说,字体实际上可以分成两个部分:图像部分,非图像部分。图像部分对于人最为重要,符号代表着意义,人通过符号获取信息。但是,有些反常识的是,图像部分对于排版软件实际上是不太重要的。重要的是非图像部分:一组抽象的信息。而这组抽象信息大多表现为数字,比如字的宽度,高度,等等。
TeX中读的字体,是TFM(TeX Font Metric),就是非图像部分的信息。最终的图像呈现部分是可能用Type 1字体或者扩展名为pk的字体。
Type 1字体,是Adobe公司的格式,就是来封装一组矢量图像的。这个Type 1实际上算是内部命名,如同三年级一班一样,没有特别的含义。而且,Adobe还有Type 2,Type 3之类字体格式。值得一提的是,Adobe公司最近停止了在自家软件中对Type 1字体的支持。不过问题不大,并不影响PDF文件中的Type 1字体。这对于以使用PDF文件为主的LaTeX用户来说,也不太成问题。
搭配TFM和Type 1字体,那么就可以见到最熟悉的LaTeX效果了。有些时候,甚至可以通过特征字体来判断某一本书是不是LaTeX做出来的。我们可以直接看字表,这就是LaTeX文档中默认的cmr10的所有字符:
不过,这套东西很麻烦。我都觉得麻烦。配置起来极为繁琐。还好,现在有直接支持OpenType/TrueType的引擎,省事多了。
近些年来,XeTeX和LuaTeX的使用基本成了主流,很大程度可能就是OpenType/TrueType的支持。尤其是2019年LuaTeX接入了harfbuzz之后,理论上的核心排版能力和质量其实已经能够超过XeTeX了。
我觉得大部分人可能都或多或少地用过如下命令:
setmainfont{<blabla>} % usepackage{fontspec}
setCJKmainfont{<blabla>} % usepackage{xeCJK}
setmainjfont{<blabla>} % usepackage{luatexja-fontspec}
这几个命令真是懒人救星。写一写页面的效果就变了,中文或者汉字的支持就解决了。除了这条命令,实际上还有下面几组对应的命令:
fontspec |
xeCJK |
luatexja-fontspec |
jfontspec |
||
setsansfont |
setCJKsansfont |
setsansjfont |
setmonofont |
setCJKmonofont |
setmonojfont |
ewfontfamily |
ewCJKfontfamily |
ewjfontfamily |
enewfontfamily |
—— |
enewjfontfamily |
setfontfamily |
setCJKfamilyfont |
setjfontfamily |
ewfontface |
—— |
ewjfontface |
defaultfontfeatures |
defaultCJKfontfeatures |
defaultjfontfeatures |
addfontfeatures |
addCJKfontfeatures |
addjfontfeatures |
这些命令大部分都比较好学,看看文档就行了,不太好学的部分,实际上是*fontfeatures部分,对于普通用户而言确实难得要领。
比如,我们手上有一个字体,要看看它文件内写入了什么feature,比如SourceHanSerifSC-Regular.otf,可以使用TeX Live自带的命令:
otfinfo -f SourceHanSerifSC-Regular.otf
那么终端输出的部分如下:
aalt Access All Alternates
calt Contextual Alternates
ccmp Glyph Composition/Decomposition
dlig Discretionary Ligatures
fwid Full Widths
halt Alternate Half Widths
hist Historical Forms
hwid Half Widths
kern Kerning
liga Standard Ligatures
locl Localized Forms
palt Proportional Alternate Widths
pwid Proportional Widths
vert Vertical Writing
vhal Alternate Vertical Half Metrics
vkrn Vertical Kerning
vpal Proportional Alternate Vertical Metrics
vrt2 Vertical Alternates and Rotation
问题来了,什么是feature呢?首先它是字体的一部分属性。其次是,它可以看作是设计者预设的一些定向的排版优化。有些文章里面把feature叫做特性,这是不太重要的翻译,可以这么叫,也可以说成是属性。OpenType内的feature一般是四个字母的缩写形式。这个缩写形式在TeX引擎底层是可以直接用的,尤其是在XeTeX中使用plain TeX格式:
font-test.tex
fontfa='[SourceHanSerifSC-Regular.otf]'
fontfb='[SourceHanSerifSC-Regular.otf]:+aalt'
width 1ex height .88em depth .12em}}
lackrectfa “字体”lackrectpar
lackrectfb “字体”lackrectpar
ye
编译方法:
xetex font-test.tex
输出效果如下(引号部分被替换了):
这个时候,其实我们该引入glyph的概念了。Glyph指的是什么呢?图像。只是一个图像的概念。我们输入到文件里面的文本,都会转换成glyph,然后显示到屏幕上或者印出来。
在介绍glyph的时候,一般有一个经典的图,用来表示一个unicode的表达的多样性的。那就是骨头的“骨”字:
输入的都是“骨”字,但是因为不同地域使用习惯用的印刷体不同,会呈现不同的效果,大致相同,小处相异。题外话,这也是我们在多语种排版的时候(尤其是中文和日文混排),就算都是使用汉字的情况也需要根据不同类别的文本使用不同的字体(华东理工大学出版社前几年出版的《日本语》就是一个比较糟糕的例子)。
但是glyph和unicode的关系还不是如此的简单。比如还有一个unicode对应两个glyph的情况,比如泰米尔语(Tamil)的u0B94:
还有多个unicode对应一个glyph的情况,这个,LaTeX用户应该比较熟悉:
分别对应着:
ff fi fl ffi ffl
但是这个例子其实还可以说成是一个unicode对应一个glyph:
不过,可以并愿意直接输入这些字符的还是少数。
让我们回到feature的话题上来。在OpenType里面,有很大一部分feature都是用做glyph变换的,在TeX或者现代一点的排版软件里面,处理文本的流程中最简单的是下面的这个过程(单个字符的变化,也是最简单的情况,还有其他情况,本文暂不涉及):
那么为什么是从0到n呢?拿上面的aalt的例子举例,用了一个字体,它默认有一个从unicode变换过来的glyph,通常会用一个数字来表示,那它就是glyph0,而使用了aalt,一旦覆盖到了glyph的变化,那么就会从glyph0变化为glyph1。n的情况,也就是变化n次才得到最终的glyph,也是会出现的,尤其是汉语/西文之外的一些语言就会存在这种形式,不过一般不像我们上面手动开启aalt的情况,因为它在某种程度上是自动的、预设的。
一个直接的例子是藏语的字体,比如我们可以看看Windows自带的himalaya.ttf内的feature:
otfinfo --features --script=tibt c:windowsfontshimalaya.ttf
输出为:
abvm Above-base Mark Positioning
abvs Above-base Substitutions
blwm Below-base Mark Positioning
blws Below-base Substitutions
ccmp Glyph Composition/Decomposition
mark Mark Positioning
mkmk Mark to Mark Positioning
vert Vertical Writing
实际上我们是无法直接使用abvs/blws的,而且在某些情况下,就算用了,也不会产生实质性的影响。这是因为在汉语或/西文之外,有很多语言的文字在处理的是时候并不是平铺直叙的从左到右或者从上到下的,而是需要变换成二维的形式。这些无法直接使用的feature大部分是为了做这些二维处理用的。
不过,能够直接使用的feature还是很多的,fontspec包对于这些feature做了一定的分类,还做了一定的语义化封装。比如:
% font-test.tex
fontfa='[SourceHanSerifSC-Regular.otf]'
fontfb='[SourceHanSerifSC-Regular.otf]:+hwid'
fontfc='[SourceHanSerifSC-Regular.otf]:+fwid'
defsample{peninsula}
fasamplepar
fbsamplepar
fcsamplepar
bye
效果如下:
那么,在使用fontspec的时候,等价的代码应该是:
documentclass{article}
usepackage{fontspec}
begin{document}
defsample{peninsula}
fontspec{SourceHanSerifSC-Regular.otf}
sample
fontspec{SourceHanSerifSC-Regular.otf}[CharacterWidth=Half]
sample
fontspec{SourceHanSerifSC-Regular.otf}[CharacterWidth=Full]
sample
end{document}
这个CharacterWidth就是fontspec定义的一个语义化后的类别,它允许用户使用不同的参数,当它等于Half的时候就会使相应的glyph变成hwid形式。
那么举一反三,如果我们想将这个feature设为LaTeX文档的字体的默认属性,那么自然可以:
usepackage{fontspec}
defaultfontfeatures{CharacterWidth=Half}
详细的归类,fontspec中有一张表:
每个类别的用法,可以看fontspec的文档。汉字字体的feature设计,其实普遍偏少,西文字体的feature设计的比较多。这些feature使用得当,文档的呈现效果会相当丰富。一个例子,就是我们在排版一些代码的时候,可以这样:
documentclass{article}
usepackage{fontspec}
setmonofont{FiraCode-Regular.ttf}[Contextuals=Alternate]
usepackage{pygmentex}
egin{document}
oindentsmall
egin{pygmented}[lang=hs]
qsort2 :: Ord a => [a] -> [a]
qsort2 [] = []
qsort2 (x:xs) = qsort2 lesser ++ equal ++ qsort2 greater
where
(lesser,equal,greater) = part x xs ([],[x],[])
part :: Ord a => a -> [a] -> ([a],[a],[a]) -> ([a],[a],[a])
part _ [] (l,e,g) = (l,e,g)
part p (x:xs) (l,e,g)
| x > p = part p xs (l,e,x:g)
| x < p = part p xs (x:l,e,g)
| otherwise = part p xs (l,x:e,g)
end{pygmented}
end{document}
效果如下:
对于某些fontspec分类没覆盖的feature,fontspec其实也可以支持,文档中的示例(LuaTeX的例子):
documentclass{article}
usepackage{fontspec}
directlua{
fonts.handlers.otf.addfeature {
name = 'oneb',
type = 'substitution',
data = {
['1'] = 'one.ss01',
}
}
}
setmainfont{Vollkorn-Regular.otf}[RawFeature=+oneb]
egin{document}
1234567890
end{document}
OpenType的feature,尤其是涉及到大量字符变体的部分,实际上和GUI结合地比较紧密,比如Adobe的软件中就有一些动态菜单可以用来控制这些变化。但是这类工具,在TeX社区其实是很少的。
写到这,我觉得有必要提一句我和我的同事们正在做的工作:一个字体预览器。在设计目标上,除了能看字体支持了那些字符外,还能看OpenType里面的这些个feature。但是研发道路漫长,有些关键性的内容还没做完。等做完,我再另写一篇文章介绍。
除此之外,fontspec还有一些其他技术支持,比如Apple的AAT技术,SIL的Graphite技术。这些技术主要是为了解决特定语言的排版难题的,汉字字体应用这两类技术的其实不多。所以本篇也不打算介绍这两个技术的内容了。我打算放在我目前的书里面介绍一下,尤其是SIL的Graphite技术,在解决阿拉伯语排版和国际音标的排版有非常好的效果。
下一篇我会介绍一下LaTeX中的插图。
欢迎分享并订阅本公众号。
文章为用户上传,仅供非商业浏览。发布者:Lomu,转转请注明出处: https://www.daogebangong.com/articles/detail/Lets%20get%20to%20know%20LaTeX%20and%20fonts%20again.html
评论列表(196条)
测试