Fontconfig (8日目) - ヒンティング

文字をまともに描画するには何ピクセルぐらい必要でしょうか? 「書」という字は横に8本線があります。 線の間と上に飛び出てる部分含めて最低16px必要ということになります。 もちろん詰めたらであって実際には上下に余白がありますから18〜20pxは欲しいところです。 もっと画数の多い字でしたらもっと必要です。 それで辛うじて字形が表現できるだけですのでフォントの美しさを堪能するには更に倍は欲しいところです。 物理サイズでは同じ10.5ptであっても、印刷物やスマートフォンはDPIで300を超えますから40pxを超えてフォント本来の形が反映されます。 PCのディスプレイでは14pxとなり到底無理な話です。

グレイスケール化の様子

フォントの形状が各ピクセルをどう占めてグレイスケール化される様子は ftgrid で確認できます。 (Debian/Ubuntu系であればパッケージfreetype2-demosに含まれています。)

ftgridの様子(ヒンティングなし)

字形の線がどこを通るかで1ピクセル幅で濃く表示されるか2ピクセル幅で薄く表示されるかがばらついているのがわかります。

ここでヒンティングを有効にしてみます。

ftgridの様子(ヒンティングあり)

字形の線がピクセル境界に近づいて1ピクセル幅で濃く表示される箇所が増えました。 その代わりに字が下側に1ピクセル分縦長になっています。

ヒンティング

ヒンティングとは、字形をピクセル境界に沿って描画することで低解像度でもなるべくくっきりはっきりした表示にしようという技術です。 当然ながら文字の形状を歪めることになります。 そのため低解像度ではフォント本来の形状よりもヒンティングの質のほうが大事なのです。

TrueTypeフォントとOpenTypeフォントでフォント側が持っているヒント情報は異なり、TrueTypeフォントの方が細かな制御ができますがヒント情報を付ける難易度が高く、OpenTypeフォントは簡単にヒント情報を付けることができますが細かな制御はできずレンダラの裁量に任せることになります。

フォントを作るのでなければ関係ないと思われるかもしれませんが、ヒンティングを設定する際の注意点がTrueTypeとOpenTypeで異なったりもします。

FreeTypeのヒンティング

FreeTypeでは大まかに「ヒンティングなし」「フォントのヒント情報を使う」「light hinting」「auto-hinter」の4つのモードがあります。

auto-hinterはフォントのヒント情報を使わずにFreeTypeが独自にヒンティングしてくれます。

light hintingはFreeTypeのドキュメント On slight hinting, proper text rendering, stem darkening and LCD filters によりますと、TrueTypeフォントではauto-hinter、OpenTypeフォントでは縦方向のみのヒンティングを行うようです。

Fontconfigのヒンティング設定

Fontconfigではヒンティングは hintinghintstyleautohint の3つの属性で設定します。

だいたいこんな感じです。

hinting

hintstyle

autohint

FreeType

false

*

*

ヒンティングなし

true

*

true

auto-hinter

true

hintnone

false

ヒンティングなし

true

hintslight

false

light hinting​(TrueTypeはauto-hinter)

true

hintmedium​/hintfull

false

フォントのヒント情報を使う

6日目にフォント設定画面で「軽く(hintslight)」を避けて「中間(hintmedium)」を選んだのはauto-hinterを避けるためでした。

TrueTypeかOpenTypeかは fontformat 属性で判別できます。 TrueTypeであれば文字列 "TrueType"、OpenTypeであれば文字列 "CFF" になります。 OpenTypeフォントのみhintslightにするにはこんな感じでしょうか。

<!-- 省略 -->
<!-- この時点でhintstyleはhintmediumかhintfullに設定されているものとする -->
<match target="font">
 <test name="fontformat" compare="eq">
  <string>CFF</string>
 </test>
 <edit name="hintstyle">
  <const>hintslight</const>
 </edit>
</match>
<!-- 省略 -->

実例

こんな風に言葉でだけ説明してもわからないと思いますのでスクリーンショットを貼っていきます。 画像はぜひ等倍かそれ以上に拡大してご覧ください。

TrueTypeフォント代表としてIPA Pゴシック、OpenTypeフォント代表としてNoto Sans CJK JPをサンプルに用います。 (Debian/Ubuntu系であればパッケージfonts-noto-cjkとfonts-ipafont-gothicに含まれています。)

注意点としましてはKDE neonではNoto Sans CJK JPは /etc/fonts/conf.d/56-neon-noto.conf で強制的にhintslightにされます。

UbuntuではIPA Pゴシックは /etc/fonts/conf.d/65-fonts-ipafont-gothic.conf で強制的にhintnoneにされます。 (IPA明朝も同様に /etc/fonts/conf.d/65-fonts-ipafont-mincho.conf でされます。)

ですのでこれらのフォントのヒンティング設定を変えてみたい時は一時的にこれらのファイル、実際にはシンボリックリンクを削除しておく必要があります。

ちなみにDebianではこれらの設定ファイルはありません。

IPA Pゴシック

hintnone

IPA Pゴシック(hintnone)

Ubuntuでは 65-fonts-ipafont-gothic.conf により常にこの表示になります。

このようにgの下が切れるのはフォントに埋め込まれている行間設定が0になっているフォントにありがちです。 実際のところフォント側の行間設定は狭いほうが使いやすいですし、エディタ側の行間設定で回避できますので見逃してください。

autohint

IPA Pゴシック(autohint)

個々の字は綺麗に見えますが全体で見ると上下に暴れてベースラインも揃っていません。 主になるフォントとしてはちょっと使えませんね。

hintslight

IPA Pゴシック(hintslight)

TrueTypeフォントですので autohint をtrueにしたのと同じに見えます。

hintmedium

IPA Pゴシック(hintmedium)

IPA Pゴシックの持つヒント情報を使った本来の状態ですがautohint以上に暴れていて汚く見えます。 Ubuntuがhintnoneを強制しているのも納得です。

hintfull

IPA Pゴシック(hintfull)

hintmediumと同じに見えます。

注釈

IPA Pゴシックはヒントの質が悪いフォントの代表として使わせていただいた面もあります。 このようにヒンティングを行わないほうがマシなフォントというのは存在しますし、フォント毎の個別設定をする価値があります。

IPA Pゴシックの名誉のために書いておきますと16pxではヒント情報を使って綺麗に表示できます。 おそらく16px以外でヒント情報を使うことは想定されていないのだと思います。

IPA Pゴシック 16px(hintmedium)

ですので 65-fonts-ipafont-gothic.conf を16px以外の時のみhintnoneにするように修正してもよいのではないでしょうか。

こんな感じでしょうか……。

<!-- 省略 -->
<!-- この時点でhintstyleはhintnone以外に設定されているものとする -->
<match target="font">
 <test name="family" compare="contains">
  <string>IPA Pゴシック</string>
 </test>
 <test target="pattern" name="pixelsize" compare="not_eq">
  <double>16</double>
 </test>
 <edit name="hintstyle">
  <const>hintnone</const>
 </edit>
 <!-- autohintやembeddedbitmapも必要ならfalseにする -->
</match>
<match target="font">
 <test name="family" compare="contains">
  <string>IPA ゴシック</string>
 </test>
 <test target="pattern" name="pixelsize" compare="not_eq">
  <double>16</double>
 </test>
 <edit name="hintstyle">
  <const>hintnone</const>
 </edit>
 <!-- 同上 -->
</match>
<!-- 省略 -->

注意点としましてこの内容を ~/.config/fontconfig/conf.d/ 以下に置くと ~/.config/fontconfig/fonts.conf の方が後から実行されますので恐らくDEの設定に上書きされてしまって(また 65-fonts-ipafont-gothic.conf が存在する場合はそれにも上書きされてしまって)意味がないかもしれません。 フォント毎の設定はなるべく後ろに回す必要があります。

Noto Sans CJK JP

hintnone

Noto Sans CJK JP(hintnone)

Notoフォントファミリーに埋め込まれた行間設定はものすごい広いです。 フォールバックフォントとして他のフォントと混ざることも多いNotoですが、縦長故に目立ってしまうのが難点です。

hintslight

Noto Sans CJK JP(hintslight, rgba)

OpenTypeフォントですので縦方向のみのヒンティングが行われています。 元々縦長のNotoが更に全体的に縦長になりましたがラインが揃わなくなることもなくヒント情報の質の良さがうかがえます。

横方向はサブピクセルレンダリングで補えますのでヒンティングは縦方向だけでも充分綺麗ですね。

KDE neonでは 56-neon-noto.conf により常にこの表示になりますhintslightが強制されるとともに rgba 属性もnone(5)にされます。

KDE neonデフォルトの状態がこちらになります。

Noto Sans CJK JP(hintslight, none)

よくよく見ますとサブピクセルレンダリングされてませんよね?

$ fc-match -v 'Noto Sans CJK JP' | grep rgba
        rgba: 5(i)(w)
$ fc-match -v 'IPA Pゴシック' | grep rgba
        rgba: 1(i)(w)
$ fc-match -v 'Ubuntu' | grep rgba
        rgba: 1(i)(w)

こんなコメントがありますが、さて……。

56-neon-noto.conf より抜粋
   <!-- Turn on the native CFF hint -->
   <!-- Turn off sub-pixel anti-aliasing because Adobe's CFF
        rasterizer is for gray-scale rendering. -->

Noto開発者のお勧め設定はhintfullかつグレイスケール(サブピクセルレンダリングなし)のようですので、これを変に部分的に適用してしまった疑いが……。

hintslightであればサブピクセルレンダリングはしたほうが良いと思います。

KDE neonを使っていた時は 56-neon-noto.conf を消していたのですけれども更新の度に復活するのがうざくて、KDE neonをやめた理由のひとつでした。

hintmedium

Noto Sans CJK JP(hintmedium)

縦横共にヒンティングが行われた結果、横幅が変化する文字が確認できます。 hintslightの画像とこの画像をそれぞれ別のタブに等倍で表示して切り替えるとわかりやすいと思います。

このように文字の横幅はレンダリングの裁量で変化し得ます。

hintfull

Noto Sans CJK JP(hintfull)

hintmediumと同じに見えます。

autohint

Noto Sans CJK JP(autohint)

幸いアルファベットは上下に暴れてはいませんが「漢」「零」あたりはちょっと怪しいですね。

IPA Pゴシックもそうでしたが、FreeTypeのauto-hinterは上下に暴れる傾向があります。 文字単位で処理されていてフォント全体の整合性は気にされていない気がします。 ですので主になるフォントにauto-hinterは適用し辛いです。 フォールバックフォントとしていくつかの文字だけ使用するフォントに適用するならありなのですが。

macOSのフォントレンダリングがフォントの持つヒント情報を使用しないのは有名ですが、それでアンチエイリアスだけのぼやけたレンダリングであると思われているようです。 実際には(Retinaではない環境では)ごく軽いヒンティングは行われている……と私は思ってます。 小サイズで複数のフォントを並べてみますと高さが若干異なるはずのフォントであっても横の線が同一線上に並びどちらかが2ピクセルにまたがるようなことはないのが確認できるはずです。

この「macOSのヒンティング」は点や線を1ピクセル以上派手に移動させるようなことはないので文字が上下に暴れることもありません。 FreeTypeのauto-hinterもこれぐらい弱いほうが良いのですけどね……。

という雑談でした。

あと薄く表示されている気がします?