🕒 この記事を読むのに必要な時間 🕒
要約のみ: 約 3分 ※オススメ!
全文: 約 20分
📜 必要な知識 📜
Linuxコマンドライン操作: 中級
fontconfig に関する知識: 中級
vim に関する知識: 初級
💻 実行環境 💻
OS: Linux Mint 22.2 x86_64
Kernel: 6.8.0-85-generic
Shell: bash 5.2.21
DE: Xfce 4.18
WM: Xfwm4
Terminal: xfce4-terminal
Packages: vim 2:9.1.0016-1ubuntu7.9, vim-airline 0.11-2, fonts-powerline 2.8.3-5, fonts-migmix 20200307-1
🔶 概要
Linux Mint へ fonts-powerline パッケージをインストールして vim-airline を設定したが、正しくフォントが表示されない。以下の画像のように、文字化けして表示されてしまう。
同じ設定を使用している Arch Linux 上では以下のように表示されている。
前提として .vimrc や vim-airline の設定自体はコピーしてきたものなので、間違っていない。これを解決する。
🔶 TL;DR 先に結論の要約を述べる
fontconfig の設定がされていないためだった。
日本語フォントの等幅フォントと Powerline フォント を一緒に使用するために必要な設定が欠けてしまっている。
以下のようなファイルを作成することで表示されるようになる。
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<!-- Add PowerlineSymbols preferences for Japanese monospace fonts -->
<fontconfig>
<alias>
<family>IPA明朝,IPAMincho</family>
<prefer><family>PowerlineSymbols</family></prefer>
</alias>
<alias>
<family>Takao明朝,TakaoMincho</family>
<prefer><family>PowerlineSymbols</family></prefer>
</alias>
<alias>
<family>IPAゴシック,IPAGothic</family>
<prefer><family>PowerlineSymbols</family></prefer>
</alias>
<alias>
<family>Migu 1M</family>
<prefer><family>PowerlineSymbols</family></prefer>
</alias>
<alias>
<family>Migu 2M</family>
<prefer><family>PowerlineSymbols</family></prefer>
</alias>
<alias>
<family>Takaoゴシック,TakaoGothic</family>
<prefer><family>PowerlineSymbols</family></prefer>
</alias>
<alias>
<family>MigMix 1M</family>
<prefer><family>PowerlineSymbols</family></prefer>
</alias>
<alias>
<family>MigMix 2M</family>
<prefer><family>PowerlineSymbols</family></prefer>
</alias>
</fontconfig>
もし、上記に自分が使いたい等幅フォントが含まれていない場合、真似して追加すること。
終わったら fc-cache コマンドを使って fontconfig のキャッシュを更新。端末アプリ(仮想ターミナル)を再起動すれば正しく表示されるだろう。
$ fc-cache -v -f
以下は解決までのログ。読まなくていい。詳しく知りたい方、興味のある方用。
🔶 現象を突っ込んで追ってみると…
なぜか GVIM では正しく表示されていた。
…フォントの字間の問題で間が空いていて、ちょっとダサいけど。
まあ、そこはいいとする。GVIM あんま使わないし。
色々いじっていると、 GVIM の [編集] > [フォント設定] でフォントを変えたとき Monospace や DejaVu Sans Mono などは正しく表示されるが、後から俺ちゃんが入れた日本語フォントとかにすると文字化けすることに気づいた。
そういえば、端末の方も日本語の等幅フォントにしていたんだった。
俺ちゃんは fonts-migmix パッケージをインストールして Migu 1M Regular を設定して使っている。
これを Monospace に戻してみると… ちゃんと表示された!
🔶 原因の推測
これらの現象から、 Linux Mint にデフォルトで入っている等幅フォントについては問題なく表示できるが、後からユーザーが追加した等幅フォントについては文字化けしてしまうのではないか?ということがわかった。
これの理由だが、フォントの重ね合わせの問題であると推測される。
Linux においてフォントは fontconfig という仕組みを用いて選択が行われ、画面へと描画される。
テキスト中に現れる文字自体は、例えば A なら 16進数で 0x41 のようなバイナリにすぎないが、これをどのフォントの "A" を使って表示すればよいのか、その優先度と重ね合わせを決定しているのが fontconfig なのである。
A 〜 Z, 0 〜 9 などの ASCII 文字列 については定義が明確で、どのフォントでも同じアルファベットや数字として製作された字体を指すので、問題にはならない。だが、今回の Powerline シンボルのような特殊な文字では バイナリの定義が未定義な、本来その意味で定義されたものではないバイナリ領域を その文字(グリフ)として用いてしまっているようだ。
このため、そのバイナリ・コードが入っていた場合に、どのフォントを使えばよいのかを fontconfig でしっかり定義されていないと文字化けが起こってしまう。
Linux Mint(というか、その元の Ubuntu)に最初から入っているフォントについてはこの定義がちゃんと行われているが、ユーザーが後から入れたフォントについては定義されていなくて、定義の追加が必要となっているものと推測される。
🔶 答え合わせ
推測が正しければ、 fonts-powerline パッケージには fontconfig を設定するためのファイルが含まれているはずだ。 dpkg コマンドを使ってみると以下が入っていた。
$ dpkg -L fonts-powerline | grep conf
/etc/fonts/conf.avail
/etc/fonts/conf.avail/10-powerline-symbols.conf
/etc/fonts/conf.d
/etc/fonts/conf.d/10-powerline-symbols.conf
$
$ ll /etc/fonts/conf.d/10-powerline-symbols.conf
lrwxrwxrwx 1 root root 39 2月 4 2024 /etc/fonts/conf.d/10-powerline-symbols.conf -> ../conf.avail/10-powerline-symbols.conf
$
ll の出力で分かると思うが、 /etc/fonts/conf.d/10-powerline-symbols.conf は /etc/fonts/conf.avail/10-powerline-symbols.conf を指すシンボリックリンクだ。なので実体は後者である。
これを less コマンドなどで閲覧してみると、以下のような定義が入っていた。
<alias>
<family>monospace</family>
<prefer><family>PowerlineSymbols</family></prefer>
</alias>
...
<alias> は別名を定義することを意味する。転じて既にあるフォント・ファミリーに対して別の定義で上書きすることを指す。ここでは次の <family> に指定したフォント・ファミリー名 "monospace" を再定義している。
これによってアプリケーションやウィンドウマネージャーなどで monospace に該当するフォントを指定すると、この別名(エイリアス)定義が使われる。
<family> はメインとなるフォント・ファミリーの指定である。フォント・ファミリーとはフォントを構成する単位のことで、例えば { 通常, 斜体, 太字 } といった同じ字体ではあるが、少し異なるスタイルのフォントをひとつにまとめたもののこと。ここでは "monospace" を指定しているので、 Monospace Regular, Monospace Italic, Monospace Bold などがこれに含まれている。
<prefer> は preference(プレファレンス) の意味で "優先" を意味するタグだ。メインとなるフォントよりも優先して表示されるべき、フォント・ファミリーをここで定義しておくことができる。 <family> タグを使って定義する。
ここでは "PowerlineSymbols" を値としているので、メインで指定したフォント・ファミリーよりも優先的に Powerline フォント が使用されることを意味する。
具体的にこれがどのように動作するかだが、この例で言えば "monospace" フォント・ファミリーに属するフォント(例えば Monospace Regular)をユーザーが選択しているときに、それよりも先にまずこの "PowerlineSymbols" フォント・ファミリーに該当フォントが無いか調べられる。有る場合は、それが優先して使われる。無い場合には "monospace" フォントファミリーが使用される。(こうした仕組みをフォールバックという)
"PowerlineSymbols" について言えば、通常の ASCII や日本語のグリフは含まないのでそれらのバイナリの場合は "monospace" が使われる。"PowerlineSymbols" のグリフに含まれるバイナリ・コードのときだけ、そちらが優先して使われる。
これによって Monospace フォント に Powerline フォント が合わさったような、あたかも Monospace フォントに追加で Powerline フォント が増えたような効果が期待できるのだ。
/etc/fonts/conf.avail/10-powerline-symbols.conf を調べると、 monospace 以外にもいろいろな等幅フォントがこうして定義されていた。デフォルトでは入っていない、 "Droid Sans Mono" などもあるが… 日本語フォントは皆無だった。
これを追加してやれば良さそうだ。
【余談】
因みに、フォント・ファミリー monospace は実体のフォントファイルが存在しない仮想的なフォントファミリー名のようだ。 Linux Mint では日本語環境を整えた後の状態ではこれは "Takaoゴシック" が使われる。
$ fc-match -s monospace | head
TakaoGothic.ttf: "Takaoゴシック" "Regular"
PowerlineSymbols.otf: "PowerlineSymbols" "Medium"
DejaVuSansMono.ttf: "DejaVu Sans Mono" "Book"
DejaVuSansMono-Bold.ttf: "DejaVu Sans Mono" "Bold"
DejaVuSansMono-Oblique.ttf: "DejaVu Sans Mono" "Oblique"
NotoMono-Regular.ttf: "Noto Mono" "Regular"
NotoSansMono-Regular.ttf: "Noto Sans Mono" "Regular"
NimbusMonoPS-Regular.otf: "Nimbus Mono PS" "Regular"
NotoSansCJK-Regular.ttc: "Noto Sans Mono CJK JP" "Regular"
opens___.ttf: "OpenSymbol" "Regular"
$
fc-match コマンドに -s オプションをつけて実行すると、あるフォント名が呼ばれた場合に、フォントの選択がどのような順序で優先されているのか、確認できる。
上記のように、 monospace は "Takaoゴシック"、 "PowerlineSymbols" の順で使われる。<prefer> タグで指定しているので実際には "PowerlineSymbols" のほうが優先になるだろう。
その後にも "DejaVu Sans Mono" などが続いているが… これはエイリアスではなく フォント・フォールバック という仕組みを使って定義されている。これがあるため、絵文字などの含まれない文字についても(例えば Noto Color Emoji などが入っていれば)フォールバックされて表示されるのである。
🔶 使用している等幅フォントの定義を追加する
ただし、 /etc/fonts/conf.avail/10-powerline-symbols.conf に直接追加するのはよくない。このファイルはパッケージ・メンテナが作成したものであって、変更してもパッケージの更新があると再び上書きされてしまうからだ。
そこでユーザーのホームディレクトリの以下の場所へファイルを作成する。
$XDG_CONFIG_HOME/fontconfig/conf.d/10-powerline-symbols.conf
このファイルは、そのユーザー環境のみに効力がある fontconfig の設定ファイルだ。しかし Linux Mint Xfce エディション の場合なぜか $XDG_CONFIG_HOME 環境変数が定義されていないので、まずはこれを定義しておく。
$ export XDG_CONFIG_HOME=$HOME/.config
ディレクトリを作り、XML のヘッダーを作る。
$ mkdir -p $XDG_CONFIG_HOME/fontconfig/conf.d
$ cat > $XDG_CONFIG_HOME/fontconfig/conf.d/10-powerline-symbols.conf
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<!-- Add PowerlineSymbols preferences for Japanese monospace fonts -->
<fontconfig>
4行の XML をコピペ し終わったら Ctrl + D キーで cat コマンドを終了させること。
次に、エイリアスを作成する。
日本語の等幅フォントは spacing=90 で作られているので以下のようなコマンドで生成することができる。
$ fc-list :lang=ja:spacing=90 family | sed -re 's|(.+)|\t<alias>\n\t\t<family>\1</family>\n\t\t<prefer><family>PowerlineSymbols</family></prefer>\n\t</alias>|g' >>$XDG_CONFIG_HOME/fontconfig/conf.d/10-powerline-symbols.conf
Ctrl + D キーで cat コマンドを終了させる。
これで以下のようなリストが生成され、追記される。
<alias>
<family>IPA明朝,IPAMincho</family>
<prefer><family>PowerlineSymbols</family></prefer>
</alias>
...
このとき、以下のような fontconfig によるエラーが出るが、気にしないでいい。まだ設定ファイルが完全ではないので出ているだけだ。
Fontconfig error: "/home/9hnder/.config/fontconfig/conf.d/10-powerline-symbols.conf", line 5: no element found
最後に、フッターを追記しておく。
$ cat >> $XDG_CONFIG_HOME/fontconfig/conf.d/10-powerline-symbols.conf
</fontconfig>
Ctrl + D キーで cat コマンドを終了させる。
終わったら fc-cache コマンドを使って fontconfig のキャッシュを更新しておこう。
$ fc-cache -v -f
これで端末(俺ちゃんの場合は xfce4-terminal)を再起動すれば OK。
以下のようにちゃんと表示されるようになった。
解決。
うむ。余は満足じゃ。
🔶 参考




