|
第一部份:Linux字体美化
约定:
1、本文中的官方网站指的是fontconfig官方网站
http://fontconfig.org/fontconfig-user.html
2、本文参考了网上的部分美化文章,主要参考了quanliking兄的
《Linux 字体微调 - windows 效果版 》
http://www.linuxsir.cn/bbs/showthread.php?t=266659
在此一并表示感谢
3、本文并不是全方位美化指南,只是对一些易于迷惑的概念进行了解释,具体的应用还需要要自已不断实践,起个抛砖引玉作用。
有什么疑惑可以在下面跟贴
4、本人不对因本文造成的物质、精神损失负责,实践有风险,操作须慎行
-、概述
在LINUX下面字体分成xft和corefonts,一些比较老的程序,通常是GTK1的程序还在使用核心字体(corefonts),像是这样的simsun.ttf-misc-simsun-bold-ro-normal--0-0-0-0-p-0-gb18030.2000-0,这些信息一般保留在字体所在的目录里面,由fonts.scale和fonts.dir保存,在GTK1程序(如xmms)中指定选用它们,进行使用。fonts.dir和fonts.scale一般由mkfontscale和mkfontdir生成,目前新版的mkfontscale已经不能生成带gb后缀的核心字体信息了,变了iso8859-1和iso10646-1了,我也不知道是为啥。
XFT字体就是我们在gtk2程序(firefox3 vim-gui gimp)中选字时见到的,一般是这样的SimSun(宋体) ,NSimSun(新宋体),文泉驿点阵(WenQuanYi Bitmap Song)等。xft字体通过freetype渲染,fontconfig进行解析,生成字体信息模板,供应用程序调用。
在此对核心字体(corefonts)不做累述,因为它们用到的时候不多,重点对xft字体的使用进行详述。在对待xft字体上面,我们中和fontconfig打交道,对freetype如何去渲染,应用程序如何去调用,我们不做过多的关心,也就是说,只要把fontconfig配置好了,字体基本上就定型了,至于微调,可能需要其它更加多知识。
二、字体的安装
找到一个合适的目录,一般情况下推荐/usr/share/fonts/TTF,把你喜欢的字体cp过去,然后执行mkfontscale生成fonts.scale,再cp fonts.scale fonts.dir,最后执行fc-cache -f -v 更新字体缓存,既完成了字体安装。安装好了的字体可能通过fc-list |more来查看,如果字体安装上了,就有相应的字体名在里,如SimSun ,WenQuanYi Zen Hei,PMingLiU等,当然也包括一些不可识别的中文字体名。一旦字体能在fc-list里面出现,就表示可以由fontconfig调用了。
三、fontconfig工作机制
fontconfig主要通过读取/etc/fonts/fonts.conf中的内容来进行字体解析,可以在fonts.conf当中通过include关键字把你自己的字体配置方案包含进来,<include ignore_missing="yes">local.conf</include>,local.conf默认路径放在/etc/fonts,当然你可以指定任何地方,在<include> </includ>中间把路径标明。
特别说明:如果fontconfig配置文件出现错误,应用程序启动的时候会出现错误提示,给你说第XX行出错,错误原因是什么。然后fontconfig过程在错误处中止,中止字体匹配过程,字体匹配失效。
fontconfig主要影响两方面的内容:
一是读解析文件,根据字体配置文件的内容,对字体属性进行更改,主要征对<edit> </edit>里的关键字的值进行修改,达到调整字体属性的目的,然后保存为一个字体属性模板,提供给应用程序读取;
二是接收应用程序的请求,比如firefox要用宋体(SimSun) 14 来显示字体,fontconfig在接到请求后就在字体属性模板进行查找,看看是不是存在SimSun字体,如果存在,读取SimSun信息;再看看SimSun的字号是不是大于14,14号字体是不是有什么特别限制(如大于12号开AA,14号大小12号,就把AA属性置为True,合并进入应用程序的请求模板),等所有的应用程序请求要求都全部读完时就生成一个应用程序模板,返给应用程序。如果没有大于14号的SimSun或者大于14号的SimSun已经被另一字体替代(如PMingLiU),就读取PMingLiU信息,生成包含PMingLiU信息的模板。应用程序就用fontconfig返还回来,经过修改属性的模板进行绘字(如果发生了PMingLiU替换SimSun的动作,你看到的14号的SimSun就有可能不是SimSun,而是PMingLiU了)。
四、一些关键的操作
<match>关键字
match用来指定匹配对像,主要有两个对象font和pattern,分别表示对字体和应用程序请求的模板进行操作(
<match target="font">
<test> </test>
</match>
)。不管对字体还是模板,只有match到了对像以后才能对实体进行相关操作,如test,edit等。当然你也可以对字体和模板进行同时操作,如
<match target="pattern">
<test target="font"></test>
</match>
说的是操作主要要对像是pattern,但是在其间对字体进行一次条件测试(test)。
<test>关键字
用来对match到的对像进行属性测试是否满足指定的条件(字体和模板属性在fontconfig官方文档里面有详细描述),一般是在match 指定target后再进行测试,要不,没有操作对像,测试谁去?<match target="pattern"> <test name="family" compare="contains"> <string>SimSun</string></test></match>这就完成了对模板的一个条件测试,测试应用程序是否在请求模板里面要求了包含了SimSun。当然,name不光光是family,还有可能是lang,size等,compare也有more more_eq lee less_eq eq等。根据条件选用,具体在fontconfig官方网站已经列出。
test也可以进行多重条件测试和步进条件测试:
多重测试,测试family字段的值中是否含有Sun,Ming或WenQuanYi字样:
<test name="family" compare="contains" qual="any">
<string>Sun</string>
<string>Ming</string> <string>WenQuanYi</string>
</test>
步进测试:先测试是否SimSun字体,再测其字体大小是不是大于8.5pt(这个写法好像有点问题,我觉得第二个test应该包含在第一个test内,形成<test> <test> </test></test>)
<test name="family" compare="eq"> <string>SimSun</string>
</test>
<test name="size" compare="more"> <double>8.5</double>
</test>
<edit>关键字
对指定的字段名或符合test后的字段名的值进行修改
<test name="family" compare="eq"> <string>SimSun</string>
</test>
<edit name="family" mode="assign"> <string>MingLiU</string>
</edit> 就完成对一个family字段的替换工作,由SimSun替换成了PMingLiU。
<match target="pattern">
<edit name="dpi" mode="assign"> <double>102</double>
</edit>
</match>不进行条件测试,强制修改请求模块中的DPI值,从默认的75修改成为102
name属性
name的值一部份可以在fontconfig官方网站查到,更具体的可以用这个命令 fc-match -v Tahoma Tahoma为字体名,你可以换成你喜欢的字体。 通过fc-match -v 可以显示你指定的字体所有属性,从而用name指定属性名,用edit更改属性值,达到对字体进行修正,以符合特别要求的目的。
compare属性
compare主要为less,less_eq,more,more_eq,eq,contains等,更详细的参考fontconfig官方网站。主要用于指定比较参数,相当程序设计语言中的比较符。
mode属性
mode为指定edit采用何种方式对name值进行修改,主要有assign(直接替换,多用于字体属性修改),prepend(匹配前插入头部,多用于中英文字体顺序调整),apppend(追加),更多方式见官方网站。
qual属性
qual为指定多元条件测试的范围,any为任何一个子元素成立,整个测试就成立;all为所有的元素都满足测试条件,测试才能成立。
几种类型
bool,用于是否开启name指定的属性值,name对应类型可以在官方网站查到 .
<edit name="antialias" mode="assign"> <bool>true</bool> </edit>
string,多用于指定字体名和厂商名(foundary)等,更多属性见官方网站。
<edit name="family" mode="prepend"> <string>Tahoma</string></edit>
double,多用于指定尺寸大小,如size,pixple,dpi等。
<test name="size" compare="less"> <double>12.5</double>
</test>
<edit name="embeddedbitmap" mode="assign">
<bool>true</bool>
</edit>
int, 多用于指定字重weight,在粗体合成中经常遇到。
<test name="weight" compare="more><int>100</int>
</test>
<edit name="embolden" mode="assign"><bool>true</bool>
</edit>
const,为fontconfig内置常量,主要用在指定字重上面和hinting风格上面,分别有light,medium,bold和hintnone,hintslight等,<edit name="hintstyle" mode="assign"><const>hintfull</const></edit>
以上为几种主要的name字段的类型,在使用的时候不要指定错类型,否则fontconfig会报错。
关于antialias (AA)和hinting
AA主要是为了解决小字模糊和大字破碎,而hinting主要起平滑作用,具体使用方向不很明确。当字号大到超过TTF字体内嵌的点阵字号时,就必须开启AA,否则字体将严重破碎,英文字体尽量开AA,不开AA看着实在很痛苦。。。。字号越大的字开AA看着越漂亮
在实际使用中,对7~12pt以下的字体基本使用内嵌点阵,达到较好的显示效果,因为这个范围内的字开AA感觉很有点模糊,脏兮兮的。。。对中文来说,启用点阵是很漂亮的,但是对英文就是个恶梦,但是英文一开AA后就立马变得粗粗黑黑,与不开AA,启用点阵,细细长长的中文相比,极度不协调!所以,只好中英文同时用点阵,同时开AA。
很多美化中都提到对8~17号字关闭AA,启用内部点阵就是这个道理,但是在linux字体微调这篇文章中征对各个字体的特性,按照不同的字号对字体开关AA和hinting进行了更为细微的优化,所以8~17号字关AA,开点阵从原则上没有问题,只不过略显粗放罢了
关于中英文替换动作
由于很多中文字体所带的英文字体不够好看,比如SimSun自带的英文就很丑,在点阵状态下,高度仅有中文的一半高,正常情况下应该和中文差不多高的,因此看着特别别扭,所以就要执行字体替换动作,用一纯英文字体放在SimSun前面。fontconfig会优先采用SimSun前的英文字体,因为纯英文字体中没有中文,所以中文部分还是会采用SimSun的。
目前有两种方式进行替换,但是我发现只有对pattern的操作有效。
方式1:
<match target="font">
<test target="pattern" name="family" compare="contains">
<string>Sun</string>
<string>Ming</string>
</test>
<edit name="family" mode="prepend"> <string>Arial</string>
</edit>
</match>
方式2::
<match target="pattern">
<test name="family" compare="contains"> <string>Sun</string>
<string>Ming</string>
</test>
<edit name="family" mode="prepend"> <string>Arial</string>
</edit>
</match>
以上是征对应用程序请求模板的操作,如果应用程序请求包含Sun,Ming字符的字体名时,就将纯英文字体Arial插入到模板头部,让应用程序优先使用Arial.当然Arial也可以换成其他你喜欢的英文字体。方式2效果很好,方式1没有效果,但是动作是执行了,但是字体没有进行替换。
对字体属性的操作可以通过fc-match -v 字体名 来察看;对模板的操作可以通过fc-match -v sans 或fc-match -v serif来察看。如果以上替换操作成功,就可以发现在sans字体序列中,Arial在最前面,SimSun第二个。
三、美化的基本流程
1、列举字体序列(sans,serif,monosplace),指定这三类字体序列包含哪些字体。
2、修改全局变量
(1)更改DPI
DPI是屏幕解析度一个量化,只有在正确的DPI下你看到的字号才是正确的,否则,你看到的12pt的字可能就是14pt或10pt大小。关于DPI的详细信息、获取,在《linux字体微调》里有详述。
<match target="pattern">
<edit name="dpi" mode="assign"> <double>102</double>
</edit>
</match>
(2)调整全局中英文字体宽度
主要对两个变量进行操作:globaladvance,spacing
<!--
The dual-width Asian fonts (spacing=dual) are not rendered correctly,
apparently FreeType forces all widths to match. Trying to disable the
width forcing code by setting globaladvance=false alone doesn't help.
As a brute force workaround, also set spacing=proportional, i.e. handle
them as proportional fonts:
-->
<match target="font" >
<test target="pattern" name="lang" compare="contains" >
<string>zh</string>
<string>ja</string>
<string>ko</string>
</test>
<test name="spacing" compare="eq">
<const>dual</const>
</test>
<edit name="spacing" mode="assign" >
<const>proportional</const>
</edit>
<edit name="globaladvance" mode="assign" >
<bool>false</bool>
</edit>
</match>
其中的const值可以通过官方网站查到,字体修改后的spacing和globaladvance值可以通过fc-match -v 字体名看到。
3、字体在何种条件下开启AA和hinting,在linux字体微调中已经对每种字体的AA和hinting条件做了详述,你也可以只对你感兴趣的字体进行微调或直接全局8~17号字关闭AA,小于7号开aa,大于17号字AA+hinting.引用一段操作范例:
<!--
For point size less equal than 6 : only smoothed
-->
<match target="font" >
<test name="foundry" qual="any" >
<string>monotype</string>
<string>microsoft</string>
</test>
<test name="size" compare="less_eq" >
<double>6</double>
</test>
<edit name="antialias" mode="assign" >
<bool>true</bool>
</edit>
<edit name="autohint" mode="assign" >
<bool>false</bool>
</edit>
<edit name="hinting" mode="assign" >
<bool>false</bool>
</edit>
</match>
<!--
Arial Regular
-->
<match target="font" >
<test name="family" >
<string>Arial</string>
</test>
<test name="weight" compare="eq">
<const>regular</const>
</test>
<test name="slant" compare="eq" >
<const>roman</const>
</test>
<test name="size" compare="more_eq" >
<double>7</double>
</test>
<test name="size" compare="less_eq" >
<double>13</double>
</test>
<edit name="antialias" mode="assign" >
<bool>false</bool>
</edit>
<edit name="autohint" mode="assign" >
<bool>false</bool>
</edit>
<edit name="hinting" mode="assign" >
<bool>true</bool>
</edit>
<edit name="hintstyle" mode="assign" >
<const>hintfull</const>
</edit>
</match>
4、进行粗体和斜体合成
合成斜体
<!--
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>
</match>
为没有粗体的字体合成粗体
<match target="font">
<!-- check to see if the font is just regular -->
<test name="weight" compare="less_eq">
<int>100</int>
</test>
<!-- check to see if the pattern requests bold -->
<test target="pattern" name="weight" compare="more_eq">
<int>200</int>
</test>
<!-- set the embolden flag -->
<edit name="embolden" mode="assign">
<bool>true</bool>
</edit>
</match>
5、执行英文替换动作
<match target="pattern">
<test name="family" compare="contains">
<string>Sun</string>
<string>Ming</string>
</test>
<edit name="family" mode="prepend">
<string>Arial</string>
</edit>
</mtach>
对含有Sun和Ming字符的字体(SimSun,MingLiU)执行英文替换动作,在此处mode选为prepend而不是assign是为了防止英文字体把中文字体替换,使中文字体显示丢失。
至此,美化部分就完成了。需要注意的是,当match target="font"时,是对字体属性的操作,可以理解为静态操作,修改的是源;而match target="pattern", 是对模板属性的操作,可以理解为动态操作,修改的是目标。 |
|