原文地址:http://www.jinbuguo.com/gui/linux_fontconfig.html
本文的主題是Linux環境下的字體美化,但是首先得要有字體,然后才能談美化。所以第一件事就是“選字體”。
字體的分類
目前,世界上的字體至少有幾萬種,並且還在不斷增加中。但是基本上都可以歸為以下五類:
- monospace[等寬]
- 是指字符寬度相同的字體,用於需要字符嚴格對齊的場合,例如控制台和源代碼以及ASCII藝術。與此相對,字符寬度各不相同的字體稱為比例字體(其余四類字體都是)。不過,對於中文字體而言,並不存在等寬與比例的差別,因為所有中文字都是等寬的。我們平常所說的“xx等寬中文”其實只是說該字體的西文部分是等寬的。
- sans-serif[無襯線]
- 是指筆畫末端沒有修飾(襯線)的字體,通常用於屏幕顯示。中文的黑體與圓體就屬於此類字體。[注意]很多非專業人士會將粗體與黑體混為一談,造成概念上的混淆,應注意區分。
- serif[有襯線]
- 是指筆畫末端有修飾(襯線)的字體,通常用於打印。中文的宋體與仿宋就屬於此類字體。
- cursive[書法]
- 以手寫風格呈現的字體,又稱為“模擬筆跡”,僅用於需要表達強烈個性風格的場合。例如被很多平面設計師鄙視的"Comic Sans MS",以及中文的隸書、楷書、行楷、行書、草書等都屬於此類字體。
- calligraphic[藝術]
- 擁有強烈的藝術風格,同時又不以手寫風格呈現的字體,中文通常稱為“美術字”,亦僅用於需要表達強烈個性風格的場合。
上述的每一類字體都可以再進一步細分,但本文的目標不是研究字體的分類,所以點到即止。
對於像筆者這樣的“普通用戶”而言,並不關心如何選擇充滿個性而又豐富多彩的書法字與藝術字,因為它們的主要使用者是平面設計師這樣的專業用戶,我更關心的是前三種字體。所以本節主要關注等寬、無襯線、有襯線三種字體的選擇。
點陣與矢量
點陣字體的優點在於低像素下依然可以保持清晰銳利的筆畫,但其不能縮放的缺點也非常致命。而矢量字體則相反,可以任意縮放,但在低像素下的表現並不突出。傳統的做法是將點陣與矢量配合使用:低像素時使用點陣、高像素時使用矢量。不過在筆者看來,這僅僅是早期的一個權宜之策罷了,當下的矢量字體渲染技術已經非常成熟,特別是在LCD已經全面取代CRT的情況下,組合使用次像素渲染、抗鋸齒、字體微調三種技術,矢量字體在低像素下的顯示效果已經非常優秀,甚至在某種程度上已經超越了點陣字體。就中文字體的實際情況來說,點陣字體最小一般只能到11~12px,而且選擇的余地非常小,只有寥寥幾款看上去更像黑體的所謂“xx宋體”;而優秀的中文矢量字體,在配置得當的情況下,可以在10px時依然清晰可辨。基於如上原因,本文將僅使用矢量字體,而不使用任何點陣字體。
選中的字體
世上的字體千千萬,並不是安裝的越多越好。一方面,很多同類字體大同小異,沒必要全部安裝;另一方面,過多的字體會影響系統的運行效率,而且增加配置的復雜度。所以不能一味貪多,只需要安裝幾個具有代表性的字體即可。同時在字符覆蓋范圍上,只需要覆蓋東亞文字(中日韓)與西方文字(拉丁/希臘/西里爾)即可,沒必要追求覆蓋所有字符[反正也看不懂]。下面分門別類的依次說明每類字體的篩選要求、最終勝出的字體的來源,還有為使每種字體達到最佳顯示效果,應該使用的渲染參數(最小10px)。
西文等寬字體
篩選要求:
- 每個西文字符的寬度正好是中文的一半[spacing=90]
- 可以清晰區分"1lI"和"O0o"
- 原生粗體
- 行高合適[使用"字體查看器"目測即可]
字體來源:最終勝出的是一款來自日本的"Migu 1M"開源字體(migu-1m-20130617.zip),下載后解壓,從中提取"migu-1m-bold.ttf"與"migu-1m-regular.ttf"兩個文件即可。在實際選擇的過程中,筆者發現,能滿足后三條的字體有很多,但是能滿足第一條的卻鳳毛麟角,"Ubuntu Mono"可算其中之一,但是美觀度嘛,真心不敢恭維。此外,"Migu 1M"字體也是本文所使用的西文字體。
渲染參數:
antialias=true hinting=true autohint=false hintstyle=hintslight lcdfilter=lcddefault
西文無襯線字體
篩選要求:
- 可以清晰區分"1lI"和"O0o"
- 字符間距與"Arial"相當(包括粗體)
- 原生四體(常規/粗體/斜體/粗斜體)
- 行高合適[使用"字體查看器"目測即可]
字體來源:最終勝出的是來自Google的"Note"系列開源字體中的"Noto Sans"字體,下載zip包后解壓,從中提取"fonts/individual/hinted/NotoSans-*.ttf"四個文件即可。此外,之所以要求字符間距與"Arial"相當,是因為"Arial"的使用相當廣泛,而其字符間距較小,如果我們選取的字體字符間距過大,則有可能會破壞某些網頁的布局。在實際選擇的過程中,筆者發現,能滿足后兩條的字體有很多,但是能滿足前兩條的卻不多。特別第一條,大多數字體都無法清晰區分"1lI"和"O0o"。
渲染參數:
antialias=true hinting=true autohint=false hintstyle=hintslight(10px,12px) hintstyle=hintfull(其他) lcdfilter=lcddefault
西文有襯線字體
篩選要求:
- 可以清晰區分"1lI"和"O0o"
- 字符間距與"Times New Roman"相當(包括粗體)
- 原生四體(常規/粗體/斜體/粗斜體)
- 行高合適[使用"字體查看器"目測即可]
字體來源:最終勝出的是來自Google的"Note"系列開源字體中的"Tinos"字體,下載zip包后解壓,從中提取"fonts/individual/hinted/Tinos-*.ttf"四個文件即可。此外,之所以要求字符間距與"Times New Roman"相當,是因為"Times New Roman"的使用相當廣泛,而其字符間距較小,如果我們選取的字體字符間距過大,則有可能會破壞某些網頁的布局。在實際選擇的過程中,筆者發現,能滿足后兩條的字體有很多,但是能滿足前兩條的卻不多。特別第一條,大多數字體都無法清晰區分"1lI"和"O0o"。就算是最終勝出的字體,也頂多算勉強合格。
渲染參數:
antialias=true hinting=true autohint=false hintstyle=hintslight(Regular/Bold=10px) hintstyle=hintfull(其他) lcdfilter=lcddefault
中文黑體(無襯線)
篩選要求:
- 漢字筆畫符合中國大陸的國家標准
- 完整覆蓋簡體/繁體/粵語/CJK擴展A區/日文字符[使用"字符映射表"即可查看(注意勾選"只顯示來自此字體的字形")]
- 原生粗體
- 行高合適[使用"字體查看器"目測即可]
字體來源:最終勝出的是來自Google的"Note"系列開源字體中的"思源黑體",下載zip包后解壓,從中提取"third_party/noto_cjk/NotoSansHans-*.otf"兩個文件即可。其實在黑體的選擇過程中,我在來自蘋果的"冬青黑體"與來自Adobe的"思源黑體"之間搖擺了很久,美觀度上,"冬青黑體"某些時候略占微弱優勢,但在字符集的覆蓋面上,"思源黑體"具有壓倒性的優勢,尤其是生僻字與各種中日韓符號。加上其開源的特性,最終選擇了"思源黑體"。需要提醒的是,不要使用"NotoSansCJK",因為需要解決'locl'問題(如果有誰解決了這個問題請告訴我)。至於被微軟吹上天的雅黑,面對它的中文標點符號,我只能“呵呵”了。
渲染參數:
antialias=true hinting=true autohint=false hintstyle=hintslight lcdfilter=lcddefault
中文宋體(有襯線)、中文仿宋(有襯線)、中文楷體(書法)
篩選要求:
- 漢字筆畫符合中國大陸的國家標准
- 完整覆蓋簡體/繁體/粵語/CJK擴展A區/日文字符[使用"字符映射表"即可查看(注意勾選"只顯示來自此字體的字形")]
- 行高合適[使用"字體查看器"目測即可]
字體來源:最終勝出的是來自Adobe CS 6的"Adobe 宋體 Std"、"Adobe 仿宋 Std"、"Adobe 楷體 Std",下載任意一個軟件的試用版,即可從中提取如下文件:"AdobeSongStd-Light.otf","AdobeFangsongStd-Regular.otf","AdobeKaitiStd-Regular.otf"。
注意,從 Creative Cloud 開始不再捆綁仿宋與楷體,必須從 Adobe Typekit 訂閱(因此只能非官方途徑更新)。此外,"Adobe 宋體 Std"還可以從Adobe Reader中提取,在Windows平台安裝后,提取"C:\Program Files\Adobe\Reader 11.0\Resource\CIDFont\AdobeSongStd-Light.otf"文件即可。
渲染參數:
antialias=true hinting=true autohint=false hintstyle=hintfull lcdfilter=lcddefault
韓文字體
字體來源:依然是來自Google的"Note"系列開源字體中的"思源黑體",下載zip包后解壓,從中提取"third_party/noto_cjk/NotoSansKR-*.otf"兩個文件即可。
渲染參數:
antialias=true hinting=true autohint=false hintstyle=hintslight lcdfilter=lcddefault
符號字體
字體來源:C:\Windows\Fonts\seguisym.ttf
渲染參數:
antialias=true hinting=true autohint=false hintstyle=hintfull lcdfilter=lcddefault
常見字體
除了上面選出的字體之外,我們還需要知道常見的中西文字體還包括哪些,后面撰寫"fonts.conf"配置文件的時候,需要使用這個信息。下表列出了來自 Windows, MS Office, Mac OS X, iOS, Android, Linux 中常見的中西文字體。
等寬 | 無襯線 | 有襯線 |
---|---|---|
Monospace mono |
Sans sans serif sans-serif |
Serif |
Andale Mono Andale Mono WT Bitstream Vera Sans Mono Biwidth Consolas Courier Courier New Cousine DejaVu Sans Mono Droid Sans Mono Fira Mono Fixed Fixedsys FreeMono Inconsolata Liberation Mono Lucida Console Lucida Sans Typewriter Luxi Mono Menlo Monaco Nimbus Mono L Source Code Pro Terminal Terminus Ubuntu Mono Unibit Unifont |
Akzidenz-Grotesk Andika Arev Sans Arial Arial Black Arial Narrow Arial Unicode MS Arimo Avenir Avenir Next Avenir Next Condensed Bitstream Vera Sans Calibri Candara Cantarell Carlito Century Gothic Charcoal Chicago Copperplate Gothic Corbel DejaVu Sans DejaVu Sans Condensed Droid Sans Droid Sans Fallback Fira Sans Franklin Gothic Bold Franklin Gothic Heavy Franklin Gothic Medium FreeSans Frutiger Frutiger Linotype Futura Gadget Geneva Gill Sans Gill Sans MT Gotham Haettenschweiler Helvetica Helvetica Neue Impact Liberation Sans Liberation Sans Narrow Linux Biolinum Lucida Grande Lucida Sans Lucida Sans Unicode Luxi Sans Microsoft Sans Serif MS Sans Serif Myriad Myriad Pro News Gothic MT Nimbus Sans L Noto Sans Noto Sans UI Open Sans Optima Roboto Roboto Condensed Segoe Segoe UI Source Sans Pro Tahoma Thonburi Trebuchet MS Tw Cen MT Ubuntu Ubuntu Condensed Univers Verdana |
Baskerville Baskerville Old Face Bell MT Big Caslon Bitstream Charter Bitstream CyberBase Bitstream Cyberbit Bitstream Vera Serif Bodoni MT Book Antiqua Bookman Old Style Californian FB Calisto MT Cambria Centaur Century Century Schoolbook Century Schoolbook L Charis SIL Code2000 Code2001 Constantia Cooper Black DejaVu Serif DejaVu Serif Condensed Didot Droid Serif Elephant FreeSerif Gabriola Garamond Gentium Georgia Goudy Old Style High Tower Text Hoefler Text Junicode Liberation Serif Linux Libertine Lucida Bright Lucida Fax Luxi Serif MS Serif New Athena Unicode New York Nimbus Roman No9 L Noto Serif Old Standard TT Palatino Palatino Linotype Perpetua Rockwell Sitka Sitka Banner Sitka Display Sitka Heading Sitka Small Sitka Subheading Sitka Text Source Serif Pro Times Times New Roman Tinos Utopia |
[說明]下面的“中文常見字體”列表中,字族名前面圓括號里的"等寬"、"無襯"、"有襯"表示的是該字體的西文部分的風格。
黑體 | 宋體 | 仿宋 | 楷體 |
---|---|---|---|
(無襯)"Source Han Sans" (無襯)"Source Han Sans CN" (無襯)"Source Han Sans SC" (無襯)"Source Han Sans TC" (無襯)"Source Han Sans TWHK" (無襯)"思源黑體" (無襯)"思源黑體" (無襯)"思源黑體 CN" (無襯)"思源黑體 TWHK" (無襯)"Noto Sans CJK" (無襯)"Noto Sans CJK Simplified Chinese" (無襯)"Noto Sans CJK Traditional Chinese" (無襯)"Noto Sans S Chinese" (無襯)"Noto Sans T Chinese" (無襯)"Hiragino Sans GB" (無襯)"冬青黑體簡體中文" (無襯)"冬青黑體簡體中文" (無襯)"Adobe Heiti Std" (無襯)"Adobe 黑體 Std" (無襯)"Adobe Fan Heiti Std" (無襯)"Adobe 繁黑體 Std" (無襯)"Hei" (無襯)"LiHei Pro" (無襯)"STHeiti" (等寬)"SimHei" (等寬)"黑體" (無襯)"Heiti TC" (無襯)"黑體-繁" (無襯)"黑體-繁" (無襯)"Heiti SC" (無襯)"黑體-簡" (無襯)"黑體-簡" (無襯)"STXihei" (無襯)"華文細黑" (無襯)"Lantinghei SC" (無襯)"蘭亭黑-簡" (無襯)"蘭亭黑-簡" (無襯)"Lantinghei TC" (無襯)"蘭亭黑-繁" (無襯)"蘭亭黑-繁" (無襯)"Microsoft JhengHei" (無襯)"Microsoft JhengHei UI" (無襯)"微軟正黑體" (無襯)"Microsoft YaHei" (無襯)"Microsoft YaHei UI" (無襯)"微軟雅黑" (無襯)"WenQuanYi Bitmap Song" (無襯)"WenQuanYi Micro Hei" (無襯)"文泉驛微米黑" (無襯)"文泉驛微米黑" (等寬)"WenQuanYi Micro Hei Mono" (等寬)"文泉驛等寬微米黑" (等寬)"文泉驛等寬微米黑" (無襯)"WenQuanYi Zen Hei" (無襯)"文泉驛正黑" (無襯)"文泉驛正黑" (等寬)"WenQuanYi Zen Hei Mono" (等寬)"文泉驛等寬正黑" (等寬)"文泉驛等寬正黑" (無襯)"WenQuanYi Zen Hei Sharp" (無襯)"文泉驛點陣正黑" (無襯)"文泉驛點陣正黑" |
(有襯)"Adobe Song Std" (有襯)"Adobe 宋體 Std" (有襯)"Adobe Ming Std" (有襯)"Adobe 明體 Std" (等寬)"AR PL UMing CN" (等寬)"AR PL UMing HK" (等寬)"AR PL UMing TW" (等寬)"AR PL UMing TW MBE" (有襯)"Apple LiSung" (有襯)"GB18030 Bitmap" (有襯)"LiSong Pro" (等寬)"Ming(for ISO10646)" (有襯)"STSong" (有襯)"華文宋體" (有襯)"STZhongsong" (有襯)"華文中宋" (有襯)"SimSun" (有襯)"宋體" (等寬)"NSimSun" (等寬)"新宋體" (等寬)"SimSun-ExtB" (有襯)"SimSun-18030" (有襯)"宋體-18030" (等寬)"NSimSun-18030" (等寬)"新宋體-18030" (有襯)"Songti SC" (有襯)"宋體-簡" (有襯)"宋體-簡" (有襯)"Songti TC" (有襯)"宋體-繁" (有襯)"宋體-繁" (有襯)"AR PLBaosong2GBK Light" (有襯)"文鼎PL報宋二GBK" (等寬)"AR PL SungtiL GB" (等寬)"文鼎PL簡報宋" (有襯)"AR PLMingU20 Light" (有襯)"文鼎PL明體U20-L" (等寬)"AR PL Mingti2L Big5" (等寬)"文鼎PL細上海宋" (有襯)"AR PL ShanHeiSun Uni" (有襯)"文鼎PL細上海宋Uni" (有襯)"文鼎PL細上海宋Uni" (有襯)"AR PL New Sung" (有襯)"文鼎PL新宋" (等寬)"AR PL New Sung Mono" (等寬)"文鼎PL新宋 Mono" (等寬)"MingLiU" (等寬)"細明體" (等寬)"MingLiU-ExtB" (等寬)"細明體-ExtB" (有襯)"PMingLiU" (有襯)"新細明體" (有襯)"PMingLiU-ExtB" (有襯)"新細明體-ExtB" (等寬)"MingLiU_HKSCS" (等寬)"細明體_HKSCS" (等寬)"MingLiU_HKSCS-ExtB" (等寬)"細明體_HKSCS-ExtB" |
(有襯)"Adobe Fangsong Std" (有襯)"Adobe 仿宋 Std" (等寬)"FangSong_GB2312" (等寬)"仿宋_GB2312" (等寬)"FangSong" (等寬)"仿宋" (有襯)"STFangsong" (有襯)"華文仿宋" |
(有襯)"Adobe Kaiti Std" (有襯)"Adobe 楷體 Std" (等寬)"AR PL UKai CN" (等寬)"AR PL UKai HK" (等寬)"AR PL UKai TW" (等寬)"AR PL UKai TW MBE" (有襯)"BiauKai" (有襯)"Kai" (等寬)"DFKai-SB" (等寬)"標楷體" (有襯)"STKaiti" (有襯)"華文楷體" (等寬)"KaiTi" (等寬)"楷體" (有襯)"Kaiti SC" (有襯)"楷體-簡" (有襯)"楷體-簡" (有襯)"Kaiti TC" (有襯)"楷體-繁" (有襯)"楷體-繁" (等寬)"SimKai" (等寬)"KaiTi_GB2312" (等寬)"楷體_GB2312" (等寬)"AR PL KaitiM GB" (等寬)"文鼎PL簡中楷" (等寬)"AR PL New Kai" (等寬)"文鼎PL新中楷" (等寬)"AR PL KaitiM Big5" (等寬)"文鼎PL中楷" (有襯)"AR PL ZenKai Uni" (有襯)"文鼎PL中楷Uni" |
fonts.conf詳解
配置文件的結構
整個配置文件由如下幾個部分依次拼接而成:
- 目錄設置(<dir>, <cachedir>, <include>)
- 雜項設置(<config>)
- 掃描階段(<match target="scan">)
- 匹配階段(<alias>, <match target="pattern">)
- 渲染階段(<match target="font">)
目錄設置
<!-- 字體目錄 --> <dir>/opt/fonts/core</dir> <!-- <dir>/opt/fonts/ext</dir> -->
由於這些字體都是自己選取的,不受系統的包管理器控制,所以安裝到"/opt/fonts"目錄中。至於為什么還要分為"core"與"ext"兩個子目錄,出於如下原因:對某些用戶而言,本文使用的字體不足以滿足其需求,他們需要安裝更多的字體,但是這些字體又不需要放到 xorg.conf 中的 FontPath 里面,所以單獨再隔開一個目錄,效果會比較好。
<!-- 緩存目錄 --> <cachedir>/var/cache/fontconfig</cachedir>
緩存目錄沒啥好說的,整個系統范圍內的字體信息都緩存到同一個地方而已。
<!-- 額外的配置目錄 --> <!-- <include>/etc/fonts/conf.d</include> -->
對於額外的配置目錄,本文沒有使用,而是將所有的配置指令都直接放在了 fonts.conf 文件中。這不是官方推薦的做法,因為軟件包升級的時候,fonts.conf 會被強制覆蓋,官方推薦將自定義的配置放在 local.conf 文件中。但是本文出於兩個原因違背了官方的推薦:(1)官方推薦的做法將一個配置文件打散為N多個部分,雖然獲得了一定的靈活性,但是不便於理解與維護。而本文只是一個示范,易於理解是首要的。(2)軟件包升級之后,再覆蓋一下也很方便。
雜項設置
<config> <blank><!-- 空白字符 --> <int>0x0020</int><int>0x00A0</int><int>0x00AD</int><int>0x034F</int> <int>0x0600</int><int>0x0601</int><int>0x0602</int><int>0x0603</int> <int>0x06DD</int><int>0x070F</int><int>0x115F</int><int>0x1160</int> <int>0x1680</int><int>0x17B4</int><int>0x17B5</int><int>0x180E</int> <range><int>0x2000</int><int>0x200F</int></range> <range><int>0x2028</int><int>0x202F</int></range> <range><int>0x205F</int><int>0x2063</int></range> <range><int>0x206A</int><int>0x206F</int></range> <int>0x2800</int><int>0x3000</int><int>0x3164</int><int>0xFEFF</int> <int>0xFFA0</int><int>0xFFF9</int><int>0xFFFA</int><int>0xFFFB</int> </blank> <!-- 每小時掃描一次配置文件與字體的變化 --> <rescan><int>3600</int></rescan> </config>
<blank>段指明了哪些Unicode字符應該顯示為空白,這是直接從官方默認的配置中抄來的,除了出於縮短配置文件長度的目的,把一系列連續的<int>用<range>進行了取代之外,沒有任何修改。關於<blank>的詳細解釋,請參考《fonts.conf 中文手冊》。
官方默認的配置是每30秒掃描一次配置文件與字體的變化,這里修改為每小時掃描一次。因為頻繁的掃描會增加系統的負載,而配置文件與字體在設定好之后,並不會頻繁變動,每小時掃描一次足矣。
掃描階段
掃描階段是最早發生的階段,它的作用是告訴應用程序:系統上安裝了哪些字體,這些字體的每個屬性的值是什么。通常用來糾正或修改字體的固有屬性。
[提示]要想看到<match target="scan">對"foo.ttf"的效果,可以分別使用如下兩個命令,對比它們的輸出結果就可以了:
fc-query /path/to/foo.ttf fc-scan /path/to/foo.ttf
西文字體舉例
<match target="scan"> <test name="family"><string>Migu 1M</string></test> <edit name="family"><string>Monospace</string></edit> <edit name="lang"><langset><string>en</string></langset></edit> <edit name="charset"> <charset> <!-- 基本拉丁(ASCII) --> <range><int>0x0020</int><int>0x007E</int></range> <!-- 此處省略了其他<range>與<int>單元,完整的配置請查看fonts.conf --> </charset> </edit> </match>
<edit name="family">的作用是將不直觀的字族名稱"Migu 1M"修改為通用名稱"Monospace",目的在於更清晰的表示這是默認的等寬字體。此外,改為通用名稱還有一個好處,那就是可以在字體選擇列表中節約一行,因為無論你的系統上是否真的安裝了名為"Monospace"的字體,都會顯示這么一行,既然如此,那不如將默認的等寬字體直接改為通用名稱算了。類似的,另外兩個西文字體的重命名("Sans"與"Serif"),也是出於同樣的原因。
<edit name="lang">的作用是強制將該字體支持的語言指定為"en",配合后面匹配階段的指令(<edit name="lang"><string>en</string></edit>),可以確保優先使用西文字體顯示西文字符,以實現對中文字體中丑陋的西文部分的替換(因為"lang"屬性優先於弱綁定的字族名)。類似的,另外兩個西文字體也進行了同樣的修改。
<edit name="charset">的作用是明確指定該字體所含字符的Unicode碼點,主要用於屏蔽字體中的某些字符。以"Migu 1M"字體來說,因為它是個來自日本的字體,里面不僅包含了我們需要的西文字符,也包含了許多CJK統一表意字符以及全角標點符號等非西文字符,如果我們不加屏蔽的使用,就會出現許多漢字的筆畫不符合中國大陸的國家標准(日文寫法),以及中文標點符號不美觀之類的問題,所以必須加以屏蔽。類似的,另外兩個西文字體("Sans"與"Serif"),由於它們都包含了不美觀的中文標點符號,以及一些不想使用的非西文字符(拉丁/希臘/西里爾之外的字符),所以也用同樣的方法進行了屏蔽。
中文字體舉例
<match target="scan"> <test name="postscriptname"><string>AdobeSongStd-Light</string></test> <edit name="family"><string>zhSong</string></edit> <edit name="style"><string>Regular</string></edit> <edit name="weight"><int>80</int></edit> <edit name="lang"><langset><string>zh-cn</string></langset></edit> </match>
與前述西文字體類似,這里使用<edit name="family">將字族名修改為"zhSong"(不存在的字族名),以確保它不會被網頁上指定的字體(強綁定)匹配到,配合后面匹配階段的指令(<alias>與<edit name="lang"><string>en</string></edit>),可以確保優先使用西文字體顯示西文字符,以實現對中文字體中丑陋的西文部分的替換(因為"lang"屬性優先於弱綁定的字族名)。類似的,其他三個核心中文字體也進行了同樣的修改。
<edit name="style">將字體樣式的名稱修改為"Regular",以確保所有字體的樣式都在顯示上保持一致性,否則將會在字體樣式中顯示"L"而不是"Regular"。同樣的,使用<edit name="weight">將字重值修改為"80"也是為了保持和其他字體的一致性。
<edit name="lang">的作用是強制將該字體支持的語言指定為"zh-cn",配合后面匹配階段的指令(<edit name="lang"><string>en</string></edit>),可以確保優先使用西文字體顯示西文字符,以實現對中文字體中丑陋的西文部分的替換(因為"lang"屬性優先於弱綁定的字族名)。類似的,其他三個核心中文字體也進行了同樣的修改。
其他字體舉例
<match target="scan"> <test name="postscriptname"><string>NotoSansKR-Bold</string></test> <edit name="family"><string>zzFailBack</string><string>zzKorean</string></edit> <edit name="familylang"><string>en</string><string>en</string></edit> <edit name="lang"><langset><string>ko</string></langset></edit> </match>
對於韓文字體(非中西文字體),將字族名修改為"zzFailBack"+"zzKorean"(也就是有兩個字族名),前一個是首選名字,會在字體列表中顯示出來,后一個是字體自身的名字,用於在配置文件中區分各個字體。而將所有非中西文字體以及符號字體統一賦予一個首選的"zzFailBack"名稱,目的在於將所有非中西文字體在字體列表中歸結為同一個項目,以節約列表空間。
調試工具
要充分理解字體匹配過程的細節,需要一個犀利的工具,幫助詳細查看Fontconfig的整個工作過程。這個工具就是環境變量"FC_DEBUG"以及"fc-match"。此外,要使用好"fc-match",還必須要熟悉"Font Name"(字體模板的格式)的結構。例如以最詳細的調試模式,查看對"宋體,15磅,簡體中文文檔"的匹配過程,可以使用如下命令:
FC_DEBUG=8191 fc-match -s '宋體-15:lang=zh-cn'
又例如,可以使用如下命令查看火狐瀏覽器在渲染頁面時,與Fontconfig的互動過程:
FC_DEBUG=5 firefox http://www.example.com/foo.html
[提示]輸出的調試信息中,前面有很長一部分是顯示火狐自身用戶界面(例如菜單文字)時的信息,后面才是網頁渲染相關的信息。
匹配階段
"family"列表的修改
匹配階段最主要的工作就是修改"family"列表。
首先第一步,使用已安裝的字體替換所有未安裝的常見字體,規則如下:
- 保持原有綁定不變
- 將常見西文字體替換為對應的字體類
- 將常見中文字體替換為對應的"西文字體類+zhXXX"(參見上一節的"中文常見字體"表)
<!-- 第一步,替換所有未安裝的常見字體 --> <alias binding="same"><family>mono</family><prefer><family>Monospace</family></prefer></alias> <alias binding="same"><family>Candara</family><prefer><family>Sans</family></prefer></alias> <alias binding="same"><family>文鼎PL中楷</family><prefer><family>Monospace</family><family>zhKai</family></prefer></alias> <alias binding="same"><family>AR PL ZenKai Uni</family><prefer><family>Serif</family><family>zhKai</family></prefer></alias> <!-- 這里省略了300多個其他類似的<alias>單元,完整的配置請查看fonts.conf -->
經過上述一系列替換動作之后,每一個能夠被識別的常見字體,都找到了替身。
下面是一段僅針對火狐瀏覽器的配置,作用是刪除"family"列表頭部不可識別的字體,以確保"family"列表的第一項可以被識別。
<!-- 第二步,剔除列表頭部不可識別的字體(僅對firefox),重復5次,確保剔除干凈,為后面補全"zhXXX"與設置"isDengKuan"標記打基礎 --> <match> <test name="prgname"><string>firefox</string></test> <test qual="first" name="family" compare="not_contains"><string>@font-face:</string></test> <test qual="first" name="family" compare="not_eq"><string>Monospace</string></test> <test qual="first" name="family" compare="not_eq"><string>Sans</string></test> <test qual="first" name="family" compare="not_eq"><string>Serif</string></test> <test qual="first" name="family" compare="not_eq"><string>zhHei</string></test> <test qual="first" name="family" compare="not_eq"><string>zhSong</string></test> <test qual="first" name="family" compare="not_eq"><string>zhFangSong</string></test> <test qual="first" name="family" compare="not_eq"><string>zhKai</string></test> <edit name="family" mode="delete"></edit> </match> <!-- 這里省略了其他4個完全相同的配置段 -->
首先,只有類似瀏覽器這種需要處理外來不可控文檔的場合,才會出現不可識別的字體,而對於可控文檔(例如文本編輯器),使用的是字體選擇器選定的字體,不會出現無法識別的情況。其次,刪除不可識別字體是一個破壞性的操作,可能會造成不良后果,必須謹慎為之,所以才將上述配置嚴格限定於僅作用於火狐瀏覽器(<test name="prgname">)。
你也許會問,那些不可識別的字體,反正也不會被匹配到,也就是說,它們並不影響字體的匹配結果,為什么還要刪除它們呢?原因注釋里說的很清楚,是為后面補全"zhXXX"與設置"isDengKuan"標記打基礎。為了達到這個目標,必須確保"family"列表的第一項是可以識別的:要么是網頁內嵌的字體(以'@font-face:'開頭),要么是系統上已經安裝的核心字體。至於為什么,讀到后面你自然就明白了。
下面是西文字體的補全操作,相當於設置默認的西文字體。指令本身一看就懂,不需要過多的解釋。
<!-- 第三步,如果不存在任何西文字體類,那么追加一個默認的西文字體類(弱綁定) --> <match> <test name="family" qual="all" compare="not_eq"><string>Monospace</string></test> <test name="family" qual="all" compare="not_eq"><string>Sans</string></test> <test name="family" qual="all" compare="not_eq"><string>Serif</string></test> <edit name="family" mode="append_last"><string>Sans</string></edit> </match>
經過上面的西文字體補全操作之后,現在"family"列表中必定存在至少一個西文字體類。這樣就可以根據西文字體來進行中文字體的補全操作了(相當於設置默認的中文字體):
<!-- 第四步,如果不存在任何核心中文(zhXXX),那么根據西文字體類補上對應的"zhXXX"(弱綁定) --> <match> <test name="family" qual="all" compare="not_eq"><string>zhHei</string></test> <test name="family" qual="all" compare="not_eq"><string>zhSong</string></test> <test name="family" qual="all" compare="not_eq"><string>zhFangSong</string></test> <test name="family" qual="all" compare="not_eq"><string>zhKai</string></test> <test name="family" qual="all" compare="not_eq"><string>Serif</string></test><!-- 沒有Serif --> <edit name="family" mode="append_last"><string>zhHei</string></edit><!-- 那么僅有Monospace與Sans --> </match> <match> <test name="family" qual="all" compare="not_eq"><string>zhHei</string></test> <test name="family" qual="all" compare="not_eq"><string>zhSong</string></test> <test name="family" qual="all" compare="not_eq"><string>zhFangSong</string></test> <test name="family" qual="all" compare="not_eq"><string>zhKai</string></test> <test name="family" qual="all" compare="not_eq"><string>Monospace</string></test><!-- 沒有Monospace --> <test name="family" qual="all" compare="not_eq"><string>Sans</string></test><!-- 並且沒有Sans --> <edit name="family" mode="append_last"><string>zhSong</string></edit><!-- 那么僅有Serif --> </match> <!-- 繼續第四步,如果"family"列表中依然沒有"zhXXX",那就表示出現了Monospace,Sans與Serif混雜的情況。那么根據列表第一項決定對應的"zhXXX"(弱綁定) --> <match> <test name="family" qual="all" compare="not_eq"><string>zhHei</string></test> <test name="family" qual="all" compare="not_eq"><string>zhSong</string></test> <test name="family" qual="all" compare="not_eq"><string>zhFangSong</string></test> <test name="family" qual="all" compare="not_eq"><string>zhKai</string></test> <test name="family" qual="first"><string>Serif</string></test><!-- 第一項是Serif --> <edit name="family" mode="append_last"><string>zhSong</string></edit> </match> <match> <test name="family" qual="all" compare="not_eq"><string>zhHei</string></test> <test name="family" qual="all" compare="not_eq"><string>zhSong</string></test> <test name="family" qual="all" compare="not_eq"><string>zhFangSong</string></test> <test name="family" qual="all" compare="not_eq"><string>zhKai</string></test> <!-- 如果依然沒有"zhXXX",那就表示列表第一項是Monospace,Sans或無法識別(例如"@font-face:*") --> <edit name="family" mode="append_last"><string>zhHei</string></edit> </match>
經過上面的中文字體補全操作之后,現在"family"列表中必定存在至少一個中文字體,並且盡可能保持與西文字體的風格一致。
<!-- 最后一步,在列表結尾補上韓文與符號字體(弱綁定) --> <match> <edit name="family" mode="append_last"><string>zzKorean</string><string>zzSymbol</string></edit> </match>
其他屬性
<match> <!-- 設置合理的像素密度,確保pt與px之間能夠合理轉換 --> <edit name="dpi"><double>96</double></edit> </match>
像素密度(DPI)是一個非常重要的參數,它是pt(磅)與px(像素)之間相互轉換的橋梁。"磅"是一個絕對長度單位,具體說來就是:1磅=1/72英寸=0.35278毫米。但是"像素"卻是一個相對長度單位。以我的顯示屏為例,其分辨率是1280x800像素,物理尺寸是331x207毫米(也就是13.0315x8.1496英寸),那么,水平DPI=1280/13.0315=98.22,垂直DPI=800/8.1496=98.16,也就是說,我的顯示器實際DPI大約是"98.2"(像素/英寸)。進一步可知,對於我的顯示器而言,1像素=(1/98.2)英寸=0.2586558毫米。如果應用程序要求顯示16px大小的文字,那很簡單,直接按16px顯示就可以了。但是如果應用程序要求顯示16pt(=16/72英寸=5.6444毫米)大小的文字,那么就得用(16*98.2)/72也就是21.82個像素來顯示(實際會四舍五入為22px)。
現在你知道DPI的意義了。但是,對這個屬性值的設置卻並非像前面描述的那樣直截了當。下面一個一個的來說明。
先說Fontconfig的默認值"75"吧,這是一個非常不合理的值,目前大多數顯示器的實際DPI都比這個值要大,所以我們不能采用。
再說說真實值吧,對於我的顯示器來說就是"98.2",這是一個理論上最正確的值,因為它能保證100%精確還原字符的真實大小,如果你對精確還原字符的真實大小很介意(例如經常需要打印預覽),那么真實值就是你的不二之選。
再說說Windows的默認值"96"吧,這是一個泛濫成災的設置,也比"75"更接近主流顯示器的實際DPI。正是因為它的泛濫成災,也在某種程度上成為了事實上的標准。如果你希望同磅值下,顯示的字體像素數量"和Windows一樣"或者"隨大流"、"和大家一樣",那么可以使用這個值。但是就別指望100%精確還原字符的真實大小了。呵呵,你看到例子中的值,就知道筆者是個"隨大流"的人了,因為98.2和96還是很接近的。
再說說那些"144"甚至"192"這樣明顯偏大的值吧,這些值是為視力不佳的用戶准備的。因為對於同一個顯示屏而言,磅值相同的情況下,DPI越大,顯示的一個字符需要使用到的像素就越多。所以如果你希望刻意放大字符,可以考慮增大DPI的值。
特別需要提醒的是,這里設置的DPI值,必須要和"xorg.conf"的設置保持一致。具體說來就是"DisplaySize"的值不能簡單的填寫顯示器的實際尺寸(除非你使用了DPI的真實值),而要通過如下公式進行設置:"DisplaySize 水平像素數x25.4/DPI 垂直像素數x25.4/DPI" 。
最后再澄清一個流傳甚廣的說法:"DPI的值必須是6甚至12的倍數"。這個說法的本意,是為了照顧點陣字體的顯示效果,既然本文完全使用矢量字體,而且未來的趨勢也將是矢量字體一統天下,你就忘記它吧。
<match> <!-- 確保弱綁定西文字體優先於弱綁定中文字體 --> <edit name="lang"><string>en</string></edit> </match>
對於弱綁定"family"來說,其匹配優先級低於"lang",這就會導致當"lang=zh-cn"的時候(例如瀏覽中文網頁),弱綁定中文字體的優先級高於弱綁定西文字體,而這是我們所不願看到的。因此強制將"lang"屬性設為"en"可以確保西文字體優先於中文字體,從而確保對中文字體中丑陋的西文部分的替換。
<match> <!-- 設置等寬標記 --> <edit name="isDengKuan"><eq><name>family</name><string>Monospace</string></eq></edit> </match>
這是個無中生有的標記,用於標記首選字體是否為等寬字體。當"family"列表的第一項是"Monospace"的時候,其值為"true",否則,其值為"false"。經過前面針對火狐瀏覽器的5個連續剔除列表頭部不可識別字體的動作之后,至少在99%的情況下,"family"列表頭部的不可識別字體都被剔除干凈了。這樣就可以保證對等寬識別的正確率至少有99%。至於這個標記的用途,繼續往后看就知道了。
渲染階段
渲染階段的核心目標是:讓字體中的每一個字符,都以其最佳效果在屏幕上顯示出來。
字體渲染三板斧
改善矢量字體的顯示效果,最重要的是下面三種技術:
- 抗鋸齒(antialias)
- 微調(hinting)
- 亞像素渲染[僅適用於LCD顯示屏]
抗鋸齒(antialias)是一個改善字體顯示效果的利器。抗鋸齒算法不是本文的重點,想了解詳細信息可以google之。站在使用者的立場,我們只需要知道,開啟它可以大幅度的改善字體顯示效果,並且沒有什么不良影響。甚至在蘋果的 Mac OS X 和 iOS 上,已經拋棄了字體微調技術(hinting),而完全依賴於抗鋸齒技術來改善字體的顯示效果。
微調(hinting)分為兩種:內嵌微調與自動微調。內嵌微調是字體設計者耗費大量的時間和精力、精心制作的、內嵌在字體文件中的額外指令,本質上是人工微調;而自動微調(autohint)是FreeType內嵌的一套微調算法,通用於所有矢量字體,本質上是機器微調。一般說來,內嵌微調比自動微調的顯示效果更佳。與微調相關的屬性有三個:
- hinting
- 微調功能的總開關,一旦關閉便徹底禁用微調(包括內嵌微調與自動微調)。
- autohint
- 是否優先使用自動微調。設為"true"表示只使用自動微調,不使用內嵌微調;設為"false"表示優先使用內嵌微調,但對於沒有內嵌微調的字體仍會使用自動微調。
- hintstyle
- 微調的程度(同時作用於內嵌微調與自動微調):(1)"hintnone"表示禁用微調(包括自動微調與內嵌微調),通常用於字號非常小的場合;(2)"hintslight"表示優先保持字符的形態,但是可能會降低筆畫的銳利度,通常更適合於自動微調以及小字號下的內嵌微調;(3)"hintmedium"表示在字符形態與筆畫銳利度之間進行折中,但實際效果通常相當於"hintfull";(4)"hintfull"表示優先提高筆畫的銳利度,但是可能破壞字符的形態,通常更適合於內嵌微調;[注意]這里對微調風格的解釋僅是一個提示,切勿教條化,對於特定的字體、特定的字號,哪種微調風格的效果最佳,最可靠的途徑是通過自己的眼睛去親自查看與對比。此外,還由於每個人的口味不同,風格有所偏向,特別是對於"hintslight"與"hintfull",不同的人可能會有相反的喜好。
亞像素渲染是一個針對LCD顯示屏的技術(切勿用於CRT顯示屏),與微軟的ClearType技術同屬一類。其基本原理是,將顯示器的R,G,B各個次像素也分別進行控制,讓其進行微妙的調整,相當於提升了分辨率,從而顯示出更細膩平滑的筆畫。與亞像素渲染相關的屬性有兩個:
- rgba
- LCD子像素的排列順序,不同的LCD排列順序未必相同,可能的取值如下:(1)"unknown"表示未知;(2)橫向(水平)"Red Green Blue"順序,這是最常見的排列順序;(3)橫向(水平)"Blue Green Red"順序;(4)縱向(垂直)"Red Green Blue"順序,例如把顯示器垂直放置的時候;(5)縱向(垂直)"Blue Green Red"順序;(6)"none"無子像素(例如傳統的CRT顯示器),其實就是關閉亞像素渲染。
- lcdfilter
- LCD filter 的風格:(1)"lcdnone"表示徹底關閉 LCD filter,不推薦,因為它會導致筆畫邊緣出現彩色邊紋;(2)"lcddefault"表示最大限度的消除彩色邊紋,但是可能會增加筆畫的模糊程度。多數場合這是最佳選擇;(3)"lcdlight"表示減輕筆畫的模糊程度,但不能最大限度的消除彩色邊紋。少數場合也許效果更好;(4)"lcdlegacy"是為了與傳統的"libXft color filter"兼容而設置,未來會被刪除;
設置默認的渲染參數
<!-- 第一步,設置默認的渲染參數 --> <match target="font"> <!-- 修整像素大小(小於10px的調整到10px,否則四舍五入到整數) --> <edit name="pixelsize"> <if> <less><name>pixelsize</name><double>10</double></less> <int>10</int> <round><name>pixelsize</name></round> </if> </edit> <!-- 開啟抗鋸齒(smooth) --> <edit name="antialias"><bool>true</bool></edit> <!-- 優先使用內嵌微調,同時默認開足微調 --> <edit name="hinting"><bool>true</bool></edit> <edit name="autohint"><bool>false</bool></edit> <!-- 依個人喜好,你也可能喜歡默認"hintslight"(此時可將下面的"第七步"全部注釋掉) --> <edit name="hintstyle"><const>hintfull</const></edit> <!-- LCD特征設置 --> <edit name="rgba"><const>rgb</const></edit> <edit name="lcdfilter"><const>lcddefault</const></edit> <!-- 禁用內嵌點陣 --> <edit name="embeddedbitmap"><bool>false</bool></edit> <!-- 禁用合成粗體 --> <edit name="embolden"><bool>false</bool></edit> </match>
修整像素大小的指令很簡單,主要是將像素值四舍五入到整數,同時確保最低顯示10px大小的字符。因為對於漢字來說,10px基本是極限,再小就幾乎沒法閱讀了。另外,將像素值四舍五入到整數也是為后面進一步修正像素大小做准備。
對於抗鋸齒、微調、LCD亞像素渲染,前面"字體渲染三板斧"已有詳細解說,這里不再贅述。
禁用內嵌點陣也非常明了。例如Windows中的"宋體"就內嵌了很多點陣,我們的策略既然是使用純矢量,自然應該關閉它,以保持一致性。
至於禁用合成粗體,其實這個屬性的默認值就是"false",這里寫出來主要是為了進一步明確這個默認值。
接下來的默認動作是為沒有原生斜體/粗體的字體使用合成斜體/粗體:
<!-- 第二步,為沒有原生斜體的字體使用合成斜體 --> <match target="font"> <test name="slant" compare="eq"><const>roman</const></test> <test name="slant" compare="not_eq" target="pattern"><const>roman</const></test> <edit name="slant"><const>oblique</const></edit> <edit name="matrix"> <times> <name>matrix</name> <matrix> <double>1</double><double>0.2</double> <double>0</double><double>1</double> </matrix> </times> </edit> </match> <!-- 第三步,為沒有原生粗體的字體使用合成粗體 --> <match target="font"> <test name="weight" compare="less"><int>105</int></test> <test name="weight" compare="more" target="pattern"><int>105</int></test> <edit name="weight"><const>bold</const></edit> <edit name="embolden"><bool>true</bool></edit> </match>
上述配置本身簡單易懂,這里想詳細說說的是合成粗體的工作原理,因為后面進一步修正像素大小的時候,如果預先知道合成粗體的工作原理,會更容易理解。
所謂"合成粗體",是指在常規體的基礎上,通過算法生成的粗體,這是一種模擬出來的粗體,而不是原生的粗體。具體算法如下:(1)當標稱大小為11px或更小時,通過就地加濃筆畫來模擬粗體,因此顯示出來的字符的視覺大小就是其標稱的大小,例如,標稱大小為10px的合成粗體就正好占用10px的屏幕空間。(2)當標稱大小為12-35px時,通過在水平和垂直方向各平移一像素並重繪一次來模擬粗體,因此顯示出來的合成粗體會比其標稱大小大一個像素,例如標稱大小為16px的合成粗體,其實際的視覺大小是17px。(3)當標稱大小為36-59px時,通過在水平和垂直方向各平移2像素並重繪兩次來模擬粗體,因此實際大小會比標稱大小大2個像素,例如標稱大小為52px的合成粗體,其實際的視覺大小是54px。(4)如果字號更大,合成粗體的平移量還會更大。例如:60-83px,平移3像素;84-107px,平移4像素……。換句話說,平移的像素值可以通過如下公式進行計算:平移像素值=trunc((視覺大小+13.5)/25),其中trunc函數的作用是去尾取整。
進一步修正像素大小
通過上面對合成粗體的講解,我引入了兩個概念:"標稱大小"與"視覺大小",這里進一步明確一下兩者的含義。所謂"標稱大小"是指"pixelsize"屬性的值,而"視覺大小"是指顯示在屏幕上實際大小。對於合成粗體與等寬西文來說,兩者有可能不等,但除此之外的其他情況,兩者總是相等的。對於合成粗體,兩者的差異上面已經講過,這里不再贅述。對於帶有原生粗體的等寬西文(Monospace)而言,由於它的每個西文字符寬度都嚴格等於半個中文字符寬度,所以當"標稱大小"為奇像素的時候(例如17px),由於無法顯示半像素字符(8.5px),只能略偏大顯示(9px)。因此對於等寬西文(Monospace)而言,偶像素下,"標稱大小"與"視覺大小"相同,但在奇像素下,"視覺大小"就要比"標稱大小"大一個像素。
<!-- 第四步,標記"視覺大小"(原本的標稱值)是否為奇數,為接下來修正等寬條件下的"標稱大小"做准備 --> <match target="font"> <edit name="isOddPx"> <eq> <round><divide><plus><name>pixelsize</name><double>0.5</double></plus><double>2</double></divide></round> <ceil><divide><plus><name>pixelsize</name><double>0.5</double></plus><double>2</double></divide></ceil> </eq> </edit> </match> <!-- 第五步,修正合成粗體的"標稱大小",盡力確保其"視覺大小"與原本的標稱值一致 --> <match target="font"> <test name="embolden"><bool>true</bool></test> <!-- 標稱大小=視覺大小-trunc((視覺大小+13.5)/25) --> <edit name="pixelsize"> <minus> <name>pixelsize</name> <trunc><divide><plus><name>pixelsize</name><double>13.5</double></plus><double>25</double></divide></trunc> </minus> </edit> </match> <!-- 第六步,在等寬條件下,為確保中西文對齊,進一步修正"標稱大小"(也會影響"視覺大小") --> <match target="font"> <test name="isDengKuan"><bool>true</bool></test> <!-- 如果"視覺大小"是奇數 --> <test name="isOddPx"><bool>true</bool></test> <!-- 那么上調為偶像素,因為Monospace在奇像素下總是大一級顯示 --> <edit name="pixelsize"><plus><name>pixelsize</name><int>1</int></plus></edit> </match> <!-- 第六步續,進一步專門處理等寬條件下"標稱大小"為11px,12px的合成粗體 --> <match target="font"> <test name="isDengKuan"><bool>true</bool></test> <test name="embolden"><bool>true</bool></test> <test name="pixelsize" compare="more"><double>10.5</double></test> <test name="pixelsize" compare="less"><double>12.5</double></test> <!-- 統一調整為12px常規體,只有這樣才能對齊 --> <edit name="pixelsize"><int>12</int></edit> <edit name="embolden"><bool>false</bool></edit> <edit name="weight"><int>80</int></edit> </match>
上述配置中的最后一個段落,專門處理等寬條件下標稱大小為11px,12px的合成粗體。因為11px,12px是個特例,在粗體條件下無法保持中西文對齊,只能調整為12px常規體,才能做到中西文對齊。
針對單個字體的調整
<!-- 第七步,針對每個字體單獨調整渲染參數 --> <match target="font"> <test name="family"><string>Monospace</string></test> <edit name="hintstyle"><const>hintslight</const></edit> </match> <match target="font"> <test name="family"><string>Sans</string></test> <edit name="hintstyle"> <if> <or> <eq><name>pixelsize</name><int>10</int></eq> <eq><name>pixelsize</name><int>12</int></eq> </or> <const>hintslight</const> <const>hintfull</const> </if> </edit> </match> <match target="font"> <test name="family"><string>Serif</string></test> <test name="pixelsize"><int>10</int></test> <test name="slant"><int>0</int></test> <edit name="hintstyle"><const>hintslight</const></edit> </match> <match target="font"> <test name="family"><string>zhHei</string></test> <edit name="hintstyle"><const>hintslight</const></edit> </match> <match target="font"> <test name="postscriptname" compare="contains"><string>NotoSansKR</string></test> <edit name="hintstyle"><const>hintslight</const></edit> </match>
這里的調整只涉及到了微調風格。至於在不同大小、不同粗細、不同風格下,使用什么樣的渲染參數效果最好,就只能靠自己的眼睛了。雖然可以使用FontForge查看字體的屬性,獲取相關信息,但是筆者依然推薦用自己的眼睛去檢查更可靠。
刪除多余的標記
<!-- 最后,刪除等寬標記與奇偶標記 --> <match target="font"> <edit name="isDengKuan" mode="delete"></edit> <edit name="isOddPx" mode="delete"></edit> </match>