\chapter{字体} 关于字体有三个重要概念:glyph、typeface、font。glyph~通常被翻译为字形,也有翻译为字体的;typeface~是一个书法和印刷领域的概念,它通常被翻译为字体或书体;font~曾经和~typeface~混用,但现在一般用作电脑领域的概念,在中国大陆被翻译为字体,在台湾被翻译为字型。 上述翻译的混乱令人十分无奈,包老师决定在本文中把它们分别翻译为字形、字样、字体,以正视听。 字形是一个字符的具体图形表现形式,一个字符可以有多个字形,比如汉字中的“強/强”、“戶/户/戸”;字样是一组相同风格样式的字形的集合,比如中文字样有宋、仿、楷、黑、隶、篆等;一种字样可以对应电脑上的几种字体。 \section{字样} \label{sec:typeface} 拉丁字母的字样主要有三大类:Serif(Roman)、Sans Serif~和~Mono-space~(Typewriter)。Serif~的笔画边缘部分有些装饰,类似于中文的宋体、仿宋、楷体、魏书等。Sans Serif~的笔画则是平滑的,类似于中文的黑体。Sans~这个词来源于法语,就是“没有”的意思。Monospace~则是等宽字样。 每一类字样都可以有加粗(bold)、斜体(italic)、倾斜(oblique)等修饰效果。Italic~通常对原字样进行过重新设计,它修饰精细,多用于~Serif;~Oblique~也称作~slanted,基本上是把正体倾斜,多用于~Sans Serif。通常~oblique~看起来比~italic~要宽一些。 \Fref{tab:typeface}列出了几种常见的字样。 \begin{table}[htbp] \caption{常见字样} \label{tab:typeface} \centering \begin{tabular}{llll} \toprule 操作系统 & Serif & Sans Serif & Monospace \\ \midrule Mac OS & Times & Helvetica & Courier \\ Windows & Times New Roman & Arial & Courier New \\ \bottomrule \end{tabular} \end{table} \section{字体格式} \label{sec:font} \subsection{点阵字体和矢量字体} 电脑上用的字体(font)按数据格式可以分为三大类:点阵字体(bitmap)、轮廓(outline)字体和笔画(stroke-based)字体。 点阵字体通过点阵来描述字形。早期的电脑受到容量和绘图速度的限制,多采用点阵字体。点阵字体后来渐渐被轮廓字体所取代,但是很多小字号字体仍然使用它,因为这种情况下轮廓字体缩放太多会导致笔画不清晰。 轮廓字体又称作矢量字体,它通过一组直线段和曲线来描述字形。轮廓字体易于通过数学函数进行缩放等变换,形成平滑的轮廓。轮廓字体的主要缺陷在于它所采用的贝塞尔曲线(Bézier curves)在光栅(raster)设备(比如显示器和打印机)上不能精确渲染,因而需要额外的补偿处理比如字体微调(font hinting)。但是随着电脑硬件的发展,人们一般不在意它比点阵字体多出的处理时间。 笔画字体其实也是轮廓字体,不过它描述的不是完整的字形,而是笔画。它多用于东亚文字。 \subsection{常见字体} 常见的轮廓字体技术有:Type 1~和~Type 3、TrueType、OpenType、~\MF~等。 Adobe~的~Type 1~和~Type 3~基于~PS,它们采用三次贝塞尔曲线。Type 1~支持微调,它使用一个简化的~PS~子集;Type 3~不支持微调,但它可以使用全部~PS~功能,因此既可以包含轮廓字体也可以包含点阵字体信息。 1991~年,Apple~发布了~TrueType,它采用二次贝塞尔曲线。二次曲线处理起来比三次曲线快,但是需要更多的点来描述。所以从~TrueType~到~Type 1的转换是无损的,反之是有损的。1994~年,Apple~着手研究~TrueType~的下一代技术:TrueType GX,它后来演变为Apple Advanced Typography(AAT)。 1996~年,微软和~Adobe~联合发布了~OpenType。它比起~AAT~的优势有:跨平台、开放和易于开发、支持更多的语言比如阿拉伯语。 早在~1984~年~Knuth~就发布了~\MF,它与~TrueType~和~OpenType的区别是,不直接描述字形轮廓,而描述生成轮廓的笔的轨迹。笔的形状可以是椭圆形或多边形,尺寸缩放自如,字形边缘也柔和一些。两种字体可以用同一个~\MF~文件,当然还有不同的参数。\MF~技术如此先进,却没有流行开来。对此~Knuth~解释道,要求一位设计字体的艺术家掌握~60~个参数太变态了,那是用来折磨数学家的。 Type 1~和~Type 3~把字体信息存储在两种文件里:metrics~和~glyph~文件。metrics~文件有~AFM(Adobe font metrics)和~PFM(printer font metrics),glyph~文件有~PFA(printer font ASCII)和~PFB(printer font binary)。~\LaTeX~使用的~metrics~格式是~TFM(TeX Font Metrics)。 TrueType~的文件后缀是~.ttf,OpenType~的是~.ttf~和~.otf。\MF~虽然用矢量图形来定义字形,实际输出的却是一种点阵格式:PK~(packed raster)。 上述字体按技术的先进性,从高到低的排序为:OpenType、~TrueType、Type 1、Type 3、PK,我们应优先选用~OpenType~和~TrueType。 \subsection{合纵连横} Adobe~收取的~Type 1~专利许可费一度十分昂贵,穷人们只好用免费的~Type 3。为了打破这种垄断,Apple~开发了~TrueType。1991~年~TrueType~发布之后,Adobe随即公开了~Type 1~的规范,~Type 1~字体从贵族堕落为平民,因而流行开来。 1980~年代中后期,Adobe~的大部分盈利来自于~PS~解释器的许可费。面对这种垄断局面,微软和~Apple~联合了起来。微软把买来的~PS~解释器~TrueImage~授权给~Apple,Apple~则把~TrueType~授权给微软。 微软得陇望蜀,又企图获得~AAT~的许可证,未遂。为了打破~Apple~的垄断,微软联合~Adobe~在1996年发布了~OpenType。Adobe~在2002~年末将其字体库全面转向~OpenType。 上面这几出精彩好戏充分展示了商场上的勾心斗角、尔虞我诈,没有永恒的伙伴,只有永恒的利益。但它同时也告诉我们,市场竞争中受益的还是广大的消费者。 \section{字体应用} PS~支持~Type 1~和~Type 3,而~PDF~除了这两种还支持~TrueType~和~OpenType。\verb|latex|、DVI浏览器、各种~driver~分别采用不同的字体技术。 \subsection{DVI} \verb|latex|~编译~\LaTeX~源文件生成~DVI~时只需要\verb|.tfm|~文件,因为~DVI~并不包含字形信息,而只包含对字体的引用。DVI~浏览器显示~DVI~时一般使用~PK,它在系统中查找相应的~\verb|.pk|~文件,若找不到就调用~\MF~在后台自动生成。 \subsection{dvips} 缺省情况下,\verb|dvips|~也会查找~\verb|.pk|~,或调用~\MF~自动生成;然后把~PK~转换成包含点阵字体的~Type 3,它的参数~\verb|-D|~可以用来控制该点阵字体的分辨率。用~\verb|ps2pdf|~处理含~Type 3~的~PS~时,输出的自然是含~Type 3~的~PDF。 GSview~在低分辨率下可以很好地渲染~Type 3,Adobe Reader~或~Acrobat~却不能,因为它们使用的~Adobe Type Manager~不支持包含完整~PS~的~Type 3。含~Type 3~的~PDF~看起来会有些模糊,所以应尽量避免使用。 \verb|dvips|~的另一个参数~\verb|-Ppdf|~把~Type 1~嵌入生成的~PS,这样再~\verb|ps2pdf|~就能生成含~Type 1~的~PDF。 \verb|dvips|~不支持真正的(native)TrueType,用户只能把~TrueType~先转成~PK~或~Type 1,这样绕了个弯效果总会打些折扣。 \verb|dvips|~的字体详细使用方法可查阅其手册\citep{Rokicki_2005}第~6~章,此处不赘述。 \subsection{dvipdfm(x)} \verb|dvipdfm|~支持~PK~和~Type 1,它可以用一个~\verb|t1fonts.map|~文件建立~PK~文件和~Type 1~文件之间的映射,这样生成的~PDF~用的就是~Type 1。\verb|dvipdfm|~也不支持真正的~TrueType。 \verb|dvipdfmx|~通过正确的设置可以使用真正的~TrueType,它对中日韩等东亚文字的支持也较好,所以它对我们来说是~Driver~的首选。 \section{TrueType~字体安装配置} CJK~自带的~UTF-8~编码字体~gbsn~和~gkai只包含~GB2312~字符集,而~CTeX~只提供~GBK~编码字体,因此中文用户通常需要自己安装配置~UTF-8~编码的~TrueType~字体。 在使用~TrueType~之前,用户通常需要作以下准备工作: \begin{enumerate} \item 用转换程序~\verb|ttf2tfm|~生成~TFM。 \item 配置字体定义文件~\verb|.fd|。 \item 配置~\verb|ttf2pk|~,因为~DVI~浏览器和~\verb|dvips|~都会自动调用~\verb|ttf2pk|~来生成~PK。 \item 配置~\verb|dvipdfmx|。 \end{enumerate} \subsection{目录和文件} 通常每个发行包都会参照~TDS~建立自己的目录系统,把各种文件发在固定的位置。比如~MiKTeX~顶层目录如下,在本节后面的示例中我们将使用这些目录的缩写。 \begin{code} Install: D:\edit\MiKTeX 2.7 UserData: C:\Documents and Settings\Alpha\Local Settings\ Application Data\MiKTeX\2.7 UserConfig: C:\Documents and Settings\Alpha\ Application Data\MiKTeX\2.7 \end{code} 目录多了有个缺点,文件不知道放在哪里好。MiKTeX~中有的配置文件居然在四个目录下各有一份,实在是令人发指。幸好我们可以用下面的命令检查配置文件的具体名字和路径。 \begin{code} initexmf --edit-config-file=ttf2pk \end{code} \subsection{ttf2tfm} 比如我们想把~\verb|SimSun18030.ttc|(18030~字符集的新宋体)转换为~UTF8~编码的字体文件,我们需要执行以下步骤。 \begin{enumerate} \item 把需要的~\verb|.ttf|~文件复制到~\verb|UserData/fonts/truetype/chinese/|。 \item 用下面的命令生成\verb|.tfm|~和~\verb|.enc|~文件。 \item 把~\verb|*.tfm|~复制到~\verb|UserData/fonts/tfm/chinese/utf8song/|。 \item 把~\verb|*.enc|~复制到~\verb|UserData/fonts/enc/chinese/utf8song/|。 \end{enumerate} \begin{code} ttf2tfm SimSun18030.ttc -q -w utf8song@Unicode@ \end{code} \subsection{字体定义文件} 字体定义文件将字体引用名和实际的字体文件联系起来,比如我们在~\verb|CJK|~环境中引用~\verb|usong|~时,系统将会找到并使用~\verb|utf8song*.tfm|。 \begin{code} %UserData\tex\latex\CJK\UTF8\C70usong.fd \ProvidesFile{c70usong.fd} %character set: GB18030 %font encoding: Unicode \DeclareFontFamily{C70}{usong}{\hyphenchar \font\m@ne} \DeclareFontShape{C70}{usong}{m}{n}{<-> CJK * utf8song}{} \DeclareFontShape{C70}{usong}{m}{it}{<-> CJK * utf8song}{} \DeclareFontShape{C70}{usong}{bx}{n}{<-> CJKb * utf8song}{ \CJKbold} \endinput \end{code} \subsection{配置~\texttt{ttf2pk}} MiKTeX~中~\verb|ttf2pk|~的配置文件是~\verb|ttf2pk.ini|~,在其它的发行包中可能是~\verb|ttf2pk.cfg|。 \verb|ttf2pk.ini|~中有一个~\verb|.map|~文件列表,后者定义了~TrueType~应该按编码转为~PK~等信息。 比如下面这个文件列表会让~\verb|ttf2pk|~读取~\verb|foo.map|~和~\verb|bar.map|。 \begin{code} map foo.map map bar.map \end{code} 如果系统找不到~\verb|ttf2pk.ini|,它会缺省使用~\verb|ttfonts.map|。 \begin{code} %UserData\ttf2tfm\base\ttfonts.map utf8song@Unicode@ SimSun18030.ttc \end{code} \subsection{配置~\texttt{dvipdfmx}} 配置~\verb|dvipdfmx|~是为了让~PDF~正确地嵌入~TrueType,否则生成的文件中的内容不能复制、粘贴。 \begin{code} %UserConfig\dvipdfm\config\dvipdfmx.cfg f cid-x.map \end{code} \begin{code} %UserData\dvipdfm\config\cid-x.map utf8song@Unicode@ unicode SimSun18030.ttc \end{code} \bibliographystyle{unsrtnat} \bibliography{reading} \newpage