Fontconfig (1日目) - 設定ファイル

フォントの設定を始めると止まらなくなる病を誰かに移してしまいたい。 というわけで今年はfontconfigをネタに書こうかなと思います。

Fontconfigとは

X WindowやWaylandのクライアントアプリケーションがテキストを描画する際に、注文されたフォントパターンに対して実際のフォントを対応付ける freedesktop.org のソフトウェアです。 主にLinuxやBSDで使われています。 クロスプラットフォームなアプリケーションであればWindowsやmacOS向けにビルドされていてもFontconfigが使われていることも稀によくあります。

注文されたフォントパターンと実際のフォントって何が違うの?って疑問が湧くと思います。

これは例えばCSSで font-family: "Noto Sans", sans-serif; のように書いた場合をイメージしていただければわかりやすいと思います。 閲覧環境に「Noto Sans」があればそれを使い、なければブラウザのデフォルトフォント(大抵のブラウザではsans-serif、serif、monospaceの3種類のデフォルトフォントが設定できます。そのうちのsans-serifに設定したもの)を使うという意味ですね。 実際の動作はもっと複雑ですが、今はとりあえずざっくりと。

これと同じようなことがブラウザ以外のGUIアプリケーションがテキストを描画する際にも行われています。 確かにブラウザ以外でsans-serifのような総称ファミリー名を使った覚えはないかもしれません。 フォントダイアログで選択するのは常に具体的なフォント名です。

しかし例えば「Noto Sans」をインストールしてそれを使うよう設定してその後「Noto Sans」をアンインストールしたとしますと、どのフォントが使われるのでしょうか。 何も表示されないか全部豆腐になるアプリケーションも全く無いとは言いませんが、大抵のアプリケーションではその時点で使用可能な何れかのフォントで代替されるはずです。

フォントはあるが特定の文字が収録されていない場合もあります。 NotoフォントファミリーはNo Tofuが語源らしく全ての文字を網羅することを目標に開発されていますが、全てがひとつのフォントファイルになっているわけではありません。 日本語の文字が収録されているのは「Noto Sans CJK JP」「Noto Sans Mono CJK JP」、ファイルでいえば NotoSansCJK-Regular.ttc であり、「Noto Sans」の NotoSans-Regular.ttf とは別になっています。 しかし大抵のアプリケーションでは日本語の文字を収録していないはずの欧文フォントを設定した状態でも日本語を表示できます。 これも何も表示されないか全部豆腐になるアプリケーションも全く無いとは言いませんが、大抵のアプリケーションでは何らかのフォントで代替されます。 ですのでNotoフォントファミリーがひと揃い入っていれば、レアな文字も豆腐になる前に「Noto ナントカ」の何れかで代替されるでしょう。

ここでは、ユーザーが設定するものも含めたアプリケーションが要求する存在していないかもしれないフォントのことを「フォントパターン」と呼ぶことにします。 先の例のCSSの font-family の値もこの一種です。

それに対して、実際のフォントは文字通り環境にインストールされていて使用可能な実際のフォントのことです。

あと代替先のフォントのことは「フォールバックフォント」と呼びます。

WindowsやmacOS等も同様のフォント選択メカニズムを持っています。

Windowsで言えばアプリケーションがテキストを描画するための準備として CreateFont APIか CreateFontIndirect APIを呼びます。 この引数の多数のパラメータ、あるいは LOGFONT 構造体がフォントパターンに該当し、返値のHFONTが実際のフォントに対応します。

これらのAPIの挙動はきたあきら先生の「API散歩道(上)」に詳しいです。 Windows 3.1時代の本ですが今でも通用する内容かと思います。

しかしWindowsやmacOSではフォント選択メカニズム自体に対してユーザーができることは少ないです。 レジストリや DefaultFontFallbacks.plist を書き換えたりすることで少しはカスタマイズできますが……。 (危険な操作となりますので自己責任でお願いします。)

それに対してFontconfigは設定ファイルがユーザーにも解放されておりものすごい自由度があります。 フォールバックフォントを簡単にしかも何重にも設定できます。 存在しないフォント名をでっち上げて英語ならこのフォント日本語はこのフォント、みたいに振り分けることも頑張れば可能です。

そんな素晴らしいFontconfigですが、同時にクソ仕様の塊かつドキュメントが少ないという一面もあります。 ですのでこうして語る価値がある……といいですね?

設定ファイルの場所

概要を無駄に長いこと書いてしまいました。 1日目として予定していた内容である設定ファイルの場所に移りたいと思います。 設定ファイルを開けないとはじまりませんからね。

設定ファイルは通常これだけあります。

  • /etc/fonts/fonts.conf

  • /etc/fonts/conf.d/*.conf (ファイル名先頭の数字順、1〜50)

  • ~/.config/fontconfig/conf.d/*.conf (ファイル名先頭の数字順)

  • ~/.config/fontconfig/fonts.conf

  • /etc/fonts/conf.d/*.conf (ファイル名先頭の数字順、51〜)

全てXML形式です。

*.conf はルールを書いていく設定ファイルです。 正確にはFontconfigが直接読みにいくのは /etc/fonts/fonts.conf だけで、 /etc/fonts/conf.d/ 以下のファイルは /etc/fonts/fonts.conf の中で読み込ませる記述がなされています。 同様に ~/.config/fontconfig/ 以下のファイルは /etc/fonts/conf.d/50-user.conf の中で読み込ませる記述がなされています。 そのため /etc/fonts/conf.d/ 以下の1から50で始まるファイルはユーザー設定よりも早く適用され、51以降のファイルはユーザー設定の後に適用されます。 設定内容は後からの設定で上書きされていきますので51以降のファイルはユーザー設定よりも強いことになり、ここで変な設定がなされていてもユーザー権限では覆せません。 (クソ要素のひとつです。)

ユーザー設定のパスの ~/.config/ の部分は環境変数 XDG_CONFIG_HOME で置き換えられます。

Flatpak

実際にFlatpak等のアプリケーションコンテナでは位置が異なっていて、例えばFlatpak版FontForgeであればユーザー設定は ~/.var/app/org.fontforge.FontForge/config/fontconfig/fonts.conf に書くことになります。 コンテナの中のアプリケーションに設定が反映されない場合に試してみてください。

Fontconfig以外の関連ファイル

  • /etc/fonts/disabledfonts.xml

/etc/fonts/disabledfonts.xml はKDEの「Font Management」を通じてフォントを無効にした場合に作成されます。

依存関係で仕方なく入ってくるフォントは結構あります。 (例えばDebianであればGhostscriptの依存関係にあるURWのC059、D050000L、P052、Z003等。 FreefontのFreeSans、FreeSerif、FreeMonoもよく勝手に入ってきます。) またディストリビューションによってはじめから入れられているフォントもあります。

そうした中には読み辛いフォントもあり無効にしておきたいケースもあります。

KDEの「Font Management」が行うのは、実際にはフォントファイルを先頭に "." を付けた名前にリネームすることでFontconfigから見えなくする力技ですが……。 disabledfonts.xml はあくまで元に戻せるようにするためのリストっぽいです。

他のDEでも恐らく類似の設定アプリが存在するでしょう。