UPM (Units per Em)UPM的意思是每个em由多少个单位组成,通常设置成1000或2048。以下段落深入解释UPM的由来。
计算机系统在渲染时会根据UPM的数值放大或缩小体字体,所以矢量的字体图像才能转换为像素。UPM可以理解成在从矢量到像素这个转换过程中的精确程度。假设字母M刚好占据一个平方em,那么系统在渲染字母M的时候会把这一个平方em划分成UPM这么多小格子。下图左边便是划分成64个格子,而右边是16*16=256个格子。由此可见,UPM越高,渲染时的精确度便越高。
UPM一般设为1000。在1995年左右,有建议将UPM设为2的正次方倍数,1024或2048是最理想的数值,即2的10或11次方。这是因为当时的计算机运算速度很慢,象1024这样的数值方便计算机运算,正如人类计算1000除以10很容易一样,1024除以2对于计算机而言一样容易。2048曾被认为是最理想的数值,因为可以包含足够多的细节也很容易计算。但随着计算机运算速度的提高,UPM一般都设为1000,当设计师想要更高的精确度或更多的细节时,可以将UPM设为2000,2048,甚至10000(FontLab的最大限制)。
上面我都一直避免提到em,因为em的定义有些复杂。在计算机还未发明的时候,西方一直把大写字母M的宽度作为定义em,而具体数值是根据字体而变的。现在的字体五花八门,更何况中文并没有西方字母,所以近代便有人建议把em定义成符号 em dash 的宽度,因为 em dash 就一个横杠,十分简单。
然而,计算机在渲染字体时,em的具体数值并不太重要,因为em只是一个抽象的概念。如果要渲染20点的字,字体的UPM是1000,20点便代表1000个单位(小格子),而这1000个小格子就是一个平方em。
在 FontLab 5 中设置字体参数设计字体的时候,第一步应当是确定字体的比例,即大写字母和小写字母的比例,这一步非常的重要。相应的,下伸和上伸部分的比例也可以确定下来。一个字体,尽管有不同样式(粗体、斜体等),字体参数(font metrics)的设置应当是一样的,不然从常规体转到粗体的时候,用户发现字体大小竟然变了,这样的结果肯定不是用户想要的。
下图是在FontLab 5中设置字体参数的一个截图。
需要注意的是,以上设置是针对西方字母的,因为很显然中文并没有什么上伸或下伸部。而且小写字体高度(x height)和大写字体高度(Caps height)对中文也不适用,应当统一设置成大写字母的高度。注意下伸部的的数值是用负数表示的,因为它在基线(baseline)以下。Underline表示该字体下划线的位置,因为是在基线以下,所以仍然是负数,如果下划线刚好在基线上,那就可以设置成零。Thickness表示字体下划线的厚度。Font BBox,即 Font Bounding Box,代表字体的上下限。注意这里并没有设置选项,因为FontLab会自动计算最高的上伸部和最低的下伸部。
TrueType 与 OpenType 的字体参数现在市面上字体主要分成TrueType和OpenType,而OpenType则在逐渐成为主流, 因为OpenType支持编程,比如把 tf 替换成一个特殊的字母设计(ligature),或者不同的字母之间允许不同的距离(kerning),这些功能都是TrueType所缺乏的。
TrueType和OpenType的字体都自带一些字体参数,这样计算机在渲染时可以正确的渲染出设计者所希望的字体。当然,不同计算机系统或程序处理字体的方式也可能不同。具体细节十分繁琐,在这里只是提到一些基本的知识。
Windows一般用OS/2规格,而苹果用hhea规格。这些字体设置直接关系到你的字体在实际应用的时候是什么样子,所以非常重要,就像人靠衣装一样。不幸的是这些设置实际上有些复杂和混乱,所以这篇文章希望能把一些基本概念解释清楚。简单的来讲,尽管你已经设计好了字体比例,确认了上伸和下伸部的高度,你仍然需要做一些计算以确保你的字体在不同的系统上渲染出来是一样的。
下面列出一些基本的计算和换算公式,|...|表示绝对值,下伸的数值是负数,需要转换成正数。
OS/2.TypoAscender + |OS/2.TypoDescender| + OS/2.TypoLineGap= hhea.Ascender + |hhea.Descender| + hhea.LineGap= OS/2.WinAscent + OS/2.WinDescent根据微软最初的规定,三个Typo的值(即TypoAscender,TypoDescender和TypoLineGap)是应该和hhea的Ascender,Descender,LineGap一样的,用来计算一个字体默认的行距,但实际上并不一样。
WinAscent和WinDescent分别代表字体的上下限,即一个字体的字符最高是多高,最低是多低,超过的这个限制的部分可能会被切掉。注意这两个值并不代表字体真正上伸和下伸。一般来说,因为WinAscent和WinDescent可以保证字体的任何部分都不会被切掉,所以这两个数值会比实际的上下伸的数值要大。而正是由于这个原因,很多情况下,苹果系统上显示的行距和Windows系统上的不一样。
行距在这里的意思是字体的默认行距,即基线到基线(baseline-to-baseline)的距离,也可以理解为行距。为了确保行距的统一,可以设置把行距设置成0,然后把行距包括在上伸和下伸部里。再设置:WinAscent=Ascender,WinDescent=Descender。这样以来,三个Typo的值就可以设置成真正的上下伸部的数值。而且这三个数值和UPM有一定的关系,不应该随意选择。
下面谈这些字体设置和UPM的关系。UPM可以想象成一个正方形,字体里的每个字符都应该刚好能放进这个正方形里。偶尔有的字符会超出这个正方形,严格来讲这是不对的。根据以往的经验,在设置字体的上伸和下伸时应该把UPM也考虑进去。
UPM = TypoAscender + |TypoDescender|TypoLineGap = hhea.LineGap = 0hhea.Ascender = OS/2.WinAscenderhhea.Descender = OS/2.WinDescender然后再计算WinAscent和WinDescent这两个值。下面是适用于拉丁文语言字体的公式(对于中文,阿拉伯文等其他文字要用其他方法)。
WinAscent = Ascender * 1.20WinDescent = Descender * 1.20WinAscent + |WinDescent| = UPM * 1.20在这里,1.20只是一个放大比例,可以换成 1.1, 1.30 等等,根据不同语言作出调整。最后,以上这些计算公式只是为了提供一个起点,如果渲染时不太理想,应该再做相应的改动。