这一段是为了测试宋体字的显示效果,包括宋体里面自带的英文字体,“This is english,how does it look like?”。这一行是小字。后面几个字是加粗的宋体。标点符号“,。:;!”
这一段是为了测试黑体字的显示效果,包括黑体里面自带的英文字体,“This is english,how does it look like?”。这一行是小字。标点符号“,。:;!”。微软雅黑是什么样子的呢“,。:!”?
This paragraph shows how does serif english fonts look like,包括英文里面夹杂中文的显示效果。Is serif same as Times New roman?
This paragraph shows how does sans-serif english fonts look like,包括英文里面夹杂中文的显示效果。Is sans-serif same as Arial?
This paragraph shows how does ui fonts look like,还有专门的界面字体,比如Windows中的Tahoma字体:File->New->New Project。
#include <stdio.h>
int main(){
return 0;//很显然这是为了测试等宽字体
}</p> <p>#include <stdio.h>//观察下面的代码了解monospace是否等于Courier New
int main(){
return 0;
}
字体的分类及其用途
在文章最开始的一个部分(也就是这部分之前的内容),我特意写了一些文字用来测试各种字体的显示效果。这些测试文本我在HTML源代码模式下经过仔细修改。第1段的字体都是设置为宋体,包括其中的英文、小字及加粗的字。第2段除了最后一句外,其余的字体都设置为黑体,包括英文及小字;最后一句字体设置为微软雅黑,是为了对比微软雅黑和普通黑体的效果。第3段除了最后一句外,其余的字体都设置为Serif,包括其中的中文;最后一句字体设置为Times New Roman。第4段除了最后一句外,其余的是Sans-Serif,最后一句是Arial。第5段的字体都是设置为Tahoma。最后的两块代码,第1块代码的字体设置为monospace,第2块代码的字体设置为Courier New。为什么这样设置,我后面会配合图片逐一讲解。下面,需要先了解字体的分类及其用途。
1、英文字体分为三类,分别是有衬线字体(serif)、无衬线字体(sans-serif)和等宽字体(monospace)。Serif是有衬线字体,意思是在字的笔画开始、结束的地方有额外的装饰,而且笔画的粗细会有所不同。Sans-serif就没有这些额外的装饰,而且笔画的粗细差不多。在传统的正文印刷中,普遍认为衬线体能带来更佳的可读性(相比无衬线体),尤其是在大段落的文章中,衬线增加了阅读时对字母的视觉参照。而无衬线体往往被用在标题、较短的文字段落或者一些通俗读物中。相比严肃正经的衬线体,无衬线体给人一种休闲轻松的感觉。同时,由于无衬线字体笔画比较饱满,所以比较适合电脑屏幕显示,在印刷和打印中,可以用无衬线字体做标题、加粗字体等表示强调。等宽字体就不用多说啦,主要用于终端字体或编程。
2、中文字体可以参照英文字体进行分类,由于中文都是等宽的,所以就只需要区分有衬线(serif)和无衬线(sans-serif)。中文的宋体、仿宋就相当于英文的serif,所以用于传统印刷和打印效果比较好。而中文的黑体、楷体、圆体等字体相当于英文的sans-serif,用于电脑屏幕的显示效果比较好,也可以用在印刷和打印中做标题和粗体字。
3、Serif字体的经典代表有Georgia和Times New Roman,sans-serif字体的经典代表有Arial和Verdana,monospace字体的经典代表有Courier New和DejaVu Sans Mono。
电脑中的字体显示技术
电脑中的字体既是一门艺术,也是一门技术。要将屏幕上的字体显示得好看难度可不小。字体可以表示为点阵(bitmap),也可以表示为轮廓(outline)。点阵字体不能缩放,轮廓字体可以随意缩放。
1、要获得锐利清晰的效果,小字必须显示为点阵(bitmap),大字可以显示为轮廓;
2、显示轮廓字体时,为了让字体边缘显得比较光滑,需要对字体边缘进行抗锯齿(anti-alias);
3、为了获得更好的效果,字体设计厂家在设计字体的时候,会对字体进行微调(hinting)。字体微调是一项耗时耗力的工作,所以就产生了自动微调技术(autohint);
4、为了让字体在液晶显示器上获得更好的效果(主要也是为了字体边缘光滑),产生了次像素平滑技术(subpixle),微软的ClearType技术也属于次像素平滑技术的一种。所谓次像素,是指每个像素中的单独的R、G、B分量,所以次像素平滑用好了,字体边缘看起来会更平滑,如果用不好,字体边缘就会显得花花绿绿。也正是因为CRT显示器和液晶显示器每个像素的组成方式不一样,所以在CRT显示器中不能开次像素平滑。
5、增加屏幕的dpi,可以增加画字的像素,从而获得更平滑的显示效果。比如在传统的96dpi的电脑显示器上,一个9pt的字符用12个像素绘制,一个12pt的字符用16个像素绘制,使用轮廓字体确实很难做到平滑。但是在目前的安卓手机、苹果iPad等设备上,高分辨率的润眼屏都在300dpi以上,画一个12pt的字符可以用50多个像素,字体平滑自然不是问题,根本不需要使用点阵、微调、抗锯齿、次像素等技术。我认为,随着显示器硬件技术的发展,以上技术都将成为浮云。
以上图片是字体测试段落在Win7系统中的显示效果。除了标题和小字外,其它的字体都是12pt。可以看到,12pt的宋体字和serif的英文字体显示为点阵,所以获得了清晰锐利的效果。而黑体、微软雅黑和sans-serif字体都没有点阵,但是由于sans-serif本身笔画饱满,所以也获得了不错的显示效果。据说微软雅黑每个字造价100美元,专为ClearType技术而设计,但是从效果上看,并不比普通黑体强多少。
前面讲过,serif和sans-serif是字体的分类名,而不是具体的字体名。Times New Roman是Windows下最经典的serif字体,但是从上图可以看出它并不是serif字体的首选字体,设置为serif的字体和设置为Times New Roman的字体显示不一样,但是都是很漂亮的有衬线字体,serif的中文选择了一种和宋体不同的点阵字体。Arial字体是最经典的无衬线字体,从图中可以看出设置为sans-serif和设置为Arial的字体显示效果相同。只是sans-serif的中文被宋体的点阵代替了。Tahoma字体的显示效果和sans-serif只是宽度上略有不同,但是依然很饱满。
使用Ctrl+鼠标滑轮可以缩放网页。将网页放大后显示,可以查看轮廓字体的显示效果,如下图:
下面来看看Ubuntu中的显示效果。从下图中可以看到,Ubuntu侧重于sans-serif和黑体,除了明确指定serif和Times New Roman的字体外,其余全部显示为sans-serif和黑体。而且没有点阵。这进一步印证了我前面说的黑体适合屏幕显示、宋体适合打印和印刷。在系统中全部显示黑体虽然不会丢失文字的信息,但是肯定会影响美观。Ubuntu没有正确地为monospace选择等宽字体,但是对Courier New倒是选择了一个很漂亮的等宽字体进行替代。
使用Ctrl+鼠标滚轮将网页放大,看到清晰饱满的字体,如下图:
对于界面字体,Windows下有Tahoma,Ubuntu下也有专用的界面字体,该字体就叫Ubuntu,是开源的。自Ubuntu 14.04开始,已经没有采用文泉驿的黑体了,而是改用Droid Sans Fallback,没错,就是Google花钱为Android系统设计的字体。反正该字体也没点阵,我觉得显示效果也就那样。
下面再来看看Fedora 20,该系统也是以黑体为主。从下面的图片中可以看到,除了Times New Roman,其它的字体显示都是一个样。
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<!-- /etc/fonts/fonts.conf file to configure system font access -->
<fontconfig></p> <p><!--
DO NOT EDIT THIS FILE.
IT WILL BE REPLACED WHEN FONTCONFIG IS UPDATED.
LOCAL CHANGES BELONG IN 'local.conf'.</p> <p> The intent of this standard configuration file is to be adequate for
most environments. If you have a reasonably normal environment and
have found problems with this configuration, they are probably
things that others will also want fixed. Please submit any
problems to the fontconfig bugzilla system located at fontconfig.org</p> <p> Note that the normal 'make install' procedure for fontconfig is to
replace any existing fonts.conf file with the new version. Place
any local customizations in local.conf which this file references.</p> <p> Keith Packard
--></p> <p><!-- Font directory list --></p> <p> <dir>/usr/share/fonts</dir>
<dir>/usr/share/X11/fonts/Type1</dir> <dir>/usr/share/X11/fonts/TTF</dir> <dir>/usr/local/share/fonts</dir>
<dir prefix="xdg">fonts</dir>
<!-- the following element will be removed in the future -->
<dir>~/.fonts</dir></p> <p><!--
Accept deprecated 'mono' alias, replacing it with 'monospace'
-->
<match target="pattern">
<test qual="any" name="family">
<string>mono</string>
</test>
<edit name="family" mode="assign" binding="same">
<string>monospace</string>
</edit>
</match></p> <p><!--
Accept alternate 'sans serif' spelling, replacing it with 'sans-serif'
-->
<match target="pattern">
<test qual="any" name="family">
<string>sans serif</string>
</test>
<edit name="family" mode="assign" binding="same">
<string>sans-serif</string>
</edit>
</match></p> <p><!--
Accept deprecated 'sans' alias, replacing it with 'sans-serif'
-->
<match target="pattern">
<test qual="any" name="family">
<string>sans</string>
</test>
<edit name="family" mode="assign" binding="same">
<string>sans-serif</string>
</edit>
</match></p> <p><!--
Load local system customization file
-->
<!-- <include ignore_missing="yes">fonts.conf.d</incllude> -->
<include ignore_missing="yes">~/fonts.conf.d</include></p> <p><!-- Font cache directory list --></p> <p> <cachedir>/var/cache/fontconfig</cachedir>
<cachedir prefix="xdg">fontconfig</cachedir>
<!-- the following element will be removed in the future -->
<cachedir>~/.fontconfig</cachedir></p> <p> <config>
<!--
These are the default Unicode chars that are expected to be blank
in fonts. All other blank chars are assumed to be broken and
won't appear in the resulting charsets
-->
<blank>
<int>0x0020</int> <!-- SPACE -->
<int>0x00A0</int> <!-- NO-BREAK SPACE -->
<int>0x00AD</int> <!-- SOFT HYPHEN -->
<int>0x034F</int> <!-- COMBINING GRAPHEME JOINER -->
<int>0x0600</int> <!-- ARABIC NUMBER SIGN -->
<int>0x0601</int> <!-- ARABIC SIGN SANAH -->
<int>0x0602</int> <!-- ARABIC FOOTNOTE MARKER -->
<int>0x0603</int> <!-- ARABIC SIGN SAFHA -->
<int>0x06DD</int> <!-- ARABIC END OF AYAH -->
<int>0x070F</int> <!-- SYRIAC ABBREVIATION MARK -->
<int>0x115F</int> <!-- HANGUL CHOSEONG FILLER -->
<int>0x1160</int> <!-- HANGUL JUNGSEONG FILLER -->
<int>0x1680</int> <!-- OGHAM SPACE MARK -->
<int>0x17B4</int> <!-- KHMER VOWEL INHERENT AQ -->
<int>0x17B5</int> <!-- KHMER VOWEL INHERENT AA -->
<int>0x180E</int> <!-- MONGOLIAN VOWEL SEPARATOR -->
<int>0x2000</int> <!-- EN QUAD -->
<int>0x2001</int> <!-- EM QUAD -->
<int>0x2002</int> <!-- EN SPACE -->
<int>0x2003</int> <!-- EM SPACE -->
<int>0x2004</int> <!-- THREE-PER-EM SPACE -->
<int>0x2005</int> <!-- FOUR-PER-EM SPACE -->
<int>0x2006</int> <!-- SIX-PER-EM SPACE -->
<int>0x2007</int> <!-- FIGURE SPACE -->
<int>0x2008</int> <!-- PUNCTUATION SPACE -->
<int>0x2009</int> <!-- THIN SPACE -->
<int>0x200A</int> <!-- HAIR SPACE -->
<int>0x200B</int> <!-- ZERO WIDTH SPACE -->
<int>0x200C</int> <!-- ZERO WIDTH NON-JOINER -->
<int>0x200D</int> <!-- ZERO WIDTH JOINER -->
<int>0x200E</int> <!-- LEFT-TO-RIGHT MARK -->
<int>0x200F</int> <!-- RIGHT-TO-LEFT MARK -->
<int>0x2028</int> <!-- LINE SEPARATOR -->
<int>0x2029</int> <!-- PARAGRAPH SEPARATOR -->
<int>0x202A</int> <!-- LEFT-TO-RIGHT EMBEDDING -->
<int>0x202B</int> <!-- RIGHT-TO-LEFT EMBEDDING -->
<int>0x202C</int> <!-- POP DIRECTIONAL FORMATTING -->
<int>0x202D</int> <!-- LEFT-TO-RIGHT OVERRIDE -->
<int>0x202E</int> <!-- RIGHT-TO-LEFT OVERRIDE -->
<int>0x202F</int> <!-- NARROW NO-BREAK SPACE -->
<int>0x205F</int> <!-- MEDIUM MATHEMATICAL SPACE -->
<int>0x2060</int> <!-- WORD JOINER -->
<int>0x2061</int> <!-- FUNCTION APPLICATION -->
<int>0x2062</int> <!-- INVISIBLE TIMES -->
<int>0x2063</int> <!-- INVISIBLE SEPARATOR -->
<int>0x206A</int> <!-- INHIBIT SYMMETRIC SWAPPING -->
<int>0x206B</int> <!-- ACTIVATE SYMMETRIC SWAPPING -->
<int>0x206C</int> <!-- INHIBIT ARABIC FORM SHAPING -->
<int>0x206D</int> <!-- ACTIVATE ARABIC FORM SHAPING -->
<int>0x206E</int> <!-- NATIONAL DIGIT SHAPES -->
<int>0x206F</int> <!-- NOMINAL DIGIT SHAPES -->
<int>0x2800</int> <!-- BRAILLE PATTERN BLANK -->
<int>0x3000</int> <!-- IDEOGRAPHIC SPACE -->
<int>0x3164</int> <!-- HANGUL FILLER -->
<int>0xFEFF</int> <!-- ZERO WIDTH NO-BREAK SPACE -->
<int>0xFFA0</int> <!-- HALFWIDTH HANGUL FILLER -->
<int>0xFFF9</int> <!-- INTERLINEAR ANNOTATION ANCHOR -->
<int>0xFFFA</int> <!-- INTERLINEAR ANNOTATION SEPARATOR -->
<int>0xFFFB</int> <!-- INTERLINEAR ANNOTATION TERMINATOR -->
</blank>
<!--
Rescan configuration every 30 seconds when FcFontSetList is called
-->
<rescan>
<int>30</int>
</rescan>
</config></p> <p></fontconfig></p> <p>/etc/fonts/fonts.conf
第二步:对英文字体进行分类
请注意,我只对英文字体进行分类。对英文字体进行分类的目的是为了给相应的英文字体搭配正确的中文,比如字体为Arial的英文句子中,如果出现中文就应该用黑体,而字体为Times New Roman的英文句子中,如果出现中文当然应该用宋体。等宽的英文字体嘛,whatever,反正中文字都一样宽,哪个顺眼就用哪个吧。对于中文其实也可以分类,然后搭配不同的英文字体。但是我认为,中文的字体中一般都包含有英文字符,用原装的即可,没有必要替换。所以,不对中文进行分类。其代码如下:
代码如下:
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<!--
If the font still has no generic name, add sans-serif
-->
<match target="pattern">
<test qual="all" name="family" compare="not_eq">
<string>sans-serif</string>
</test>
<test qual="all" name="family" compare="not_eq">
<string>serif</string>
</test>
<test qual="all" name="family" compare="not_eq">
<string>monospace</string>
</test>
<test qual="all" name="family" compare="not_eq">
<string>宋体</string>
</test><test qual="all" name="family" compare="not_eq">
<string>黑体</string>
</test>
<edit name="family" mode="append_last">
<string>sans-serif</string>
</edit>
</match>
</fontconfig></p> <p>~/fonts.conf.d/03-treat-unclassified-fonts-as-sansserif.conf
到这里,所有的分类工作完成。使用fc-pattern命令可以看到字体名被替换的过程。如下图:
比如,当应用程序请求字体的pattern为“Time New Roman”时,pattern被更改为“Times New Roman” “serif”;当应用程序请求字体的pattern为“微软雅黑,不认识的字体”时,“sans-serif”被添加到了pattern的最后面。这也是字体分类的原理,就是将字体的类名添加到列表的后面。在Fontconfig的配置语法中,<alias>是<match>的一种简化写法,如果需要测试和替换的只是字体名的话,使用<alias>就更简单。如果使用<alias>,则<prefer>表示添加到所选字体的前面,<accept>表示添加到所选字体的后面,<default>表示添加到字体列表的最后。在这里选择用<accept>而没有用<default>的原因是,如果用<default>,每次都是把分类名添加到最后,遇到比较奇怪的pattern(比如上图中的最后一个测试)就会造成混乱。 第四步:对每一个字体分类,指定自己喜欢的字体
对每一个分类都可以指定一个字体列表,排在越前面的优先级越高。在每一个分类的最后指定一个中文字体的分类,当句子中出现中文时,前面的英文字体中肯定找不到相应的字符啦,这时就会一个一个往字体列表的后面找,直到在最后的中文字体里找到。代码如下:
代码如下:
写到这里,我不得不提到另外一个问题,就是<edit...binding="?">...</edit>中binding究竟应该设置为什么的问题。binding属性有几种选择,分别是binding="strong"、binding="weak"和binding="same"。如果该属性设置不合理,则会出现这样的问题:明明使用fc-pattern查看的时候是文泉驿点阵宋体排在AR PL UMing前面,是DejaVu Sans Mono排在文泉驿等宽正黑前面,但是使用fc-match匹配的时候,偏偏首选的是AR PL UMing和文泉驿等宽正黑。为什么会这样呢?这是因为Fontconfig选择字体的时候不仅仅只看字体名的排列顺序,还要综合考虑一种字体能覆盖的字符集和字体大小范围,所以,在前面的例子中,虽然文泉驿点阵宋体排在AR PL UMing前面,但是它覆盖的字体大小范围只有12px到16px,DejaVu Sans Mono虽然排在文泉驿等宽正黑前面,但是其覆盖的字符集不包含中日韩文,所以Fontconfig就会首选排在后面的字体。为了解决这个问题,就必须把binding属性设置为strong,这样,不管什么情况都首选排在前面的字体,只有遇到该字体不能胜任的字符时才选择后面的字体。在我的配置文件中,我都是一路strong到底。 第七步:对没有包含斜体和粗体的字体自动合成斜体和粗体
代码如下:
代码如下:
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<!--
Artificial oblique for fonts without an italic or oblique version
-->
<match target="font">
<!-- check to see if the font is roman -->
<test name="slant">
<const>roman</const>
</test>
<!-- check to see if the pattern requested non-roman -->
<test target="pattern" name="slant" compare="not_eq">
<const>roman</const>
</test>
<!-- multiply the matrix to slant the font -->
<edit name="matrix" mode="assign">
<times>
<name>matrix</name>
<matrix><double>1</double><double>0.2</double>
<double>0</double><double>1</double>
</matrix>
</times>
</edit>
<!-- pretend the font is oblique now -->
<edit name="slant" mode="assign">
<const>oblique</const>
</edit>
<!-- and disable embedded bitmaps for artificial oblique -->
<edit name="embeddedbitmap" mode="assign">
<bool>false</bool>
</edit>
</match></p> <p><!--
Synthetic emboldening for fonts that do not have bold face available
--></p> <p> <match target="font">
<!-- check to see if the font is just regular -->
<test name="weight" compare="less_eq">
<const>medium</const>
</test>
<!-- check to see if the pattern requests bold -->
<test target="pattern" name="weight" compare="more">
<const>medium</const>
</test>
<!--
set the embolden flag
needed for applications using cairo, e.g. gucharmap, gedit, ...
-->
<edit name="embolden" mode="assign">
<bool>true</bool>
</edit>
<!--
set weight to bold
needed for applications using Xft directly, e.g. Firefox, ...
-->
<edit name="weight" mode="assign">
<const>bold</const>
</edit>
</match>
</fontconfig></p> <p>~/fonts.conf.d/07-synthetic.conf