2019年04月14日

Ubuntu mono のカギカッコのずれを直した

ターミナルのフォントを変更しようとしたら、等幅フォントのくせにガッタガタになったときの記録。

発端

ターミナルのフォントは今まで(なんとなく) Takao フォントの等幅、 TakaoGothic を使っていた。コード以外の文書を作るときもターミナルで済ませるので、日本語もきれいに見えるほうがよかろうという理由だったと思う。

それが(なんとなく)コード読むときに読みづらいなぁと気づいて Ubuntu mono に変えたらくっきりして見やすくなった。喜んだのもつかの間、マルチバイト文字がいまいち揃っていないことに気づいた。下図の真ん中がそれ。

Ubuntuでの等幅フォント
それぞれ (1) TakaoGothic を指定 (2) Ubuntu mono を指定しただけ (3) Ubuntu mono を指定して fontconfig を修正

感嘆符にカーソルを合わせているため1マス反転されているが、(2)だけ位置ズレしていることがわかる。これを修正する手順をメモしておく。

フォントを調べる

fontconfig のデバッグは環境変数 FC_DEBUG で気軽にできる。とりあえずテキストレンダリング用に pango-view を使うがこの出力は捨てる (-q)。第一引数のフォント名を指定した状態で第二引数の文字が実際には何のフォントが使われるかを調べる。

# fontlookup.sh
FC_DEBUG=4 pango-view -q --font="$1" -t "$2" | grep 'family:\s*"' | tail -n1

実行してみる。

$ bash fontlookup.sh "Ubuntu mono" a
        family: "Ubuntu Mono"(s)
$ bash fontlookup.sh "Ubuntu mono" あ
        family: "TakaoPGothic"(s)

TakaoPGothic、プロポーショナルフォントが使われている。それはズレるね!

解決策

考えられる方法は3つ。

  • (A) Ubuntu mono のフォールバックに TakaoGothic を指定する
  • (B) フォント指定を monospace (システムデフォルト) にして、fontconfig のデフォルトを Ubuntu mono → TakaoGothic の順にする
  • (C) TakaoGothic に含まれる ASCII 文字を禁止して代わりに Ubuntu mono を参照するように変える

過激派としては(C)も捨てがたいが、ターミナル外の日本語文書や UI では Ubuntu mono の半角文字はちょっと癖が強そうだったのでやめにした。

とりあえず(A)を試す。

# ~/.config/fontconfig/conf.d/99-monospace.conf
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
  <match>
    <test qual="any" name="family">
      <string>Ubuntu Mono</string>
    </test>
    <edit name="family" mode="append" binding="strong">
      <string>TakaoGothic</string>
    </edit>
  </match>
</fontconfig>

キャッシュを消去して確認。

$ fc-cache -f
$ bash fontlookup.sh "Ubuntu mono" a
  family: "Ubuntu Mono"(s)
$ bash fontlookup.sh "Ubuntu mono" あ
  family: "TakaoGothic"(s)

ビフォー
TakaoGothic

アフター
Ubuntu mono + TakaoGothic

英字がくっきりして色味が強くなったのと太字が効くようになったので見やすさがかなり上がって満足。
いや、Ubuntu mono に含まれる三点リーダがベースラインについているのが不満なのでこれを実現するために (C) の方法を探すか……

ちなみに三点リーダが真ん中に来るほうが誤りじゃないのかよというバグ報告もあったりする→Bug #956016 “Three middle dot is used as HORIZONTAL ELLIPSIS” : Bugs : Takao Fonts
実際は三点リーダの位置は地域慣習によって違うのでどっちでもいい。

日本語表記では、原稿用紙マスの真中を通るように点を並べる。多くの欧文フォントは、ベースライン上に点が並ぶ。3点リーダーとは別に Midline horizontal ellipsis (⋯) があり、こちらではフォントによらず点は中央を通る。

リーダー (記号) - Wikipedia

うまくいかなかった残骸

1. Ubuntu mono が sans-serif 扱い

先のコマンドと同じ方法で出したデバッグログを眺めると、Ubuntu mono が monospace (等幅) ではなく sans-serif (ゴシック体) として処理されていることがわかった。 そのため TakaoPGothic を始めとしたプロポーショナルフォントがフォールバックとして名を連ねてしまっている。

Prepend list after “Ubuntu mono”(s) “DejaVu Sans”(w) “DejaVu LGC Sans”(w) “DejaVu LGC Sans”(w) “DejaVu Sans”(w) “Bitstream Vera Sans”(w) “Verdana”(w) “Arial”(w) “Albany AMT”(w) “Luxi Sans”(w) “Nimbus Sans L”(w) “Nimbus Sans”(w) “Helvetica”(w) “Lucida Sans Unicode”(w) “BPG Glaho International”(w) “Tahoma”(w) “Loma”(w) “Waree”(w) “Garuda”(w) “Umpush”(w) “Laksaman”(w) “Noto Sans CJK JP”(w) “Noto Sans CJK KR”(w) “Noto Sans CJK SC”(w) “Noto Sans CJK TC”(w) “Droid Sans Fallback”(w) “TakaoPGothic”(s) […] “VL Gothic”(w) “IPAMonaGothic”(w) “IPAGothic”(w) “Sazanami Gothic”(w) “Kochi Gothic”(w) “AR PL KaitiM GB”(w) “AR PL KaitiM Big5”(w) “AR PL ShanHeiSun Uni”(w) “AR PL SungtiL GB”(w) “AR PL Mingti2L Big5”(w) “MS ゴシック”(w) […]

これは /etc/fonts/conf.d/49-sansserif.conf が一律にフォントファミリーを付与しているのが原因。

# /etc/fonts/conf.d/49-sansserif.conf
<match target="pattern">
  <test qual="all" name="family" compare="not_eq">
    <string>sans-serif</string>
  </test>
  <test qual="all" name="family" compare="not_eq">
    <string>serif</string>
  </test>
  <test qual="all" name="family" compare="not_eq">
    <string>monospace</string>
  </test>
  <edit name="family" mode="append_last">
    <string>sans-serif</string>
  </edit>
</match>

フォントファミリーに「sans-serif」「serif」「monospace」のいずれも含まれていなければ「sans-serif」とみなすというもの。ちょっと乱暴すぎないか?

→ このファイル(シンボリックリンク)を削除。 TakaoPGothic はまだ消えない。どうやら Ubuntu mono のフォールバックフォントがないため、日本語のデフォルトフォントである TakaoPGothic (実際は “/usr/share/fonts/truetype/fonts-japanese-gothic.ttf”) が使われているようだ。

2. TakaoGothic でしゃばりすぎ

Ubuntu mono を monospace にしてみる

<match target="pattern">
  <test qual="all" name="family">
    <string>Ubuntu mono</string>
  </test>
  <edit name="family" mode="assign" binding="same">
    <string>monospace</string>
  </edit>
</match>

すると英字でも TakaoGothic が強制されるようになってしまった。

$ bash fontlookup.sh "Ubuntu mono" a
    family: "TakaoGothic"(s)

これは Takao が日本語環境において TakaoGothic を等幅フォントの先頭に入れるようにしているから。

# /etc/fonts/conf.d/65-fonts-takao-gothic.conf
<match target="pattern">
    <test name="lang" compare="contains">
        <string>ja</string>
    </test>
     <test qual="any" name="family">
        <string>monospace</string>
    </test>
    <edit name="family" mode="prepend" binding="strong">
        <string>TakaoGothic</string>
    </edit>
</match>

fc-match で見るとこんな感じ

$ fc-match -s monospace | head -n3
TakaoGothic.ttf: "TakaoGothic" "Regular"
DejaVuSansMono.ttf: "DejaVu Sans Mono" "Book"
DejaVuSansMono-Bold.ttf: "DejaVu Sans Mono" "Bold"

$ LANG=C fc-match -s monospace | head -n3
DejaVuSansMono.ttf: "DejaVu Sans Mono" "Book"
DejaVuSansMono-Bold.ttf: "DejaVu Sans Mono" "Bold"
DejaVuSansMono-Oblique.ttf: "DejaVu Sans Mono" "Oblique"

同じ理由で (B) ターミナルの指定フォントを monospace にする も使えない。実際には fontconfig の柔軟性を考えればユーザーローカルの設定で上書きできそうだが (A) で解決できたのでよしとする。

参考

Fixing My Missing Degree Celsius Symbol | 梦断代码
FC_DEBUG を用いて、実際に使われたフォントを探す方法。記事の内容自体も「℃」記号が表示されないことにある日気づいたという地味ながらなかなか根深い問題で興味深い。

I stared into the fontconfig, and the fontconfig stared back at me / fuzzy notepad
49-sansserif.conf が sans-serif を付与することについて、セリフ体とか等幅とかは人の目で見て確認すべきなんだからフォント名を元に一括指定とかひどい、考えられない。まったくもって同意。

posted by かぷらす at 23:11| Comment(0) | 作業記録 | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
コチラをクリックしてください