字體配置
Fontconfig 是一個用於向應用程式提供可用的字體列表,以及字體渲染配置的庫。FreeType 庫依此配置渲染字體。Arch 上的 freetype2 字體渲染庫啟用了字節碼解釋器(bytecode interpreter,BCI)以優化字體渲染,尤其是在 LCD 屏幕上。參見#預置和字體配置/示例。
儘管大多數類 Unix 系統現在使用 Fontconfig,但部分應用程式仍在使用原始的 X Logical Font Description 作為字體選擇與顯示方法。
字體路徑[編輯 | 編輯原始碼]
為了使字體能夠被應用程式發現,必須對它們進行編目,以便快速訪問。
Fontconfig 的默認字體路徑是 /usr/share/fonts/
和 ~/.local/share/fonts
(以及過時的 ~/.fonts/
)。Fontconfig 將在這些路徑下遞歸查找字體。為了便於安裝與管理,在安裝字體時,建議使用這些路徑。
以下命令列出 Fontconfig 已知的字體文件:
$ fc-list ':' file
fc-list(1) 中有更多的輸出格式。
Xorg 已知的字體路徑可通過其日誌了解:
$ grep /fonts ~/.local/share/xorg/Xorg.0.log
- 也可使用
xset q
命令查看 Xorg 的已知字體。 - 若 Xorg 以根用戶權限運行,應查看
/var/log/Xorg.0.log
。
Xorg 不像 Fontconfig 一樣遞歸查找 /usr/local/share/fonts
。添加路徑時,必須像這樣添加絕對路徑:
Section "Files" FontPath "/usr/share/fonts/local/" EndSection
有關 Xorg 讀取配置的更多細節,請閱讀Xorg#配置。如果要為用戶單獨配置字體路徑,可以像這樣修改對應的 ~/.xinitrc
來添加或移除默認的字體路徑:
xset +fp /想要/添加的/字体/路径 # 将一个路径添加到 Xorg 的已知字体路径列表中 xset -fp /想要/移除的/字体/路径 # 将一个路径从 Xorg 的已知字体路径列表中移除
Fontconfig 配置[編輯 | 編輯原始碼]
fonts-conf(5) 中有 Fontconfig 的配置文檔。
用戶配置文件位於 $XDG_CONFIG_HOME/fontconfig/fonts.conf
中(通常是 $HOME/.config/fontconfig/fonts.conf
)。全局配置文件位於 /etc/fonts/local.conf
。
用戶配置優先級高於全局配置。兩個文件使用相同的語法。
- 需要啟用
50-user.conf
預設才能讓用戶配置生效,啟用51-local.conf
預設才能讓全局配置生效。閱讀#預設一節了解如何啟用這些預設。 ~/.fonts.conf/
、~/.fonts.conf.d/
和~/.fontconfig/*.cache-*
已過時,以後的包將不再讀取這些路徑和文件。對應的新路徑分別是$XDG_CONFIG_HOME/fontconfig/fonts.conf
、$XDG_CONFIG_HOME/fontconfig/conf.d/NN-name.conf
和$XDG_CACHE_HOME/fontconfig/*.cache-*
。如果使用第二個路徑,確保文件命名正確(NN
是兩位數,如00
、10
和99
。
Fontconfig 把所有配置集中到一個單獨的中心文件(/etc/fonts/fonts.conf
)中。Fontconfig 升級時會替換這個文件,因此不應當直接修改它。支持 Fontconfig 的程序查看這個文件以獲取可用的字體及如何渲染之;重啟這類程序即可載入新的配置。該文件是全局配置(/etc/fonts/local.conf
)、預設配置(/etc/fonts/conf.d/
)、用戶配置($XDG_CONFIG_HOME/fontconfig/fonts.conf
)的組合。使用 fc-cache
命令重建 Fontconfig 的配置,但只有新運行的程序會使用新的配置。
某些桌面環境(如 GNOME 和 KDE)的字體設置界面會自動創建或覆蓋用戶的字體配置文件。對於此類桌面環境,最好讓設置界面中的字體設置和配置文件相符合。同時請確定桌面的區域設置或 locale 受配置好的字體支持,否則字體配置可能被覆蓋。
Fontconfig 配置文件使用 XML 格式,其需要的頭部如下:
<?xml version="1.0"?> <!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd"> <fontconfig> <!-- settings go here --> </fontconfig>
文中的配置示例省略了這些標籤。
預設[編輯 | 編輯原始碼]
預設存放在 /usr/share/fontconfig/conf.avail
。可以通過創建符號連結到此處來啟用,無論是單用戶配置還是全局配置。這些預設會覆蓋各自配置文件中的對應設置。
例如,以下命令啟用全局次像素 RGB 渲染:
$ cd /etc/fonts/conf.d # ln -s /usr/share/fontconfig/conf.avail/10-sub-pixel-rgb.conf
以下命令啟用用戶級次像素 RGB 渲染:
$ mkdir $XDG_CONFIG_HOME/fontconfig/conf.d $ ln -s /usr/share/fontconfig/conf.avail/10-sub-pixel-rgb.conf $XDG_CONFIG_HOME/fontconfig/conf.d
抗鋸齒(Anti aliasing)[編輯 | 編輯原始碼]
字體光柵化將字體從向量數據(比如一個TrueType字體)轉換為光柵或者位圖數據。由於混疊現象,轉換後的字體可能會出現鋸齒狀邊緣。抗鋸齒技術可以使邊緣看起來更平滑。
Fontconfig默認啟用抗鋸齒,如要禁用:
<match target="font"> <edit name="antialias" mode="assign"> <bool>false</bool> </edit> </match>
字體微調(hinting)[編輯 | 編輯原始碼]
字體微調使用數學指令來調整輪廓字體的顯示,使其與光柵化網格(如顯示器上的像素網格)對齊。它的預期效果是使字體看起來更清晰,從而使它們更容易閱讀。當顯示器擁有 300 左右的 DPI 時,字體即使不經微調也能正確排列。
字節碼解釋器(BCI)[編輯 | 編輯原始碼]
TrueType 字體的微調指令由 FreeType 的解釋器使用 BCI 微調渲染。通常來說,微調指令完備的字體使用 BCI 微調效果很好。
微調是默認啟用的,如要禁用:
<match target="font"> <edit name="hinting" mode="assign"> <bool>false</bool> </edit> </match>
/etc/profile.d/freetype2.sh
中修改,通過傳遞參數 truetype:interpreter-version=NN
設置解釋器。NN 對應所選擇的版本,傳遞給腳本中的 FREETYPE_PROPERTIES
變量。一些流行的選項如下:
- 35 - 經典模式,模擬 Windows 98
- 36 - 經典 Windows ClearType 模式,Windows XP 以下的 Windows 使用
- 38 - 「無窮」模式,高定製性,被認為性能較低,已不再開發
- 40 - 最小模式(精簡版的無窮模式,默認值)
自動微調(autohint)[編輯 | 編輯原始碼]
自動微調依自己的算法嘗試微調,無視字體內所有的微調指令。以前這是默認選項,因為 TrueType2 字體受專利保護,但現在專利已過期,基本不需要使用它。如果字體的微調指令很少或沒有,它的效果會更好,否則效果是不如 BCI 的。常見字體都有完備的微調指令,因此自動微調用處不大,現在是默認關閉的。如要啟用:
<match target="font"> <edit name="autohint" mode="assign"> <bool>true</bool> </edit> </match>
微調風格(hint style)[編輯 | 編輯原始碼]
微調風格是指對字體進行調整顯示、使其與光柵化網格對齊的調整量。支持的值有 hintnone
、hintslight
、hintmedium
和 hintfull
,微調程度依次加深,即字形變得更扭曲、更清晰——hintslight
會使字體更模糊,無法與網格對齊,但在保留字體形狀方面會更好(參見 [2]。),而 hintfull
會使字體更清晰,能很好地與像素網格對齊,但會讓字體嚴重變形。對於非 CFF(.otf)字體,hintslight
設置會在豎直方向上隱式使用自動微調,以支持這類字體的原生字體信息。
默認選項是 hintslight
,如要更改:
<match target="font"> <edit name="hintstyle" mode="assign"> <const>hintnone</const> </edit> </match>
像素排布(RGBA)[編輯 | 編輯原始碼]
大多數顯示器使用 RGB 方式排列像素,但也有例外。Fontconfig 需要知道顯示器類型才能正確顯示字體。這個選項的值有四個:RGB、BGR、V-RGB(縱向 RGB 排列)或 V-BGR。如果你的顯示器旋轉使用,可修改這個值。如果找不到相應的資料,這個網站可協助測試。
<match target="font"> <edit name="rgba" mode="assign"> <const>rgb</const> </edit> </match>
次像素渲染[編輯 | 編輯原始碼]
次像素渲染(英文維基百科頁面)通過單獨控制一個像素的三個分色,在一個方向上獲得三倍解像度,以使得字體看看起來更銳利。在 Windows 上,這項技術叫做 zhwp:ClearType。
FreeType2 提供兩種次像素渲染方式(FT_CONFIG_OPTION_SUBPIXEL_RENDERING
),Harmony 和 ClearType [3]。
若使用 ClearType 次像素渲染,建議啟用 LCD 濾鏡(見下)。使用 Harmony 次像素渲染則不需要。
從 FreeType 2.10.3 起,Arch 默認啟用 ClearType 次像素渲染。[4]
lcdlight
LCD 濾鏡以獲得 FreeType 2.10.3 以前的 Harmony 次像素渲染行為(而不是 ClearType)。LCD 濾鏡(LCD filter)[編輯 | 編輯原始碼]
LCD 濾鏡是用來減輕 ClearType 次像素渲染的色邊現象的。這是 FreeType 2 API 文檔對其的描述,其中 FT_LcdFilter 一節解釋了各個選項。這個網頁展示了各個 LCD 濾鏡的測試效果。
大多數用戶可使用 lcddefault
。其他選項包括:適合太粗或模糊的字體使用的濾鏡 lcdlight
、原始的 Cairo 濾鏡 lcdlegacy
、完全關閉 LCD 濾鏡的選項 lcdnone
。
<match target="font"> <edit name="lcdfilter" mode="assign"> <const>lcddefault</const> </edit> </match>
高級 LCD 濾鏡選項[編輯 | 編輯原始碼]
如果對內置的 LCD 過濾器不滿意,可以通過構建一個自定義的 freetype2 軟件包並修改硬編碼的過濾器的方式,來非常具體地調整字體的渲染。Arch 構建系統可用於從原始碼構建和安裝軟件包。
查看 freetype2包 的 PKGBUILD 並下載/解壓構建文件。Arch 構建系統#通過 Git 獲取 PKGBUILD 源碼列出了一些方法。假設使用 asp:
$ asp checkout freetype2 $ cd freetype2/trunk $ makepkg --nobuild
編輯文件 src/freetype-VERSION/include/freetype/config/ftoption.h
並取消對 FT_CONFIG_OPTION_SUBPIXEL_RENDERING
宏的註釋,啟用 ClearType 次像素渲染。
然後,編輯文件 src/freetype-VERSION/src/base/ftlcdfil.c
並查找常量 default_filter[5]
的定義:
static const FT_Byte default_filter[5] = { 0x10, 0x40, 0x70, 0x40, 0x10 };
這個常量定義了一個應用於渲染的字形的低通濾波器。根據需要對其進行修改。(參考 freetype 郵件列表的討論)
最後,保存文件,構建並安裝自定義軟件包:
$ makepkg --noextract # pacman --remove --nodeps freetype2 # pacman --upgrade freetype2-VERSION-ARCH.pkg.tar.xz
重啟系統或窗口系統。現在,lcddefault 過濾器應該會以不同方式渲染字體。
某些字體/字形的單獨設置[編輯 | 編輯原始碼]
自動微調使用複雜而巧妙的方法進行字體渲染,但它常常使粗體字變得太寬。幸運的是,可以關閉粗體字的自動微調,而對其他字形則保留它:
... <match target="font"> <test name="weight" compare="more"> <const>medium</const> </test> <edit name="autohint" mode="assign"> <bool>false</bool> </edit> </match> ...
一些字體也許在 BCI 自動微調下外觀不佳。可以為這些字體禁用微調:
... <match target="font"> <test name="family" qual="any"> <string>My Font</string> </test> <edit name="hinting" mode="assign"> <bool>false</bool> </edit> </match> ...
設置默認和後備字體[編輯 | 編輯原始碼]
匹配測試[編輯 | 編輯原始碼]
設置默認或後備字體的一個可靠方法是添加一個 XML 片段來進行匹配測試。例如,通過設置 "binding" 屬性,下面的設置將使 Georgia 回退到 Gentium。
... <match target="pattern"> <test qual="any" name="family" compare="eq"><string>Georgia</string></test> <edit name="family" mode="assign" binding="same"><string>Gentium Book Plus</string></edit> </match> ...
在上面的例子中,"compare" 屬性可以是 "eq"(即完全等於 Georgia)、"contains"(例如,匹配 Georgia 或 Georgia Pro),或其他值。參見 [5]。
別名[編輯 | 編輯原始碼]
另一種方法是使用 <alias> 來設置「首選」字體。<family> 元素指定的字體在匹配到實際字體前,會被修改為 <prefer> 字體列表中的一個字體,順序由上至下。下面的例子使 Helvetica 回退到 Bitstream Vera Sans:
... <alias> <family>Helvetica</family> <prefer> <family>Bitstream Vera Sans</family> </prefer> </alias> ...
<alias> 也可以用來指定當缺少某些字形時使用的後備字體。例如,一個用戶將 Noto Sans 設置為默認的無襯線字體後,安裝了 Helvetica Neue,想用它書寫拉丁文字。由於很多版本的 Helvetica Neue 並不包括希臘字符,這位用戶希望使用 FreeSans 來書寫希臘文字,因為它與 Helvetica 很像。但事實上,希臘文字將會回退到用戶設置的默認字體 Noto Sans,而使用下面的方法則可以實現:
... <alias> <family>Helvetica Neue LT Pro</family> <prefer> <family>Helvetica Neue LT Pro</family> <family>FreeSans</family> </prefer> </alias> ...
如果用戶只是想在使用的字體缺少相應字形時,回退到默認字體,則不需要上述設置。
字體白名單/黑名單[編輯 | 編輯原始碼]
禁用位圖字體[編輯 | 編輯原始碼]
禁用位圖字體縮放[編輯 | 編輯原始碼]
自動生成粗體和斜體[編輯 | 編輯原始碼]
規則優先級[編輯 | 編輯原始碼]
Fontconfig 按數字順序處理 /etc/fonts/conf.d
中的文件。因此,01-aaa.conf
和 02-bbb.conf
的規則將與單個 01-aaabbb.conf
文件具有相同的效果——首先包含 01-aaa
的規則,然後是 02-bbb
的規則。
通常來說,這意味着前綴較小文件將具有較高的優先級。但是,Fontconfig 的語法很靈活,允許新規則優先於現有規則。因此,建議#查看當前設置來測試規則相互作用的結果。
$XDG_CONFIG_HOME/fontconfig/fonts.conf
和目錄 $XDG_CONFIG_HOME/fontconfig/conf.d
中定義的用戶規則是通過文件 /etc/fonts/conf.d/50-user.conf
載入的,並且通常優先於以較大數字開頭的文件中定義的規則。查看當前設置[編輯 | 編輯原始碼]
要查看當前生效的設置,可使用 fc-match --verbose
。例如:
$ fc-match --verbose Sans
family: "DejaVu Sans"(s) hintstyle: 3(i)(s) hinting: True(s) ...
可在 font-config(5) 中查詢數字的意義。例如,hintstyle: 3 代表 hintfull。
不支持 Fontconfig 的程序[編輯 | 編輯原始碼]
有些應用程式,如 Telegram,會忽略 Fontconfig 設置。你可以通過使用 ~/.Xresources
來解決這個問題,但它沒有 Fontconfig 那麼靈活。例如(#Fontconfig 配置中有對各個選項的解釋):
~/.Xresources
Xft.autohint: 0 Xft.lcdfilter: lcddefault Xft.hintstyle: hintslight Xft.hinting: 1 Xft.antialias: 1 Xft.rgba: rgb
確保 X 在通過 xrdb -q
啟動時能正確加載設置(更多信息參見 X resources)。
疑難問題[編輯 | 編輯原始碼]
字體模糊[編輯 | 編輯原始碼]
系統 DPI 設置與顯示器的硬件 DPI 不匹配會導致字體顯示模糊不清;關於處理高 DPI 或混合 DPI 顯示器的說明,請參見HiDPI。
一些字體在小尺寸下顯示不正確(如 Calibri, Cambria, Monaco 等)[編輯 | 編輯原始碼]
一些矢量字體內嵌有位圖版本,這些位圖字體主要用於在較小的尺寸下渲染。在這種情況下,使用公制兼容字體作為替代可以改善渲染效果。
你也可以通過禁用字體的嵌入式位圖來強制在所有尺寸下使用矢量字體,但會犧牲一些渲染質量。
應用程式無視 Fontconfig 的微調或抗鋸齒設置[編輯 | 編輯原始碼]
一些應用程式或桌面環境可能會覆蓋默認的 Fontconfig 微調和抗鋸齒設置。這種情況可能發生在 GNOME 上,例如,當你使用 vlc包 或 smplayer包 等 Qt 應用程式時。在這種情況下,請使用該應用程式特定的配置程序。對於 GNOME,請嘗試使用 gnome-tweaks包。
應用程式無視 GNOME 的微調設置[編輯 | 編輯原始碼]
在 GNOME 下,有時會發生這樣的情況:即使在 GNOME 設置中將微調設置為「無」,Firefox 之類的應用也會使用「完全」微調設置渲染字體,導致字體變得寬而銳利。在這種情況下,你必須在你的 fonts.conf
文件中添加微調設置:
<?xml version='1.0'?> <!DOCTYPE fontconfig SYSTEM 'urn:fontconfig:fonts.dtd'> <fontconfig> <match target="font"> <edit mode="assign" name="hinting"> <bool>false</bool> </edit> </match> </fontconfig>
在上面的例子中,微調級別被設置為了 "greyscale"。
GTK 應用程式的字體微調不正確[編輯 | 編輯原始碼]
在某些桌面環境(尤其是 GNOME 和 Plasma 之外的)中,一些 GTK 應用程式無法正確讀取字體配置。為了解決這個問題,請安裝 xsettingsd包 或 xsettingsd-gitAUR 並在每次系統啟動時運行它。更多信息請參見 Xsettingsd 和xsettingsd wiki。
對於此問題,可以使用以下配置:
~/.xsettingsd
Xft/Hinting 1 Xft/HintStyle "hintslight" Xft/Antialias 1 Xft/RGBA "rgb"
如果這在一些應用程式中依然不起作用,可以安裝 xorg-xrdb包 並使用以下配置:
~/.Xresources
Xft.hinting: 1 Xft.hintstyle: hintslight Xft.antialias: 1 Xft.rgba: rgb
然後在每次系統啟動時執行腳本 xrdb -merge ~/.Xresources
來應用這些設置。參見 X resources 和 #不支持 Fontconfig 的程序。
此外,使用 GTK4 和 libadwaita 的程序會忽略字體微調設置。可以創建或修改以下配置來修正:
~/.config/gtk-4.0/settings.ini
[Settings] gtk-hint-font-metrics=true
生成的 PDF 文件中的 Helvetica 字體模糊[編輯 | 編輯原始碼]
如果執行如下命令
fc-match helvetica
返回
helvR12-ISO8859-1.pcf.gz: "Helvetica" "Regular"
那麼由 xorg-fonts-75dpi包 提供的位圖字體就有可能被嵌入到各種應用程式的「打印到文件」或「導出」功能所生成的 PDF 文件中。該位圖字體可能是在安裝整個 xorg包組 包組的時候安裝的(通常不推薦這樣做)。要解決這個問題,可以卸載該軟件包,並安裝gsfonts包(Type 1)或tex-gyre-fonts包(OpenType)字體,以獲得 Helvetica(以及其他 PostScript/PDF 基本字體)的自由替代品。
FreeType 破壞了位圖字體[編輯 | 編輯原始碼]
一些用戶報告說,在將 freetype2包 升級到 2.7.1 版本後,各個位圖字體的名稱發生了變化,導致終端模擬器和其他一些程序(如 dwm 或 dmenu)的字體混亂,因為它們會回退到另一種不同的字體進行顯示。該問題是由 PCF 字體族格式的改變造成的,這在他們的發佈說明[6]中有所描述。從舊格式過渡到新格式的用戶可以通過創建字體別名來解決這個問題,就像[7]中描述的解決方案一樣;該方案同時在下面給出:
假設我們想為terminus-font包創建一個別名,在之前提到的 freetype2包 更新中,它從{ {ic|Terminus}} 被改名為 xos4 Terminus
,那麼在 /etc/fonts/conf.d/
中創建一個文件,用於設置字體別名:
/etc/fonts/conf.d/99-TerminusPCFFont.conf
<?xml version="1.0"?> <!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd"> <fontconfig> <alias> <family>Terminus</family> <prefer><family>xos4 Terminus</family></prefer> <default><family>fixed</family></default> </alias> </fontconfig>
現在,一切都應該能夠像之前一樣正常工作,但務必重新加載 .Xresources
或重啟顯示伺服器,以便使受影響的程序能夠使用字體別名。
DejaVu 的等寬字體不能顯示下劃線[編輯 | 編輯原始碼]
自 Pango 1.44 起,在以某些字號使用 DejaVu Sans Mono 字體時,下劃線會消失。一種解決辦法是使用 Liberation Mono 作為等寬字體,見#設置默認或後備字體。
調試 FreeType 字體[編輯 | 編輯原始碼]
freetype2-demos包 提供用於調試 FreeType 字體配置的工具。ftview
是它的一個 GUI,你可以在其中實時預覽字體的渲染設置。比如:
$ ftview -e unic -d 1024x768x24 -r 96 10 /usr/share/fonts/noto/NotoSans-Regular.ttf
網頁將數字和空格顯示得很寬[編輯 | 編輯原始碼]
這是因為網頁優先使用了 emoji 字體。一種情況是,用戶在字體配置文件中指定了優先使用 emoji 字體。這種情況只需要刪除該配置即可。一種類似的情況是用戶在字體配置文件中替換了一部分符號字體(例如使用了noto-color-emoji-fontconfigAUR),這種情況也是刪除相關配置(使用該AUR包的可以換用noto-color-emoji-fontconfig-no-bindingAUR)。
另一種情況是,網頁做了奇怪的假設,比如「假設有 Apple Color Emoji 的人一定在使用 macOS」,從而優先使用 macOS 才識別的系統字體、然後是 emoji 字體。繞過的辦法是,讓 fontconfig 假裝系統上有這類字體,比如將如下內容保存為 ~/.config/fontconfig/web-ui-fonts.conf
,並在 ~/.config/fontconfig/fonts.conf
開頭 <include prefix="xdg">fontconfig/web-ui-fonts.conf</include>
。
<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
<!--
https://caniuse.com/extended-system-fonts
GitHub uses this for code blocks.
-->
<match target="pattern">
<test qual="any" name="family">
<string>ui-monospace</string>
</test>
<edit name="family" mode="assign" binding="same">
<string>monospace</string>
</edit>
</match>
<match target="pattern">
<test qual="any" name="family">
<string>ui-sans-serif</string>
</test>
<edit name="family" mode="assign" binding="same">
<string>sans-serif</string>
</edit>
</match>
<match target="pattern">
<test qual="any" name="family">
<string>ui-serif</string>
</test>
<edit name="family" mode="assign" binding="same">
<string>serif</string>
</edit>
</match>
<match target="pattern">
<test qual="any" name="family">
<string>-apple-system</string>
</test>
<edit name="family" mode="assign" binding="same">
<string>sans-serif</string>
</edit>
</match>
</fontconfig>