top page > PC unix > here

firefox における日本語フォント


概要

目的は次のようなものです.

  1. firefox がどのように日本語フォントを得ているか,またそれをいかにして指定するかを示す.
  2. TrueType Font において embedded bitmap を使用しない方法を示す.

対象は次のものです.

  1. PC は PC-98 および AT 互換機 です.
  2. OS は FreeBSD (7.4, 8.2, 8.3, 8.4, 9.3, 10.3) です. (比較のために 7.2 にも言及します.)
  3. firefox は 3.5, 4.0, 10.0, 20.0, 26.0, 47.0 です. (比較のために 2.0 にも言及します.)

目次

1. 背景
2. 日本語フォントの制御
2.1 日本語フォントの選択
2.2 FreeBSD 7.2
2.3 FreeBSD 7.4
2.4 FreeBSD 9.3, 10.3
2.5 副作用について
3. embedded bitmap の抑制
4. 資料
4.1 pango
4.2 cairo
4.3 freetype2

1. 背景

FreeBSD 7.2 + firefox 2 から FreeBSD 7.4, 8.2 + firefox 3.5, 4 に移行したら,IPA FONT の表示が美しくなくなりました. FreeBSD 8.3 + firefox 10.0 や FreeBSD 8.4 + firefox 20.0, 26.0 でも同様です. 明朝体はかすれが目立つようになりました. (「す」の右上とか半角 B, D の水平部分とか.) また,ゴシック体は文字の太さが揺れるようになりました.

その原因は firefox の version の違いではなく,フォントを fontconfig で管理するようになったことです. この問題は次の二つの対策を施せば解決することができます. すなわち,

  1. Open Type Font でなく TrueType Font を使うようにする.
  2. TrueType Font の embedded bitmap を使わないようにする.

(注)「問題」とか「解決」とか書くと,現状のままでは使えないような印象を与えかねませんが,そうではありません. 選択する font Size (私は 16 point) やモニターの大きさ等に依るでしょう.

それと,「IPA の Open Type Font が美しくない」と言っているのではなく,あくまで現在の freetype2 を経た画面表示に限定した話です.

実際に文字がどう表示されているかを種々の環境を用意することなしに確認するには,次のようにします.

1. firefox で使うフォントを用意する.
  IPA の TrueType Font ipam.ttf, ipag.ttf および Open Type Font ipam.otf, ipag.otf を用意する.
  FreeBSD 7.2 では ja-ipa-ttfonts-1.0.20060520.p1_2,2 を導入すれば,以下のフォントが得られます.

/usr/local/share/ipa-ttfonts/fonts/ipamp.ttf
/usr/local/share/ipa-ttfonts/fonts/ipam.ttf
/usr/local/share/ipa-ttfonts/fonts/ipagui.ttf
/usr/local/share/ipa-ttfonts/fonts/ipagp.ttf
/usr/local/share/ipa-ttfonts/fonts/ipag.ttf

また FreeBSD 7.4, 8.2, 8.3, 9.3, 10.3 では ja-font-ipa-0030? を導入すれば,以下のフォントが得られます.

/usr/local/share/font-ipa/ipamp.otf
/usr/local/share/font-ipa/ipam.otf
/usr/local/share/font-ipa/ipagp.otf
/usr/local/share/font-ipa/ipag.otf

二つを見比べるためには両方のフォントを工面する必要がありますが,ports から同時に両方を導入できるわけではありません. 一方は ports から導入し,もう一方は packages を自分で解凍して cp するのが合理的です.

2. ports/print/ft2demos を導入する.
  これには freetype2 の使用例となる種々のプログラムが含まれています. その中の ftview を使います.

3. フォントを表示する. font file のある directory に行き,次のようにする.

% ftview                ← 使用法が表示される.
% ftview 16 ipam.ttf    ← ゴシックや Size 10 も試して下さい.
% ftview 16 ipam.otf

数字はフォント の "point size" であり,firefox にて規定している font Size に一致します.
  表示画面がアクティブな状態で [SPACE] キーを打てば表示されるフォントが変わります. [q] キーを打てば終了します.

*.ttf が FreeBSD 7.2 + firefox 2 の文字の表示に,*.otf が FreeBSD 8.2 + firefox 3.5 以降の文字の表示に対応します.

なお,確信はありませんが以下に記す方法が唯一無二とも思えません. dot file にてすべてが制御できれば一番楽なのですが.

2. 日本語フォントの制御

2.1 日本語フォントの選択

firefox において,日本語フォントは default では (私にとって) 出所不明のフォントが使われています. 日本語フォントは以下のようにして選択することができます.

Edit
→ Preference
→ Content
→ Font & Colors
→ Advanced...
→ fonts for: メニューから Japanese を選択する.メニューから四通りのフォントと二通りの Size を選択する.

FreeBSD 7.2 でも 7.4, 8.2, 8.3, 8.4, 9.3, 10.3 でも,firefox のメニューは同じ「IPA 明朝」,「IPA ゴシック」です. しかし,前者は TrueType Font に,後者は Open Type Font に対応しています.

2.2 FreeBSD 7.2

FreeBSD 7.2 においては,ja-ipa-ttfonts-1.0.20060520.p1_2,2 を導入すると,それらは /usr/local/share/ipa-ttfonts/fonts/ に置かれ,かつ /usr/X11R6/lib/X11/fonts/TrueType/ にそれらの symbolic link が作られます.

また,IPA とは別のフォントのために /usr/local/lib/X11/fonts/OTF/ も作成されます. FreeBSD 7.2 の環境で IPA の Open Type Font を使うならここに置けば良いのでしょうが,試しておりません.

2.3 FreeBSD 7.4

FreeBSD 7.4, 8.2, 8.3, 8.4 では ja-font-ipa を導入すると,それらは /usr/local/share/font-ipa/ に置かれ,/usr/local/share/fonts/std.ja_JP/ にそれらの symbolic link が作られ,さらに /usr/local/lib/X11/fonts/OTF//usr/local/share/fonts/std.ja_JP/ への symbolic link が作られます.

また,ja-font-mplus-ipa を導入すると,それらは /usr/local/share/font-mplus-ipa/fonts/ に置かれます. これは IPA の TrueType フォントです.

また,IPA とは別のフォントのために /usr/local/lib/X11/fonts/TTF が作成されます. TrueType Font を cp するなら,そこでも良いですし,/usr/local/lib/X11/fonts/TrueType 等を mkdir してそこに置いても良いです. ただし,そのようにしても firefox のメニューに二つの選択肢が現われるわけではなく,(拡張子以外は) 同名の Open Type Font しか選択できません.

TrueType Font の方を使いたいのであれば,/usr/local/lib/X11/fonts/OTF/ から IPA Open Type Font を消します. 私は以下のようにしております.

# cd /usr/local/lib/X11/fonts
# cp -pR OTF ..     ← backup を残す.
# cd OTF
# rm ipa*.otf
# vi fonts.dir      ← ipa*.otf 関連の記述を消す.
# vi fonts.scale    ← 同上.(おそらく修正は不要です)

firefoxfontconfig にて,TrueType Font を Open Type Font よりも優先するように修正ができれば,もっと合理的なのですが.

FreeBSD 8.3, 8.4 においては,上記の変更に加えて /usr/local/etc/fonts/fonts.conf を以下のように変更する必要があります.

--- fonts.conf.orig     2012-04-20 20:24:39.000000000 +0900
+++ fonts.conf  2012-05-03 21:01:41.000000000 +0900
@@ -23,7 +23,7 @@

 <!-- Font directory list -->

-       <dir>/usr/local/share/fonts</dir>
+       <!--dir>/usr/local/share/fonts</dir-->    ← この行を消しても良い.
        <dir>/usr/local/lib/X11/fonts</dir>
        <dir>~/.fonts</dir>

FreeBSD 8.3 においてはさらに,freetype2 2.4.7 を用いて ipag.ttf を 16 dot で表示すると,半角の英数字の大きさが不揃いになります. 特に 1 や 5 の文字の背が低いです. (FreeBSD 8.4 + freetype2 2.4.11 でも同様です. 18 dot ならばこの問題は生じません. また ipam.ttfipagp.ttf ならば大丈夫です.)

FreeBSD 7.4, 8.2 と同じ freetype2 2.4.4 を用いたら解決しました. この問題は 2.4.5 から生じ,現時点で最新の 2.4.9 でも解決しておりません.
(補足) 2014.1.12 の時点で最新の ports の freetype2 2.5.2 ではこの問題は解決しております.

以下のように修正すれば,この問題は生じません.

--- src/base/ftobjs.c.orig      2012-02-11 18:29:31.000000000 +0900
+++ src/base/ftobjs.c   2012-05-04 17:56:50.000000000 +0900
@@ -636,17 +636,22 @@
       else
       {
         FT_Render_Mode  mode = FT_LOAD_TARGET_MODE( load_flags );


+#ifndef AAA  ← 2.4.4 では以下のようにしている.
+        if ( mode == FT_RENDER_MODE_LIGHT             ||
+             face->internal->ignore_unpatented_hinter )
+#else       ← 2.4.5 からは以下のようになっている.
         /* the check for `num_locations' assures that we actually    */
         /* test for instructions in a TTF and not in a CFF-based OTF */
         if ( mode == FT_RENDER_MODE_LIGHT                       ||
              face->internal->ignore_unpatented_hinter           ||
              ( FT_IS_SFNT( face )                             &&  ← ここから 3 行が原因.
                ttface->num_locations                          &&
                ttface->max_profile.maxSizeOfInstructions == 0 ) )
+#endif
           autohint = TRUE;
       }
     }

     if ( autohint )

2.4 FreeBSD 9.3, 10.3

FreeBSD 9.3, 10.3 では,X の導入においてフォントは /usr/local/share/fonts/ に置かれ,従来の置き場である /usr/local/lib/X11/fonts/ は作成すらされません.

また,ja-font を導入すると,それらは /usr/local/share/font-ipa/ に置かれ,/usr/local/share/fonts/std.ja_JP/ のみにそれらの symbolic link が作られます.

ja-font-mplus-ipa に関しては前節と同じです.

/usr/local/etc/fonts/fonts.conf を以下のように修正します. すなわち,「/usr/local/share/fonts/ の下すべて」の設定を改め,OTF を避けて各々を名指しで指定するようにします. (より古い FreeBSD でも,このやり方は有効かもしれません.)

--- fonts.conf.orig     2016-07-03 10:05:36.774162000 +0900
+++ fonts.conf  2016-08-06 16:18:03.920982000 +0900
@@ -23,8 +23,11 @@

 <!-- Font directory list -->

-       <dir>/usr/local/share/fonts</dir>
-       <dir>/usr/local/lib/X11/fonts</dir>
+       <!--dir>/usr/local/share/fonts</dir-->      ← この行を消しても良い.
+       <dir>/usr/local/share/fonts/TTF</dir>
+       <dir>/usr/local/share/fonts/dejavu</dir>
+       <dir>/usr/local/share/fonts/TrueType</dir>  ← ここに ipa?.ttf を置く.
+       <!--dir>/usr/local/lib/X11/fonts</dir-->    ← この行はもう不要である.
        <dir prefix="xdg">fonts

2.5 副作用について

firefox 以外にも fontconfig を利用しているプログラムはありますので,上記のような自前の変更を行なう場合には副作用を考慮する必要があります. 例えば,emacs もフォントとして IPA を選択すれば firefox と同じものが表示されます.

私としては,少なくとも今のところは ghostscript が Open Type を,それ以外は TrueType を使えるようになれば良いので, 副作用の点検もその範囲内でしか行ないません.

3. embedded bitmap の抑制

TrueType Font や Open Type Font には,embedded bitmap が組み込めるようになっています. IPA Font に関しては,

  1. TrueType Font には embedded bitmap が組み込まれている.
    明朝のそれはゴシックのような書体だし,ゴシックのそれも丸っぽい書体であり,あまり美しくない.
  2. Open Type Font に embedded bitmap は組み込まれていない.(たぶん.)

前節のように TrueType Font を使うようにしても,FreeBSD 7.2 と 8.2 とでは firefox の表示に差異が生じます. すなわち,

FreeBSD 8.2 における対策として,以下のことが考えられます. (ここでは別のフォントを使うことは考えない.)

  1. embedded bitmap は 10, 12, 16dot なので,そこを避けるようにフォントの大きさを選ぶ.(それでも完全に避けることはできない.)
  2. ipa*.ttf から embedded bitmap を削る.
  3. embedded bitmap を使わないように,firefox および関連する library を直す.

ここでは最後の選択肢を追求します. TrueType font の表示の流れは firefoxpangocairofreetype2 と複雑です.

ソースを追ってみたのですが,firefox から pango 以下を制御して embedded bitmap を使わないようにすることはできないようです.[1] また,pango からの制御も容易ではないようです. ここまでで embedded bitmap を使用するか否かの制御は行なわれておらず,「下流」の default の設定に任せています. 従って,cairo, freetype2 のいずれかを修正することになります.

[1] firefox から制御できることが分かりました. 詳細はこの節の末尾を御覧下さい.

以下のどちらか一方の修正を行なえば,embedded bitmap を使わないようになります. 現在,私のところでは前者の修正を行なって副作用の有無を検討中です.

ports/graphics/cairo/ は以下の修正を行ないます.

--- src/cairo-ft-font.c.orig    2010-12-25 23:21:34.000000000 +0900
+++ src/cairo-ft-font.c 2011-05-15 14:21:17.000000000 +0900
@@ -1580,7 +1580,7 @@
 #endif

     _cairo_font_options_init_default (&ft_options.base);
-    ft_options.load_flags = FT_LOAD_DEFAULT;
+    ft_options.load_flags = FT_LOAD_NO_BITMAP;
     ft_options.extra_flags = 0;

 #ifndef FC_EMBEDDED_BITMAP

ports/print/freetype2/ は以下の修正を行ないます.

--- src/truetype/ttdriver.c.orig        2010-02-07 15:21:26.000000000 +0900
+++ src/truetype/ttdriver.c     2011-05-15 17:51:39.000000000 +0900
@@ -330,6 +330,8 @@
         load_flags |= FT_LOAD_NO_HINTING;
     }

+    load_flags |= FT_LOAD_NO_BITMAP;
+
     /* now load the glyph outline if necessary */
     error = TT_Load_Glyph( size, slot, glyph_index, load_flags );

FreeBSD 7.2 の環境で,なぜ embedded bitmap が使われないのかは,謎のままです. そのうち追求してみます. (ftview の結果に差異はないので cairo 以外に考えられないのですが.)

(2012.7.27) 以下の内容の ~/.fonts.conf を作成すれば,cairofreetype2 を修正する必要はありません.

<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
    <match target="font">
        <edit name="embeddedbitmap" mode="assign"><bool>false</bool></edit>
    </match>
</fontconfig>

4. 資料

この節は未完成です. 現在は自分用のメモをさらしているだけです.

以下に FreeBSD 8.2 における ports のソースを抜粋します.

4.1  pango

ソースは /usr/ports/x11-toolkits/pango/work/pango-1.28.3/pango/ 以下に展開されます.
pangocairo-fcfont.c

static void pango_cairo_fc_font_class_init()
{
  font_class->get_glyph_extents = pango_cairo_fc_font_get_glyph_extents;
}

static void pango_cairo_fc_font_get_glyph_extents(font,,,)
{
   _pango_cairo_font_private_get_glyph_extents(font->cf_priv,,,);
}

pangocairo-font.c

void _pango_cairo_font_private_get_glyph_extents(cf_priv,,,)
{
   _pango_cairo_font_private_get_glyph_extents_cache_entry(cf_priv,);
}

static PangoCairoFontGlyphExtentsCacheEntry *
_pango_cairo_font_private_get_glyph_extents_cache_entry(cf_priv,)
{
   compute_glyph_extents(cf_priv,,);
}

static void compute_glyph_extents(cf_priv,,)
{
   cairo_scaled_font_glyph_extents(
      _pango_cairo_font_private_get_scaled_font(cf_priv),,,);
}
   | find where option set.
   +-----+---------+---------+---------+---------+---------+---------+
   | pangocairo-font.c
   | cairo_scaled_font_t * _pango_cairo_font_private_get_scaled_font()
   | {
   |    cairo_scaled_font_create();
   |    ここでの load_flags の初期化は上流から制御できない.
   | }
   | from where ?
   | _get_pattern_ft_options()

4.2  cairo

ソースは /usr/ports/graphics/cairo/work/cairo-1.10.2/src/ 以下に展開されます.
cairo-scaled-font.c

void cairo_scaled_font_glyph_extents(scaled_font,,,)
{
   _cairo_scaled_glyph_lookup(scaled_font,,CAIRO_SCALED_GLYPH_INFO_METRICS,);
}

cairo_int_status_t
  _cairo_scaled_glyph_lookup(scaled_font,,info,) cairo-scaled-font.c
{
   need_info = info & ~scaled_glyph->has_info;

   引数の info の方は定数である.
   scaled_font->ft_options.load_flags の方は _get_pattern_ft_options()
   で設定されているのだが,結果として 0 (FT_LOAD_DEFAULT) である.

   scaled_font->backend->scaled_glyph_init(scaled_font,,need_info);
}

cairo-ft-font.c

_cairo_ft_scaled_glyph_init(abstract_font,,info)
{
   load_flags = abstruct_font->ft_options.load_flags;

   info       : firefox を使った限り,常に 1 or 2 である.
                これを制御して以下の if にかかるようにするのは困難である.
   load_flags : firefox を使った限り,常に 0 である.
                上流で制御するなら,こちらの方が見込みがありそうだが,
                firefox からの制御は困難または不可能である.

   if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 &&
       (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) == 0)
      load_flags |= FT_LOAD_NO_BITMAP;

ここで load_flags |= FT_LOAD_NO_BITMAP; としても,今のところ副作用はない.
→ 現在,_get_pattern_ft_options() にて対応したものを試行中.

   FT_Load_Glyph(,,,load_flags);
}

info : CAIRO_* で始まる.
load_flags : FT_* で始まる.

4.3  freetype2

ソースは /usr/ports/print/freetype2/work/freetype-2.4.4/src/truetype/ 以下に展開されます.
ttdriver.c

static FT_Error Load_Glyph(,,,load_flags)
{

ここで load_flags |= FT_LOAD_NO_BITMAP; としても,今のところ副作用はない.
これは現在 _get_pattern_ft_options() の方で対応しており,freetype2 は
修正なしで使っている.

   TT_Load_Glyph(,,,load_flags);
}

ttgload.c

FT_LOCAL_DEF( FT_Error ) TT_Load_Glyph(,,,load_flags)
{
   load_flags : FT_LOAD_***
}

pangocairo-font.c

_pango_cairo_font_get_metrics()
{
   font_options = cairo_font_options_create();

   pango_cairo_context_set_font_options();
}

_pango_cairo_font_private_get_hex_box_info()
{
   font_options = cairo_font_options_create();

   pango_cairo_context_set_font_options();
}

_pango_cairo_font_private_initialize()
{
   cf_priv->data->options = cairo_font_options_copy();
}

_pango_cairo_font_get_metrics()
{
   font_options = cairo_font_options_create();

   pango_cairo_context_set_font_options();
}

_pango_cairo_font_private_get_hex_box_info()
{
   font_options = cairo_font_options_create();

   pango_cairo_context_set_font_options();
}

_pango_cairo_font_private_initialize()
{
   cf_priv->data->options = cairo_font_options_copy();
   cf_priv->is_hinted = cairo_font_options_get_hint_metrics();
}

pangocairo-context.c :

pango_cairo_context_set_font_options()
{
   cairo_font_options_copy();
}

cairo-font-options.c :

cairo_font_options_create()
{
   _cairo_font_options_init_default();
}

_cairo_font_options_init_default (cairo_font_options_t *options)
{
    options->antialias = CAIRO_ANTIALIAS_DEFAULT;
    options->subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
    options->lcd_filter = CAIRO_LCD_FILTER_DEFAULT;
    options->hint_style = CAIRO_HINT_STYLE_DEFAULT;
    options->hint_metrics = CAIRO_HINT_METRICS_DEFAULT;
}

cairo_font_options_copy()
{

}

cairo-ft-font.c :

_cairo_ft_font_face_get_implementation()
{
   _cairo_ft_resolve_pattern();
}

_cairo_ft_resolve_pattern()
{
   _get_pattern_ft_options();
}

or

_cairo_ft_font_face_create_for_toy()
{
   _cairo_ft_font_face_create_for_pattern();
}

_cairo_ft_font_face_create_for_pattern()
{
   _get_pattern_ft_options();
}

_get_pattern_ft_options()
{
   ft_options.load_flags = FT_LOAD_DEFAULT;
   ここを FT_LOAD_NO_BITMAP にして副作用がなければ,ここが良いかも.
→ とりあえず,こちらで試用を続ける.

   /* Check whether to force use of embedded bitmaps */
    if (FcPatternGetBool (pattern,
                          FC_EMBEDDED_BITMAP, 0, &bitmap) != FcResultMatch)
       bitmap = FcFalse;
    ここを常に FcFalse になるようにしても,反映されるかは antialias 次第.

    if (antialias) {
        /* Force embedded bitmaps off if no hinting requested */
        if (ft_options.base.hint_style == CAIRO_HINT_STYLE_NONE)
          bitmap = FcFalse;

        if (!bitmap)
            ft_options.load_flags |= FT_LOAD_NO_BITMAP;
    }
}

(参考) firefox 4 のソースにある方の freetype2 は FreeBSD では使われません.