Droid Sans Fallbackフォントのせいで日本語が中華漢字で表示される問題を直す
Live With Linux::practical
- TOP
- Articles
- Live With Linux
- Droid Sans Fallbackフォントのせいで日本語が中華漢字で表示される問題を直す
序
Linuxで割とよくある問題が、「日本語が表示はされるが、一部の漢字が中華漢字で表示される」という問題である。
この問題は特にウェブにおいて発生しやすく、日本語に特化していないLinuxディストリビューションでは非常によくある。
一見すると、「フォントをインストールすればいいんだろう」くらいに思うかもしれないが、実のところこの問題は非常に根深く、難しい。 そもそも、「フォント」という科目はMimir Yokohamaの授業、「Linux基礎初級」において最難関と言っても良いものである。
ちょっと調べてみたがこの問題についてちゃんと説明している記事が出てこなかった。 難しい問題であると同時に、わかっている人にとっては別に「特別なことは何もない」作業なので記事にしたりしないのだろう。
そこで、ここではその問題、修正方法、修正の意味を解説する。
前提知識
FontConfig
FontConfigはLinuxで使われている、フォントを選択する機構である。
FontConfigを用いることで、「論理的な」フォントファミリーが要求されたときに、具体的なフォントファイルとして何を使うべきかを決定できる。 また、その論理的なフォントファミリーで必要とされるグリフを満たすために、複数の具体的なフォントファイルを優先度順に回答したりすることもできる。
また、FontConfigを用いてレンダリングオプションを制御したりすることもできる。 ただし、レンダリングオプションはLinuxで標準的な1フォントレンダリングエンジンであるFreeType以外では基本的に効かない。
ブラウザとFontConfig
FirefoxおよびChromeは完全にFontConfigに頼ってはおらず、要求されたフォントファミリーについてFontConfigを使ってフォントファイルを特定することはするが、2番目以降の候補は無視し、グリフが埋まらなけれれば次のフォントファミリーを試す。
例えば和文において font-family: "Roboto", "VLGothic";
が要求されたとして、Roboto
がRoboto > Source Han Sans JP
という優先順位で定義されていたとする。
FreeTypeにおまかせするアプリケーションの場合は和文にはSource Han Sans JP
が使用されるが、ウェブブラウザの場合はRoboto
だけを適用して、VLGothic
を適用しようとする。
FontConfigの設定
FontConfigの設定は/etc/fonts
にあるfonts.conf
と、conf.d/
以下の*.conf
である。
これらのファイルのinclude
によってさらに他の設定ファイルが読まれる場合もある。
ちなみに、/etfc/fonts/conf.d/
自体、/etc/fonts/fonts.conf
で読んでいるものなので、その記述がなければconf.d
は読まれない。
ユーザーの設定はFontConfig標準の設定ファイルではuser.conf
によって読むようになっており、これにより${XDG_CONFIG_HOME:-$HOME/.config}/fontconfig/fonts.conf
と${XDG_CONFIG_HOME:-$HOME/.config}/fontconfig/conf.d/
、およびdeprecatedになっている~/.fonts.conf
と~/.fonts.conf.d/
を読むようになっている。
FontConfig設定の優先度
ファイル名の辞書順で読み、読んだ順に適用していく。
ディストリビューションとFontConfigの設定
ディストリビューションはFontConfigの設定に個性を出していることが多く、その設定の違いで挙動に違いが出たりする。
YouTube
YouTubeはDroid Sansを要求したりしなかったりするため、中華漢字になったりならなかったりする。
どういう基準なのかは不明。
FontConfigのコマンド
fc-list
はFontConfigで認識されているすべてのフォントを一覧する。
オプションをつけない場合、フォントファイルが持っている名前が一覧される。
fc-match
は引数として与えた論理名に対してFontConfigの回答を受け取れる。
-a
オプションをつけると、すべての候補を優先度順に返す。
fc-cache
はフォントキャッシュを更新する。
-f
をつけるとキャッシュを削除して更新する。
設定の反映にも使える。
修正する
まず、日本語フォントを導入する。 ここでは例として、ZEN角ゴシック NEW
(Zen Kaku Gothic New
)を使うと仮定する。
基本的に~/.local/share/fonts/
以下に置けば良い。
~/.config/fonts/20-general.conf
として次のようにする。
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
fontconfig>
<<!-- Default sans-serif font -->
match target="pattern">
<test qual="any" name="family"><string>sans-serif</string></test>
<edit name="family" mode="prepend" binding="strong">
<string>Zen Kaku Gothic New</string>
<edit>
</match>
</
<!-- Japanese Default -->
match target="scan">
<test name="lang">
<string>ja-jp</string>
<test>
</test name="family">
<string>Zen Kaku Gothic New</string>
<test>
</match>
</default>
<family>Zen Kaku Gothic New</family>
<default>
</fontconfig> </
次に~/.config/fonts/90-droid-sans.conf
として次のようにする。
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
fontconfig>
<<!-- Default sans-serif font -->
match target="pattern">
<test qual="any" name="family"><string>Droid Sans</string></test>
<edit name="family" mode="prepend" binding="strong">
<string>Zen Kaku Gothic New</string>
<edit>
</match>
</match target="pattern">
<test qual="any" name="family"><string>Droid Sans Fallback</string></test>
<edit name="family" mode="prepend" binding="strong">
<string>Zen Kaku Gothic New</string>
<edit>
</match>
</fontconfig> </
利用しているデスクトップ環境がフォントの設定を持っている場合、標準フォント、あるいはサンセリフフォントとしてsans-serif
を指定する。
最後にブラウザのフォント設定を確認し、Droid
Sansが指定されているようであればsans-serif
あるいはSans
に変更しておく。
Firefoxの場合は言語ごとの設定があるので注意。
解説
まず、webコンテンツでDroid Sansが適用される状況は次の通り。
- webコンテンツでDroid Sansが指定されている
- ブラウザが標準フォント、あるいはサンセリフフォントとしてDroid Sansを使っている
- FontConfigが
sans-serif
を要求されたときにDroid Sansを返す
もちろん、日本語フォントがインストールされていることは前提として必要となる。
次にsans-serif
対策。
sans-serif
の候補リストの先頭に、高い優先度で希望のフォントを追加する。
また、日本語のデフォルトフォントとしても同じフォントを使うように設定する。
sans-serif
とデフォルトフォントが常に同じとは限らない。
続いてDroid Sans
とDroid Sans Fallback
の候補リストに高い優先度で希望のフォントを追加する。
実はfc-list
で確認してもDroid Sans Fallback
という名前は出てこないのだが、だいたいDroid
Sans
Fallbackを構成するパッケージにdroid-sans.conf
が含まれていて、これがDroid Sans Fallback
を定義している。
この中で
match target="scan">
<test name="fullname">
<string>Droid Sans Fallback</string>
<test>
</edit name="family">
<string>Droid Sans</string>
<edit>
</edit name="fullname">
<string>Droid Sans</string>
<edit>
</edit name="fontversion">
<int>2</int>
<edit>
</match> </
としていて、ここでDroid Sans Fallback
が生まれている。
で、ウェブでDroid Sans
が要求される場合は当然ながらDroid Sans
の結果を返すのだけど、なぜかウェブではDroid Sans Fallback
のほうが使われたりする。
おそらくはFontConfig任せにフォントを選んでいないからだろう。
このため、Droid Sans
とDroid Sans Fallback
の両方に対して追加しておく必要がある。
さらに、デスクトップ環境のフォント設定する機能が設定ファイルよりも優先される場合があり、明示的にsans-serif
を使わせることで設定ファイルに従わせる。
おことわり
FontConfigの機能は非常に豊富なので、これが最適解ではない可能性がある。
ただ、一般的によく使う機能・記述を用いて実現したので、応用はしやすいと思う。
ひとこと
FontConfigはただでさえ機能がめちゃくちゃ多い上にわかりづらいというのに、XMLで書かされるせいで本当にきついし、理解しづらい。
LuaのDSLとかにしてくれないか。 それでもそこまで楽になる気はしないけど。