HowtoCustomFontswithFontconfig
出自Ubuntu 正體中文 Wiki
目錄 |
前言
Fontconfig 是個強大的函式庫,可以讓使用者自行設定所需字型的使用法則。
- 如果您對本篇內容有任何疑問或建議,請與zerng07聯絡
Fontconfig
Fontconfig 是一個函式庫,提供一套字型比對的機制,使得運用 Fontconfig 的應用程式能得到所需的字體樣式。應用程式本身可以利用 Fontconfig 所得到的字型來畫字,也可以架構在自己原先的字型選擇架構上,以達到對舊型設定的一定相容性。
功能概述
Fontconfig 由兩個主要的模組構成,其一是設定模組,把XML設定檔轉換成 Fontconfig 的內部設定;另一為比對模組,將應用程式傳來的字型樣式需求與現有字型比對,傳回最相似的字型。
Fontconfig 設定檔的目的,即是儘量不更動字型設定,並且讓各種應用程式共用一個設定。這樣一來當程式之間需要交換字型名稱時,所取得的字型較為一致。若字型設定能集中管理,字型的安裝和個人化就會較簡易而且有秩序。
設定檔
如果你已經裝了 fontconfig,那麼它應該已經附上了預設的設定檔,位於 /etc/fonts/ (一些 Linux distributions) 或 /usr/X11R6/etc/fonts/ (一些 BSD flavors) 的 fonts.conf。
由於 /etc/fonts/fonts.conf 是 X window 的預設設定,系統更新時,可能會將您所設定過的檔案覆蓋掉,強烈建議不直接更改。系統全域設定建議寫於 /etc/fonts/conf.d ,個人設定則寫在 ~/.fonts 資料夾內,並自訂名稱,像是10-myfonts.conf(可以參考原本已位於此資料夾的檔案),前面是個二位數(00-99),表示設定配置檔時的優先順序,越小優先度越高。
設定檔可以參考示範設定。
fontconfig 的設定檔儲存格式為 xml,這種格式可以使玩家們自由編輯。其內容包含兩個重要的元素(element),test 與 edit,存放在 match 元素中。(請見教學)
- 走馬看花:
match target="pattern"
test qual ="any" name="屬性" compare="eq"
edit name ="屬性" mode="assign" binding="weak"
重要的字型性質與其型態
性質 型態 family string style string (值包括 slant, weight) slant int (值包括 italic, oblique, roman) weight int (值包括 light, medium, demibold, bold, black) size double pixelsize double antialias bool autohint bool charset charset lang string
- 如需進一步說明或是想查字型性質與其型態,請見fonts-conf http://edt1023.sayya.org/fontconfig/fontconfig-user.html
重要名詞介紹
Hinting
當向量字型在縮放時,如果其中一筆畫的線,剛好位在兩個螢幕像素中間,那麼應該要放在左邊的格子呢?還是右邊的格子?如果這時選錯了,常會使字體變得歪七扭八或變形,所以這時如果有人能告訴它,比較正確的位置在哪裡,那麼一來,此向量字型就會變得好看許多,而這些資訊,我們稱之為—Hinting,但是有良好 Hinting 的字型卻不多。
Freetype 有 autohint 的功能,可以自動為沒有 hinting 的字型做出 hinting,但是對於筆劃複雜的文字(如中文),卻常會有反效果。
Anti-alias
防鋸齒,即是將字型先以數倍的大小來繪製,然後再縮成想要的大小,其中不滿一格的格子點用灰階補上。但是因為中文字筆劃多,小字時若補上灰階,常會使整個字看起來糊糊的(因為大部分的地方都成了灰階),這就是為什麼我們要關閉小字的防鋸齒了。
雖然把有防鋸齒的小英文字,放在無防鋸齒的中文字間,會看起來刺眼,但是英文字不開防鋸齒看起來很不舒服,所以預設打開。
Subpixel Rendering
液晶螢幕的畫面,是由許多長方形小像素構成的,它的排列通常是 紅、綠、藍,也就是說,如果液晶螢幕的水平解析度是 1024 個像素的話,就有 1024 x 3 = 3072 個點,而這些點是由 rgbrgbrgb... 依序排列的。
以白底黑字為例,如果需要滿格的像素,rgb 三格就需是全關 (0,0,0);如果只是右邊三分之二部份, 就關掉 g 和 b, 留下最左邊的 r 開著。理論上,這樣就有原來三倍的水平像素能夠使用,可以大幅增加液晶螢幕的解析度。但由於只開著紅色或黃色或其他顏色,會有很明顯的光暈,所以一般都採用 filtering 的方式,把一個次像素的值往左右兩格分散(因為無論對哪一格次像素來說,它的左右兩格的顏色和本身都是不同的,所以往左右兩格分散可以均勻影響亮度),成為 1/3, 1/3, 1/3 分佈 ;但這樣的壞處是會顯得太模糊了一點,於是再多一層,把原先三格分成 5 格, 但權重改為 1/9 2/9 3/9 2/9 1/9。3/9 那一格就是原本的次像素,而鄰近的格子 就用這樣的方法分散後和原來該次像素格子的光度值相加,達到像素往中央集中, 卻又不太模糊的效果。
Fontconfig 的 rgba 選項,即是設定液晶螢幕次像素的排列方式,一般都是 rgb,而 v 開頭的表示三種顏色是縱向排列。
- 以上擷取自 http://fractal.csie.org/~eric/wiki/Fontconfig -EricCheng
Serif
Serif 中文譯為「有襯線字體」,襯線即是印刷字體在每個筆劃起始與終止處,加上短線或三角突起等,以便於快速辨認字元,利於閱讀,為印刷專用字體。舊版 Windows 與較舊的 Linux 發行版以此為預設顯示字體,而英文新版則改為 Sans-Serif,中文新版則是:當字體大於某一程度時,則將 Serif 的明體或宋體,以 Sans 的黑體取代。
Serif 字體著名的有:Times New Roman、DejaVu Serif、宋體、明體。
Sans-Serif
Sans-Serif 中文譯為「無襯線字體」,專用於螢幕、簡報、藝術字體、展示等,較美觀,但不適於長時間閱讀。多數英文語系的作業系統多以此為預設字體,而採用此字體為預設字體的中文作業系統,以 Apple Macintosh OS X 最為著名。
Sans-Serif 字體著名的有:Arial、DejaVu Sans、Helvetica、Verdana、楷體、圓體、黑體、ubuntu logo 體。
Monospace
Mono 意思是「單一的」,space 意思是「空間」,中文翻為「等寬字體」。等寬字是打字機時代下的遺產,每個英文字母皆設計為同一寬度,以便於排版;現代為節省不必要空間的浪費,依字母形狀分配其寬度,如 m 與 i 其寬度便不相同。Monospace 現多用於終端機顯示、程式碼表示等。
Monospace 字體著名的有:Andale Mono、DejaVu Sans Mono、Courier、AR PL New Sung Mono。
字型比對
當 fontconfig 接收到字型的樣式需求時,Fontconfig會將它與電腦現有的字型逐一比對,比對其間的差距。然後從結果中選出最接近的字型。雖然一定會傳回一個字型,但不保證傳回的字型和需求的樣式有多麼相符。
教學
xml基礎
首先,你的文件開頭,一定要有
<?xml version="1.0"?> <!DOCTYPE fontconfig SYSTEM "fonts.dtd">
來表明你的檔案身份。
再來,你得用<fontconfig>與</fontconfig>這對元素把其他元素夾在裏面,這種一層夾一層的樹枝狀結構是 xml 檔一大特色之一。另一特色即是每個元素皆以小於及大於符號括住,而且後面的那個需要加上倒斜線 /,來表示結束。寫作時,最好進行縮排,較能輕鬆解讀,也較不會漏掉任何一對由小於及大於符號括住的元素。
(等待擴充內容......)
內容寫作指導
加入字體所在路徑
避免 fontconfig 進行比對時找不到你所指定的字體,這裡列的是一般人會放字體的地方。
<dir>/usr/share/fonts</dir> <dir>/usr/share/fonts/local</dir> <dir>/usr/local/share/fonts</dir> <dir>~/.fonts</dir> <!--加入點陣字體路徑--> <dir>/usr/X11R6/lib/X11/fonts</dir>
<match>與<edit>用法
我現在來簡單地解釋範例中的寫法(下面可以看得到縮排用法)
<!--所有字型預設樣式--> <match target="font"> <edit name="antialias" mode="assign"> <bool>true</bool> </edit> <edit name="hinting" mode="assign"> <bool>false</bool> </edit> <edit name="autohint" mode="assign"> <bool>false</bool> </edit> </match>
第一行,是註解,由驚嘆號與兩個減號開頭,再加上兩個減號表示結束。注意!不同於其他元素,它不是一對的。fontconfig 會將這裡面包含的東西忽略。
一開始的<match target="font">即是告訴 fontconfig 說,我現在要比對的目標,是字體。<match>元素下一行接的是<edit>元素,用來更改比對到的字體的值;其中的 mode 值是 assign ,意思是:"指定模式"以取代原本的值。
簡單的說,這一段主要是告訴 fontconfig,我要比對所有的字體,不特別挑任何一個(要挑選的話,得加上<test>元素,下面可以看到用法),把所有字體的 antialias (防鋸齒)值改成 true ,hinting 值改成 false, autohint 值改成 false。所以可以看的出來,這是對所有字體設定預設的樣式。
接下來,我們要看看<test>元素的用法。
<test>用法
同樣的,我拿下面範例設定來講解。
<!--打開中文粗體--> <match target="font" > <test name="family" compare="contains" > <string>Song</string> <string>Sun</string> <string>Kai</string> <string>Ming</string> </test> <test compare="more_eq" target="pattern" name="weight" > <int>180</int> </test> <edit mode="assign" name="embolden" > <bool>true</bool> </edit> </match>
當然,首先我們還是得說:「我現在要比對的目標是字體。<match target="font" >」。接下來,我們要把對字體作任何修改的想法寫在<test>元素中。其中的 name,就是性質名稱,像 weight, family 等。compare 則是拿來比較用的,可以比較任何可以比的東西(這不是廢話嘛?),像是數值大小,或是像這裡的範例一樣,比較是否有相同的字串等。
了解了這些以後,我們就可以用很兇的口氣(因為這是 fontconfig 的工作)對 fontconfig 說:「fontconfig!給我找出字型名稱中,含有Song(宋), Sun(宋), Kai(楷), Ming(明)這些字串的字體來。<test name="family" compare="contains" > <string>Song</string> <string>Sun</string> <string>Kai</string> <string>Ming</string> </test>」一般來說,中文字體名稱都含有這些字串,像文鼎新宋、文鼎上海宋、文鼎正楷、標楷體、細明體等。
找出這些字後,我們得再找出符合粗體的條件,很明顯的,我們還是得要求 fontconfig 比較粗體的值(要不然你要怎麼找出誰是粗體?)。這裡有件很重要的事情要做,就是─要記好應該包住這個值的元素,<int>元素(這裡所說的元素也就是重要的字型性質與其型態裡的型態)。接下來,我們就說:「再來,fontconfig,我要比較字體樣版(pattern)中的粗細(weight),找出粗細值大於等於180的字型。<test compare="more_eq" target="pattern" name="weight" > <int>180</int> </test>」
最終的一步,也就是把我們所比對到的字體的值改掉。那麼要用什麼元素呢?就是<edit>啦!當然,我們要修改的值,只有允許粗體的 true 或取消粗體的 false,這裡選用的 mode 還是 assign。接下來,你應該想到一件很重要的事了。那就是,上面說過要注意包住這個值的元素啊,你還記得嗎?而這個元素是<bool>,不清楚請查表。再寫下對應的</edit>後就大功告成了,但是別忘了</match>喔(開頭結尾必須是一對的,還記得吧!)所以就像這樣:<edit mode="assign" name="embolden" > <bool>true</bool> </edit> </match>
- 有些時候修改的效果沒有顯現,可能是設置了相衝突的條件,例如:一開始限定了某字體大小於等於16,又說某字體等於17時打開防鋸齒,那麼,你將永遠看不到防鋸齒效果的出現。
<alias>用法
alias 元素主要功能是,為某個字體提供一個替代字體列表,越上面越優先使用,請看範例是怎麼使用的。
<!--適應中文用戶的用字習慣--> <alias> <family>serif</family> <prefer> <family>DejaVu Serif</family> <family>Bitstream Vera Serif</family> <family>Times New Roman</family> <family>Thorndale AMT</family> <family>Luxi Serif</family> <family>Nimbus Roman No9 L</family> <family>Times</family> <family>Frank Ruehl</family> <family>MgOpen Canonica</family> <family>Norasi</family> <family>Kinnari</family> <family>AR PL New Sung</family> <family>AR PL ShanHeiSun Uni</family> <family>SimSun</family> <family>MingLiu</family> <family>Kochi Mincho</family> <family>UnBatang</family> <family>Baekmuk Batang</family> </prefer> </alias>
在 alias 元素內的是 family 以及 prefer 這兩個元素。當然,family 就是你想要替代掉的字型名稱,這裡是 serif ,一個經常使用的字型代稱,代指無襯線字型,像 arial、楷體、圓體,這些都屬於 serif(許多網頁會指定某些字型,如 Times New Roman,而 serif, sans-serif, monospace 這三者都是網頁最後的指定字型,也就是說,當您的系統沒有它指定的字型時,才會使用它)。襯線指的是每一筆畫起始處,以及結尾處所加的小短線;襯線字多用於印刷,因為這種字體較容易閱讀。為了得到較好的視覺效果,我在 sans-serif 列表中仍用宋體、明體,當然,如果您想用楷體也行。sans-serif 是無襯線字,系統多預設此字型;monospace 是等寬字,多用於展示程式碼。
- 在 kde 環境下,更改完設定後,可以開啟 gtk2-based 程式(ex.firefox)來看看效果。
如何應用
也許有一天,你雄雄發現文鼎上海宋在顯示大字時,因為沒有內嵌點陣字,所以會有點糊糊的。又突然發現, cwTeXHeiBold 在顯示大字時,看起來還蠻不錯的,有粗體的感覺,還很像 Macintosh 的字體呢!(需要者請至此下載 http://cle.linux.org.tw/fonts/cwttf/ )
所以我們可能會這樣想,當字體大於等於18時,就把 AR PL ShanHeiSun Uni 換成 cwTeXHeiBold ,這樣看起來應該美觀多了吧!
我們可以這樣寫:
<!--選擇性使用cwTeXHeiBold--> <match target="font"> <test name="family"> <string>AR PL New Sung</string> <string>AR PL ShanHeiSun Uni</string> </test> <test name="pixelsize" compare="more_eq"> <double>18</double> </test> <edit name="family" mode="assign"> <string>cwTeXHeiBold</string> </edit> </match>
示範設定
ubuntu 8.04 的中文支援內已將此做了改進,已不需設定便有好效果了,或許了解設定格式寫法,依照自己心意設定才是最好的。
- Ubuntu 用戶:
sudo gedit /etc/fonts/conf.d/10-myfonts.conf
- Kubuntu 用戶:
kdesu kwrite /etc/fonts/conf.d/10-myfonts.conf
PS. 以 kate 或 kwrite 修改後,系統會自動產生 10-myfonts.conf~ 做為備份,但是位於此資料夾下的合格檔案(有開頭的宣告)都會被 fontconfig 承認,所以必得將他砍掉,以免效果無法顯現,或者改用其他程式修改,例:nano。
內容如下:
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<!-- conf.d/myfont.conf -->
<fontconfig>
<dir>/usr/share/fonts</dir>
<dir>/usr/share/fonts/local</dir>
<dir>/usr/local/share/fonts</dir>
<dir>~/.fonts</dir>
<!--加入點陣字體路徑-->
<dir>/usr/X11R6/lib/X11/fonts</dir>
<!--所有字型預設樣式-->
<match target="font">
<edit name="antialias" mode="assign">
<bool>true</bool>
</edit>
<edit name="hinting" mode="assign">
<bool>false</bool>
</edit>
<edit name="autohint" mode="assign">
<bool>false</bool>
</edit>
</match>
<!--打開中文粗體-->
<match target="font">
<test name="family" compare="contains">
<string>宋</string>
<string>明</string>
<string>楷</string>
<string>Song</string>
<string>Sun</string>
<string>Ming</string>
<string>Kai</string>
</test>
<test compare="more_eq" target="pattern" name="weight">
<int>180</int>
</test>
<edit mode="assign" name="embolden">
<bool>true</bool>
</edit>
</match>
<!-- 關閉小字AA -->
<match target="font">
<test name="pixelsize" compare="less">
<double>12</double>
</test>
<edit name="antialias" mode="assign">
<bool>false</bool>
</edit>
</match>
<!-- 關閉宋體、明體小字AA -->
<match target="font">
<test name="family" compare="contains">
<string>宋</string>
<string>明</string>
<string>Song</string>
<string>Sun</string>
<string>Ming</string>
</test>
<test name="pixelsize" compare="less_eq">
<double>20</double>
</test>
<edit name="antialias" mode="assign">
<bool>false</bool>
</edit>
</match>
<!-- 解決中文字體英文間距過寬 -->
<match target="font">
<test target="pattern" name="lang" compare="contains">
<string>zh-tw</string>
<string>zh-cn</string>
<string>ja</string>
<string>ko</string>
</test>
<edit name="spacing">
<const>proportional</const>
</edit>
<edit name="globaladvance">
<bool>false</bool>
</edit>
</match>
<!--設定中文最小字號-->
<match target="font">
<test name="family" compare="contains">
<string>宋</string>
<string>明</string>
<string>楷</string>
<string>Song</string>
<string>Sun</string>
<string>Ming</string>
<string>Kai</string>
</test>
<test name="pixelsize" compare="more_eq">
<double>8</double>
</test>
<test name="pixelsize" compare="less_eq">
<double>12</double>
</test>
<edit name="pixelsize" compare="eq">
<double>12</double>
</edit>
</match>
<!--適應中文用戶的用字習慣。註,這個問題似乎已不會再發生。所以以下設定也許是沒必要的。-->
<alias>
<family>serif</family>
<prefer>
<family>DejaVu Serif</family>
<family>Bitstream Vera Serif</family>
<family>Times New Roman</family>
<family>Times</family>
<family>AR PL New Sung</family>
<family>AR PL ShanHeiSun Uni</family>
<family>Kochi Mincho</family>
<family>UnBatang</family>
<family>Baekmuk Batang</family>
</prefer>
</alias>
<alias>
<family>sans-serif</family>
<prefer>
<family>DejaVu Sans</family>
<family>Bitstream Vera Sans</family>
<family>Lucida Grande</family>
<family>Helvetica</family>
<family>Arial</family>
<family>Verdana</family>
<family>AR PL New Sung</family>
<family>AR PL ShanHeiSun Uni</family>
<family>AR PL New Kai</family>
<family>AR PL ZenKai Uni</family>
<family>Kochi Gothic</family>
<family>UnDotum</family>
<family>Baekmuk Dotum</family>
</prefer>
</alias>
<alias>
<family>monospace</family>
<prefer>
<family>DejaVu Sans Mono</family>
<family>Bitstream Vera Sans Mono</family>
<family>Andale Mono</family>
<family>Courier New</family>
<family>Courier</family>
<family>AR PL New Sung Mono</family>
<family>AR PL New Sung</family>
<family>AR PL ShanHeiSun Uni</family>
<family>Kochi Gothic</family>
<family>Baekmuk Dotum</family>
</prefer>
</alias>
<alias>
<family>細明體</family>
<prefer>
<family>AR PL New Sung</family>
<family>AR PL ShanHeiSun Uni</family>
</prefer>
</alias>
<alias>
<family>新細明體</family>
<prefer>
<family>AR PL New Sung</family>
<family>AR PL ShanHeiSun Uni</family>
</prefer>
</alias>
<alias>
<family>標楷體</family>
<prefer>
<family>AR PL New Kai</family>
<family>AR PL KaitiM Big5</family>
<family>AR PL KaitiM GB</family>
<family>AR PL ZenKai Uni</family>
</prefer>
</alias>
</fontconfig>