Fontconfig (6日目) - デスクトップ環境のフォント設定

Fontconfigがどういう動作をするかもわかってきましたので実際の設定に入りたいのですけれども、設定ファイルを書き始める前にDEで設定できるものは設定してしまいましょう。 DEのフォント設定は ~/.config/fontconfig/fonts.conf を作ったりしますので自分の設定はそれを元に書くようにすると簡単かもしれませんし、余計なことするなになるかもしれません。 いずれにせよDEの挙動は踏まえておくべきです。

引き続きKDE neonを使用しますのでKDEに強く依存した内容にはなりますが、他のDEでもフォント設定画面はありますのでご自身の環境でどうなっているか確かめていただければと思います。

KDEのフォント設定

インストール直後のKDE neonのフォント設定画面はこのようになっていました。 (Ubuntu 22.04がベースの版。 neon-user-20221117-0714.iso からインストールして更新はしていません。)

インストール直後の状態

Notoフォントが設定されている中で等幅のHackが目立ちますね。 4日目に見ましたように fc-match 'monospace' の結果はNoto Sans Mono CJK JPでしたがこれは LANG が日本語になっていたからで、英語のmonospaceはHackです。 また英語のsans-serifはNoto SansでしたのでKDEのフォント設定では未設定時の値をFontconfigの英語の設定から取っているものと思われます。

$ fc-match monospace
NotoSansCJK-Regular.ttc: "Noto Sans Mono CJK JP" "Regular"
$ LANG=en_US.UTF-8 fc-match monospace
Hack-Regular.ttf: "Hack" "Regular"
$ LANG=en_US.UTF-8 fc-match 'sans\-serif'
NotoSans-Regular.ttf: "Noto Sans" "Regular"

で、これを弄るわけですけれども、変更が ~/.config/fontconfig/fonts.conf にどう反映されるかを見たいわけですからほぼ全部変えちゃいましょう。

Noto Sansは行間の広いフォントですからUIに使用すると表示できる内容が減ります。 VirtualBoxの狭い画面ですと尚更です。 本文は安定のDejaVu Sans、UIは小さくても文字が判別しやすいUbuntuにします。

またDPIを72にしてmacOS同様にポイントサイズとピクセルサイズが一致するようにしちゃいましょう。 (DPIを弄るのはどんな意図しない作用があるかわからないので実環境では怖いですが、実験環境ですし。)

サブピクセルレンダリングを有効にします。

ヒンティングは「軽く(hintslight)」を避けて「中間(hintmedium)」にします。

設定変更(適用前)

適用ボタンを押すと次のような ~/.config/fontconfig/fonts.conf が生成されました。

~/.config/fontconfig/fonts.conf
<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
 <its:rules version="1.0" xmlns:its="http://www.w3.org/2005/11/its">
  <its:translateRule translate="no" selector="/fontconfig/*[not(self::description)]"/>
 </its:rules>
 <!--
 Artificial oblique for fonts without an italic or oblique version
 -->
 <match target="font">
  <!-- check to see if the font is roman -->
  <test name="slant">
   <const>roman</const>
  </test>
  <!-- check to see if the pattern requested non-roman -->
  <test name="slant" target="pattern" compare="not_eq">
   <const>roman</const>
  </test>
  <!-- multiply the matrix to slant the font -->
  <edit name="matrix" mode="assign">
   <times>
    <name>matrix</name>
    <matrix>
     <double>1</double>
     <double>0.2</double>
     <double>0</double>
     <double>1</double>
    </matrix>
   </times>
  </edit>
  <!-- pretend the font is oblique now -->
  <edit name="slant" mode="assign">
   <const>oblique</const>
  </edit>
  <!-- and disable embedded bitmaps for artificial oblique -->
  <edit name="embeddedbitmap" mode="assign">
   <bool>false</bool>
  </edit>
 </match>
 <!--
 Synthetic emboldening for fonts that do not have bold face available
 -->
 <match target="font">
  <!-- check to see if the weight in the font is less than medium which possibly need emboldening -->
  <test name="weight" compare="less_eq">
   <const>medium</const>
  </test>
  <!-- check to see if the pattern requests bold -->
  <test name="weight" target="pattern" compare="more_eq">
   <const>bold</const>
  </test>
  <!--
    set the embolden flag
    needed for applications using cairo, e.g. gucharmap, gedit, ...
  -->
  <edit name="embolden" mode="assign">
   <bool>true</bool>
  </edit>
  <!--
   set weight to bold
   needed for applications using Xft directly, e.g. Firefox, ...
  -->
  <edit name="weight" mode="assign">
   <const>bold</const>
  </edit>
 </match>
 <match target="font">
  <edit name="hinting" mode="assign">
   <bool>true</bool>
  </edit>
 </match>
 <match target="font">
  <edit name="hintstyle" mode="assign">
   <const>hintmedium</const>
  </edit>
 </match>
 <match target="font">
  <edit name="rgba" mode="assign">
   <const>rgb</const>
  </edit>
 </match>
 <match target="font">
  <edit name="antialias" mode="assign">
   <bool>true</bool>
  </edit>
 </match>
</fontconfig>

上からざっとこんな感じでしょうか。

  • フォントがイタリック体(oblique)を持っていない場合に変換行列を使ってイタリック体っぽくする。

  • フォントがボールド体を持っていない場合に embolden をtrueにしてボールド体っぽくする。

  • hintinghintstylergbaantialias はフォント設定画面で選択したそのまま。

イタリック体やボールド体が無い場合のフォローまでしてくれてるとは気が利いてますね。

適用ボタンを押して一度ログアウト/ログインしなおしたスクリーンショットになります。

適用/ログアウト/ログイン後

hintslightの罠

上でヒンティングを「中間(hintmedium)」にしました。 「軽く(hintslight)」を避けるのは理由があります。

FreeTypeのドキュメント On slight hinting, proper text rendering, stem darkening and LCD filters に書かれていますが、以前はhintslightはautohintを有効にするのと同じ意味でした。 現在はOpenType/CFFフォントでは望ましい挙動に変更されているようです。 しかしTrueTypeフォントでは依然autohintと同じです。

autohintは元々持っているヒント情報の質が悪いフォントには有効なのですが、全体を通じて有効にしたいものではありません。 ですので全体に影響する設定ではautohintと共にhintslightも避けます。

アンチエイリアスから除外する範囲

ちなみに「アンチエイリアスから除外する範囲」を例えば1ptから9ptまで設定すると次のような内容が出力されます。

~/.config/fontconfig/fonts.conf
<!-- 省略 -->
<match target="font">
 <test compare="more_eq" name="size" qual="any">
  <double>1</double>
 </test>
 <test compare="less_eq" name="size" qual="any">
  <double>9</double>
 </test>
 <edit name="antialias" mode="assign">
  <bool>false</bool>
 </edit>
</match>
<match target="font">
 <test compare="more_eq" name="pixelsize" qual="any">
  <double>1</double>
 </test>
 <test compare="less_eq" name="pixelsize" qual="any">
  <double>12</double>
 </test>
 <edit name="antialias" mode="assign">
  <bool>false</bool>
 </edit>
</match>
<!-- 省略 -->

現在のFreeTypeでは特定のフォントを除きどのサイズでもアンチエイリアスを使ったほうが綺麗になりますのでこの設定はいらないと思います。

KDEのフォントファミリー設定の保存場所

~/.config/fontconfig/fonts.conf には設定したDejaVu Sans、DejaVu Sans Mono、Ubuntu等の名前が見当たりません。 Fontconfigのmonospaceとsans-serifはどうなっているでしょうか?

$ fc-match monospace
NotoSansCJK-Regular.ttc: "Noto Sans Mono CJK JP" "Regular"
$ LANG=en_US.UTF-8 fc-match monospace
Hack-Regular.ttf: "Hack" "Regular"
$ fc-match 'sans\-serif'
NotoSansCJK-Regular.ttc: "Noto Sans CJK JP" "Regular"
$ LANG=en_US.UTF-8 fc-match 'sans\-serif'
NotoSans-Regular.ttf: "Noto Sans" "Regular"

変わっていません。 Hack/Noto Sans Mono CJK JPとNoto Sans/Noto Sans CJK JPのままです。

KDEのフォント設定は上側のフォントファミリーの部分に関してましては ~/.config/kdeglobals に保存されます。 KDEアプリケーションはKDEのライブラリを用いてますのでそれで反映されます。 また ~/.gtkrc-2.0~/.config/gtk-3.0/settings.ini も修正されますのでGTKアプリケーションにも反映されます。 (こうしてKDEがGTKの設定ファイルを変更するのは同一環境に複数のDEを共存させる際の障害にもなっています。)

KDEライブラリもGTKも使っていないアプリケーションやFlatpak等のコンテナ内で実行されるアプリケーション等にも狙ったフォントを使わせたい場合はFontconfigの設定が必要になりますので、明日以降設定していきましょう。

KDEのDPI設定の保存場所

すみませんわかりません探しておきます……。

~/.config/kcmfonts に記録されていました。