Tofu issue 日本語フォントの表示 - Kivy Advent Calendar 2013

さて、Kivyで一番残念に思うのは日本語がトウフになることでしょう。

多くのプラットフォームは日本語フォントを持っていますし、Androidも4.0からは日本語フォントがシステムフォントとして取り込まれています。しかし、いくら日本語フォントを持っていても、Kivyは現在「システムフォントを取得する仕組みがなく」「日本語グリフのないフォントをデフォルトにしている」ために、ウィジェットごとにフォントを指定しないと日本語が表示できません。

http://blog.logicdesign.jp/entry/2012/12/07/003711
http://supportdoc.net/support-kivy/03jp.html

一応開発チームもこの問題に対応しようとしていて

https://github.com/kivy/kivy/tree/unicode_textinput

みたいなブランチを切っていますけど... あまりテストできていない?

対策

個人的には次の方法で対策をしています。

(fonts_ja.py)

from kivy.resources import resource_add_path
from kivy.core.text import LabelBase, DEFAULT_FONT
from kivy.utils import platform

def add_paths(*paths):
    for p in reversed(paths):
        resource_add_path(p)

def set_regular(family, *filenames):
    for f in filenames:
        try:
            LabelBase.register(family, f)
            break
        except IOError:
            continue
    else:
        raise IOError, 'No appropriate fonts for Kivy UI'

_platform = platform()
if _platform is 'android':
    add_path('/system/fonts', '/data/fonts')
    set_regular(DEFAULT_FONT,
        'DroidSansJapanese.ttf',
        'MTLmr3m.ttf',
        'MTLc3m.ttf',
        'DroidSansFallback.ttf',
    )

elif _platform is 'ios':
    add_path('/Library/Fonts')
    set_regular(DEFAULT_FONT,
        'Osaka.ttf',
        'OsakaMono.ttf',
    )

elif _platform is 'linux':
    add_path('/usr/share/fonts/truetype/ipafont', '/usr/local/share/font-ipa')
    set_regular(DEFAULT_FONT,
        'ipagp.ttf', # IPAfont (http://ipafont.ipa.go.jp/)
        'ipagp.otf', # IPAfont (http://ipafont.ipa.go.jp/)
    )

elif _platform is 'macosx':
    add_path('/Library/Fonts', '/System/Library/Fonts')
    set_regular(DEFAULT_FONT,
        'Hiragino Sans GB W3.otf',
        'Osaka.ttf',
        'OsakaMono.ttf',
        'AppleGothic.ttf',
    )

elif _platform is 'win':
    add_path('c:/Windows/Fonts')
    set_regular(DEFAULT_FONT,
        'VL-Gothic-Regular.ttf', # ProjectVine (http://vlgothic.dicey.org/)
        'meiryo001.ttf',         # separated from meiryo.ttc with unitettc.exe
        'msgothic001.ttf',       # separated from msgothic.ttc with unitettc.exe
        'ipagp.ttf',             # IPAfont (http://ipafont.ipa.go.jp/)
    )

else:
    raise IOError, 'Unknown platform: %s' % _platform

各プラットフォームごとに検索パスと日本語フォントファイル名を用意して、一致したものがあればLabelのベースクラスのデフォルトフォントとして登録することで、LabelだけでなくTextInput、Buttonなどのウィジェットについても日本語が表示されることになります。

(/sdcard/kivy/font/)

android.txt Androidの場合必要
fonts_ja.py 上記参照
main.py 下記参照
docutils/ docutilsを丸ごと入れる (RstDocumentを動かすため)

(android.txt)

title=tofu
author=cheeseshop
orientation=landscape

(main.py)

# -*- coding:utf-8 -*-
from kivy.app import App
from kivy.uix.carousel import Carousel
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.rst import RstDocument
import fonts_ja

class FontsApp(App):

    def build(self):
        carousel = Carousel()
        carousel.add_widget(Label(text=u'Labelウィジェットに日本語を表示する'))
        carousel.add_widget(Button(text=u'Buttonウィジェットに日本語を表示する'))
        carousel.add_widget(TextInput(text=u'TextInputウィジェットに日本語を表示する'))
        carousel.add_widget(RstDocument(text=u'''\
==========================================
RstDocumentで日本語を表示
==========================================

見出し1
                                      • -
本文1 見出し2
                                      • -
次の個所はトウフになる :: 等幅フォントを表示しようとするとTofu Problem ''')) return carousel if __name__ == '__main__': FontsApp().run()

まとめると、

  • Kivyは「日本語が扱えない」のではなく「システムフォントが分からない」。日本語フォントを指定すれば表示はできる。
  • 一つ一つ指定しなくても、LabelBase.register で設定すればほとんどのウィジェットに表示できる。

この対策の問題点としては

  • TTCフォントを指定できない
    • TTCフォントは、breakttcやunitettcといったツールでTTFに分解すれば使えるようになります。Windowsで指定している「meiryo001.ttf」というのは、meiryo.ttcから分解して作ったフォントファイルです。
  • ボールド、イタリックも同じフォントが使われる
    • 日本語ファイルは必ずしもボールドが用意されていないし、2つ登録するのも面倒なのでここでは端折ってます...
  • 等幅フォントの個所だけ日本語表示できない
    • 後で紹介しますが、reStructuredTextを表示するRstDocumentウィジェット等幅フォントを表示するところで「DroisSansMono.ttf」を指定しているのでそこだけトウフになってしまいます。この対応についてはまた後程...

自分のNexus7-2013ではモトヤマルベリ(/system/fonts/MTLmr3m.ttf)が表示できていますが、例によって他のプラットフォームは確認していないです。
ところで、IPAフォントを積んでいるAndroid端末ってあったりしますか?
他にも何か情報があったらよろしくです。