🍌

Linux fontconfigの設定について

2023/05/04に公開

例から始める

初めて Linux を使う場合、下記の画像のように、絵文字が表示されないまたは完全に表示されない問題に遭遇するかもしれません:

Emoji は本質的に Unicode 文字集合のサブセットであり、特定の文字が正しく表示されない場合は、システムのフォントファイルがその文字をサポートしているかどうかを確認する必要があります。一般的に、ディストリビューションには、1つの絵文字フォントが組み込まれています。たとえば、macOS/iOS には 「Apple Color Emoji」 フォントが組み込まれており、Windows には 「Segoe UI Emoji」フォントが組み込まれています。Android には 「Noto Color Emoji」フォントが組み込まれています。そのため、同じ絵文字でも、異なるデバイスで異なる外観を持つ場合があります。同じ文字でも、異なるフォントで表示されるときのように、表示効果が異なることがあります。組み込みのフォントのほか、多くのアプリケーションには Emoji フォントが搭載されています。たとえば、Twitter や Facebook などがあります。

コンピュータが文字を入力すると(たとえば、U+1F680 を入力すると)、最初に現在のフォントでその文字の字形(glyph)を検索します。現在のフォントが 「Fira Code」 であると仮定しますが、U+1F680 に対応する字形を含まないため、他のインストールされているフォント(フォールバック戦略)を検索して、U+1F680 の字形を含むフォントを探します。

コンピューターが対応するフォントを見つけられない場合、四角形または Unicode 文字が含まれた四角形が表示されます。下の画像をご覧ください:

そのため

  1. 対応するフォントファイルをインストールする。
  2. フォントファイルの使用順序を設定する。

fontconfigを設定する

第一歩として、fc-list コマンドを使用して、システムに現在インストールされているフォントファイルを確認することができます。

fc-listは、fontconfig が提供するコマンドラインツールの一つです。GUI プログラムは、fontconfig が提供するインタフェースを介してフォント情報を検索します。フォントパターンを fontconfig に渡し、fontconfig は自身のルールに従ってマッチングを行い、結果をアプリケーション側に返します。また、アプリケーションは、fontconfig を全く守らないことができます。つまり、プログラムはフォントの検索に fontconfig を使用しなくても構いません。

フォント設定のルートファイルは /etc/fonts/fonts.conf にあり、XML形式で書かれており、以下のような内容となっています

このファイルは変更する必要はありません。変更した場合でも、アップグレード時に上書きされます。上の図から、いくつかの重要なパスが定義されていることがわかります。属性値 prefix="xdg" は、デフォルトで ~/.config/ ディレクトリである XDG_CONFIG_HOME ディレクトリを表します。ユーザーレベルの設定をこのディレクトリに置く必要があります。また、conf.d パスには多くの設定ファイルが含まれています。これらの設定ファイルは、fontconfig に新しいフォントを追加するよう指示することができます。fontconfig の目標は、できるだけ使用可能なフォントを提供することであるため、システムにこれらのフォントがあれば、それらを使用して文字を表示しようとします。これは、理解できない文字が表示されない心配をする必要がないことを意味します。なぜなら、fontconfig は有効なフォントに fallback しようとします。

fc-conflist コマンドは、システム内の設定ファイルを表示することができます

設定は XML 構文に従います。詳細については、以下を参照してください https://www.freedesktop.org/software/fontconfig/fontconfig-user.html

私たちは、実際の例を使用して、以下を見てみましょう

<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
  <match target="pattern">
    <test name="family">
      <string>monospace</string>
    </test>
    <edit name="family" mode="assign">
      <string>Fira Code</string>
    </edit>
  </match>
</fontconfig>

この例では、family 属性の値が 「monospace」 の場合、 family 属性を 「Fira Code」 に設定します。以下のコードに相当します。

def custom_match(font):
    if font.family == "monospace":
        font.family = "Fira Code"

    return font

実行して、変更前と変更後の結果を比較してみてください。

各種設定を変更した後は、fc-cache --really-force コマンドを使用してキャッシュを再構築することをお勧めします。fc-match コマンドを使用して、マッチング結果をテストできます。「monospace」 は一般的な font family 名であり、「sans-serif」 と 「serif」 などの存在しない名もあります。

特定のフォントの後に fallback ロジックを追加することで、最初の問題である Emoji の正しい表示方法を修正できます。

~/.config/fontconfig/fonts.conf ファイルを編集し、以下の内容を追加してください。

<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
  <match target="pattern">
    <test name="family" compare="eq" ignore-blanks="true">
      <string>Fira Code</string>
    </test>
    <edit name="family" mode="append">
      <string>Noto Color Emoji</string>
      <!-- <string>Twemoji</string> -->
    </edit>
  </match>
</fontconfig>

このように、「Fira code」 フォントを使用するたびに、「Noto Color Emoji」 を後ろに追加して、複合フォントを形成することができます。Linux プラットフォームでの Emoji フォントには、いくつかの選択肢があります。以下はいくつかの例です。

  • yay -S ttf-apple-emoji

  • yay -S noto-fonts-emoji

  • yay -S ttf-twemoji

  • yay -S ttf-joypixels

Discussion