一、必须掌握的概念 DPI (以下讨论先避免 sub-pixle 子像素渲染技术,以免混淆)
看过无数流行的汉化或字体美化的文章,往往存在一个致命伤,即忽略了 DPI 这个重要概念,因此是不完整的。
DPI 原来是印刷上的记量单位,意思是每个英寸上,所能印刷的网点数(Dot Per Inch)。但随着数字输入,输出设备快速发展,大多数的人也将数字影像的解析度用DPI表示,但较为严谨的人可能注意到,印刷时计算的网点(Dot)和 电脑显示器的显示像素(Pixel)并非相同,所以较专业的人士,会用PPI(Pixel Per Inch)表示数字影像的解析度,以区分二者。而在本文中我们约定两个概念可以互换,即 DPI 就是 PPI。
参考: Coming to Terms with DPI, PPI and Size
问题一: dpi 和我们的 LCD 屏有什么关系呢?
把眼睛凑近屏幕,容易发现我们的屏幕是由一个个小方格组成,我们称这些方格为像素,LCD 中有个术语叫屏幕的 native resolution(物理解析度),指的的就是屏幕所包含的像素数量,比如我的 TFT LCD 14" native resolution 为 1024x768,即水平由 1024 个像素组成,垂直由 768 个像素组成。通常让我们的 LCD 工作在 native resolution,成像效果最好。
通过控制像素的开关和色彩的组合来显示我们需要的图像,但不要忽略了屏幕像素的数量是有限的,所以往往在低解析度的显示设备上看到的图像并不十分清晰,比 如在观察白底黑字(或黑底白字)的文字时,文字的边缘有尖锐的锯齿状(阶梯状),长时间观看,眼睛很容易疲乏,这也就是很多人喜欢看纸制书籍的一个重要原 因,制作精良的纸张,它包含的“像素”可以达到很高,边缘看起来非常的流畅。
问题二: 有什么办法可以解决或缓解上述缺陷呢?
除了通过各种辅助技术(hinting,anti-alias,sub-pixel,etc.)改善成像效果外,最快捷的途径是换一台高解析度(高分屏或高 dpi) 的屏幕,简单说像素越精细越好。
讲到这里你可能很关心自己的屏幕的 dpi 具体为多少?(拿去和别人炫耀 :)
到这里找找看有没有你的 LCD dpi 信息: http://www.prismo.ch/comparisons/notebook.php
问题三: 如果找不到,如何来手工计算?
找把尺子,把 LCD 屏可视区域的宽和高量一下,比如我的屏幕 width = 287 mm = 28.7 cm,height = 215 mm = 21.5 cm
换算比例: 1 cm = 0.39 inch, 1 inch = 2.54 cm
水平 dpi = 水平 resolution * 2.54 / width = 1024 * 2.54 / 28.7 = 90.6
垂直 dpi = 垂直 resolution * 2.54 / height = 768 * 2.54 / 21.5 = 90.7
故我的 dpi 大概为 90x90,在某些机子上水平 dpi 和 垂直 dpi 会不相当,这是很正常的。
问题四: 下面我们看看自己的单个像素具体有多大?
术语: pixel pitch - 像素间距,即单个像素的水平宽度,类似于 CRT 的 dot pitch(点距)
我的 TFT 14" 1024x768
pixel pitch = 28.7 / 1024 = 0.028 cm = 0.28 mm
而一台 T43 高分屏 SXGA+ 14" 1400x1050, pixel pitch = 0.2047 mm
可以看出 SXGA+ 14" 要精细的多。羡慕啊!
问题五: 我要显示一个 px = 12 的文字,实际看起来会有多大?
术语: [color=red]px(pixel size) - 显示单个文字需要的水平像素数量
实际大小 = px * pixel pitch
TFT 14" 1024x768: 12 * 0.28 = 3.36 mm
SXGA+ 14" 1400x1050: 12 * 0.20 = 2.4 mm
看到这里高分屏的用户应该明白为什么同样是 12 px 的 SimSun 点阵字体(bitmap font),在自己的屏幕上看起来要小很多,因为你的 pixel pitch 小。pixel pitch 小不是更好么?
不是不好,而是字太小了,看起来太累,为了保护你的视力,你应该选择大一些的 px。
但要注意中文点阵字体提供商并没有为每个 px 制作点阵汉字,因为中文点阵都是手工绘制的,需要很高的专业技能,非常耗时,故一般只绘制最常用的 px,而且点阵的一个最大的缺点就是不能够缩放,每个点阵汉字的每一个像素都是事先安排好的,缩放后打乱了原有的布局,比如出现破碎,高高低低之类的现 象,使字体变得非常丑陋。
好在 winxp 带的 simsun.ttc 除了 outline 字体外,还包含了丰富的点阵,ppem(pixels per em)分别为 12px, 13px, 14px, 15px, 16px, 18px,你可以根据你的需要选择。例如选择 16px:
实际大小 = 16 * 0.20 = 3.2 mm,这样看起来和 14" TFT 上的 12 px 字就差不多大小了。
当然因为 ppem 不同(或 px 不同),绘制点阵字体时的空间自由度也不同,出来的点阵效果也不同,而且竖线横线比划一般都只占用一个像素宽度,在高分屏上 16px 看起来会有细胳膊细腿的感觉,这也就是为什么不少人会觉得 12px 在 14" 1024x768 上会比较好看,比较符合东方人对中文的审美观。
要注意,由于点阵字体以上的缺陷,通常用在低解析度的屏幕上,现在随着技术的发展,屏幕解析度逐步提高,越来越流行使用 outline 字体,这种字体可以随意的缩放,而不影响形状,现在高分屏用户可以尝试用黑体,如 mac os 带的华文细黑或微软新出的雅黑,黑体比划很粗,适合一部分人的审美观,在大屏幕上效果比较好。
问题六:既然 dpi 都不一样,我要去和别人讨论字体大小,如何讲清楚该字体究竟有多大呢?
真是一个难题,显然用 pixel 这个相对度量去讨论是不合适的,谁也说不清。所以这里我们引入另外一个重要单位 point(磅)。
1 point = 1/72 inch
这里的 inch 就是实际生活中使用的 inch。没错 point 才是绝对度量,比如一个 9 point(9磅)的字的实际大小:
9 * 1/72 = 1/8 inch = 1/8 * 2.54 cm = 3.175 mm
这样的话,大家才能从同一个标准出发讨论问题。所以你看到 MS office word 里的 size,都是以 point 为单位的。
注意,不同家族的字体,如 Arial 和 Verdana 字体,由于设计思路不同,同样磅值的字,看起来 Verdana 感觉要大一些。
Arial VS Verdana
不要让 windows 蒙蔽了你的眼睛!
由于显示器市场的混乱,不同产品 dpi 都不同,为了统一,windows 默认设置 dpi 为 96。注意这里的 dpi 不是你机器的实际 dpi,而是 windows 给你强加上去的。
统一的 96 dpi 有它的优点,因为市面上大多数的显示器 dpi 和这个值接近,而且大多数人都是用 wndows 来设计网页,因此无形中 96dpi 成了一个 de facto 上的标准。但缺点也是很明显的,设计师在 96 dpi 显示器上设计的网页到了 120 dpi 的机器上看起来可能效果会差强人意。所以现在有人建议设置 em 值,这个已经超出我的知识范围。
问题七:你在自己机器上看到的 9 point 还是 9 point 大么?
初看这句话好像自相矛盾,难不成 1 != 1 了!小学老师欺骗了俺?!
别着急!因为你打开 MS word,字体设置栏里看到的 9 point 字,很可能是错误的信息。
假如你运气很好,你的机器实际 dpi 刚好为 96 dpi,那么恭喜你,你没受骗,你看到的是正确信息,如果你的实际 dpi 和 96 相差比较大,那么你看到的是虚假信息。为什么这么讲呢?
我们来做几道小学数学题:
文字在 LCD 上成像,不管是 bitmap font 还是 outline 字体,最终都是以像素绘制。
比方我有一台实际 96 dpi 的 LCD,我要显示一个 9 point 大小的字,我们来看看具体需要多少像素 px?
换算公式: px = pt * dpi / 72
96 dpi, 9 pt: px = 9 * 96 / 72 = 12
操作系统水平要用 12 个像素来描绘该字。
屏幕上看起来有多大?
12 * pixel pitch
假如我通过各种手段人为的把 dpi 改成了 72,来算一下需要的像素值 px?
72 dpi, 9 pt: px = 9 * 72 / 72 = 9
屏幕大小:9 * pixel pitch
注意 pixel pitch 是不变的,计算方法见上文。
现在操作系统就以 9 个像素给你描绘该字,显然比 12 像素描绘出来的小。
这也就是为什么很多人抱怨 Debian/Ubuntu 下默认的 75 dpi ,设置为 9 ponit 的字会看起来比 windows 96 dpi 下小的多的缘故。
此时最可能发生的做法就是,把 9 point 改成更高的 point,而不知其实是 dpi 在跟你开玩笑呢!正确做法,应该先调整好系统 dpi,使之接近你的实际 dpi。
再结合高分屏来讨论一下。
问题八: 同样显示一个 9 point 字(即实际大小一样),显然在 TFT 上需要描绘该字的像素比较少,因为像素个头比较大,而在 SXGA+ 上用来描绘的像素多,个头细,哪个会看起来更漂亮些呢?
我猜你会毫不犹豫选择后者,好比用一个高 dpi 的数码相机拍摄同一个场景,拍出来的效果比低 dpi 要好的多。
但我只能部分同意,还要看你选择的是哪种字体。
如果你正在使用 outline 字体,它是可以任意缩放的,明显同样大小在 SXGA+ 上的表现要好很多,即字体边缘更加光滑流畅,好比在一张好的和画布上作画。
点阵字体要分情况讨论,不要忘了点阵字体是不能缩放的,而且 px 并不完整,只绘制了一些最常用的 px。
例如:
拿两台实际 dpi 分别为 96 和 72 的机器来讨论,同样显示 9 point 的点阵汉字。
上面已经计算过,dpi 96 要用 12 px, dpi 72 要用 9 px 绘制该字。
而使用的字体只带了 9px, 10px, 11px, 13px,14px,15px .....,恰好没提供 12px。
此时 96 dpi 机器上的 9 point 汉字,将会非常丑陋,因为此时的 12px 点阵是机器为你合成的,现在的 AI 还没那么智能,远没达到和人类一样的审美能力。就好比一台高性能手机,可惜不在服务器,任你本事多强,也无用武之地,多郁闷啊!
而 72 dpi 的机器,9 point 刚好落在 9px,此时的字体比划端端正正,自然效果会好的多。
以上的讨论也正说明了点阵字体的缺点,很不灵活。
所以在后面的讨论中,对于 outline 字体,我们用 point size 讨论, 直观方便。而对于 simsun 内嵌的点阵(bitmap font)会用 pixel size 来控制比较好,因为用 point size 的话,还要进行换算,看看是否刚好落在特定的 px,而换算要用到 dpi,个人的实际 dpi 又不尽相同,事先没法得知,故用 point size 是不合适的。
总结一下,dpi 在这里就像是一个桥梁,将 point size 转化为需要的 pixel size。
听了这么多,你也累了,休息一下吧!然后我们一起来实践一下,注意 Linux 将会有多个需要调整 dpi 的地方,希望你能区分清楚。
1、告诉 X server 你的实际 dpi
Debian/Ubuntu 下 X server 默认会使用 75 dpi,可以通过以下命令查看你的 X server 的 dpi 设置:
$ xdpyinfo |grep resolution resolution: 75x75 dots per inch
因为我的实际 dpi 为 90, 故 75 对我来说低了。如果让 X server 工作在正确的 dpi,有多种途径,而且不同发行版略有差异,由于篇幅所限,只能部分介绍,具体请参考:
Mozilla DPI-related Font Size Issues on Unix
Solving the Linux DPI Puzzle
引用其中的几句话,简单看一下有哪几种和它们的优先级:
How the XFree86 and Xorg servers calculate DPI The DPI of the X server is determined in the following manner: 1. The -dpi command line option has highest priority. 2. If this is not used, the DisplaySize setting in the X config file is used to derive the DPI, given the screen resolution. 3. If no DisplaySize is given, the monitor size values from DDC are used to derive the DPI, given the screen resolution. 4. If DDC does not specify a size, 75 DPI is used by default. You can check what DPI your X server is set to by running xdpyinfo | grep resolution in a terminal window. |
对于 Debian/Ubuntu 我采用方法 2,下面的设置改成你自己的,注意 dpi 的数值最好为 6 或 12 的倍数,原因:
As above, if this works, but at less than 100% satisfaction, tweak the number lower or higher to suit your preference. If possible, use a number that is a multiple of 6, or even 12, as numbers that aren't sometimes result in annoying rounding errors that cause adjacent bitmap font sizes to not increment and decrement linearly. |
$ vi /etc/X11/xorg.conf 加入 Section "Monitor" ...... DisplaySize 287 215 # 1024x768 90dpi ...... EndSection
这里的 287, 215 即我的实际显示区域的宽和高,单位为 mm。
重启 X 后,生效。以 gdm 为例:
$ /etc/init.d/gdm restart
查看是否生效:
$ xdpyinfo |grep dimensions dimensions: 1024x768 pixels (289x217 millimeters) $ xdpyinfo |grep resolution resolution: 90x90 dots per inch
告诉 X server 实际 dpi 后,最直观的感觉就是用 gdm 登录管理器,在使用默认 75dpi 下,gdm Option 菜单和输入框中的字体会显得较小,其它的变化待大家慢慢发觉吧!
2、fontconfig/xft
对于传统的程序或系统,使用 legacy x font server,简称 xfs,那么上面的做法应该已经足够,但对于现在的程序来说,通常使用 fontconfig/xft,还得做进一步的工作。
Unfortunately, variations in the implementations of X mean display size reconciliation as above won't be a solution on every system. Failure here seems to be common on newer systems using fontconfig instead of legacy xfs |
$ vi /etc/fonts/local.conf 或 vi ~/.fonts.conf 加入 <!-- Target dots per inch --> <match target="pattern"> <edit name="dpi" mode="assign" > <double>90</double> </edit> </match>
fontconfig 中 pixel size 的计算过程
据我实践,kde Qt3 程序会使用该值,包括 kdm,用该值来控制 Qt3 程序的字体 dpi 比较方便。
3、dpi in gonome
GNOME also offers an interface to set the Xft DPI. If "gnome-settings-daemon" is running, this will advertise the DPI value set in the gnome-font-properties dialog to GNOME applications via XSETTINGS, and set the Xft.dpi X resource. Any Qt application started after gnome-settings-daemon is running will use the Xft.dpi value configured by GNOME. |
操作方法,在 gnome 的字体功能面板 dpi 设置栏里输入 90,就可以了,你可以根据喜好,进行微调,马上能见到效果。
查看 Xft.dpi 值,方法如下:
$ xrdb -query ...... Xft.antialias: 1 Xft.dpi: 90.00000 Xft.hinting: 1 Xft.hintstyle: hintfull Xft.rgba: rgb
细节:
如果 gnome 中的 dpi 和 X server 中的不同,而且相差很大,比如一个 120,一个 90。那么你在登录到 gnome 那一瞬间,会发现开始菜单的字体一下子变大,原因是最开始时 gnome-settings-daemon 还没运行。
4、字体大小不等,dpi 惹得祸
如果你在使用 kde 或 fvwm 之类,而又没有运行 gnome-font-properties,那么你会发现同样是 9 point 字,gtk2 程序和 Qt3 程序的显示大小不同。例如你打开 gnome terminal 和 kde terminal 比较一下。
解决方法:
$ vi ~/.Xresources
Xft.dpi: 90