読者です 読者をやめる 読者になる 読者になる

にせねこメモ

はてなダイアリーがUTF-8じゃないので移ってきました。

TTXでAppleカラーフォントを作る

フォント

TTX/FontTools が Version 2.5 から Apple カラーフォントをサポートしているようなので、これを使ってAppleカラーフォントを試作してみた。以下メモ。

動作例

Mac OS X Yosemite のテキストエディットで使用してみた例。
左が作成したnxTokiACF.ttf、右がHelveticaです。Aしか実装していないのでAだけ。
f:id:nixeneko:20150607012809p:plain

サンプルファイル

GitHubレポジトリとしてアップロードしました。

output/nxTokiACF.ttf が出力されたフォントです。

フォントのビルドの仕方

Cygwin上でビルドしています。他の環境でもおそらくできるはず。

  1. 次のものを使える状態にする。
  2. Makefile を開き、TTXのコマンド TTXCMD とPythonのコマンド PYTHONCMD を適切に書き換える。
  3. コマンドラインから、ディレクトリに移動して make する。

作成方法

流れとしては、まずひな形となるTTFフォントをFontForgeなどで出力し、それを TTX で XML ファイルに出力する。そして出力されたXMLファイル(.ttx)を編集してカラービットマップを追加し、それを TTX でTTFフォントにコンパイルする。

使うもの

以下の手順ではこれらのツールにパスが通っているものとする。

また、カラービットマップの設定については Apple Color Emoji.ttf を参考にするとスムーズにできるかと。次の場所にあります。

  • /System/Library/Fonts/Apple Color Emoji.ttf

Appleカラーフォントとsbixテーブル

カラーフォントのビットマップデータは 'sbix' テーブルに格納される。
sbix テーブルの詳しい説明は次の Apple のページ参照


必要そうなところだけまとめる次の図のようになっている。らしい。
f:id:nixeneko:20150606235224p:plain

  • ‘sbix’テーブルの下にいくつかの strike データレコードがくる。
  • strike は ppem (PPEMを表す)、resolution (画像の解像度)、多数の glyph データレコードを含む。
    • PPEMは画面のdpiとフォントのポイント数によって決まる数値で、
      ppem = pointSize * dpi / 72
      で求められる。ppemとresolutionの組み合わせごとにstrikesがつくられる。
    • dpiが72でppemを正方形の画像の一辺のサイズにすると、画像の一辺がemの大きさになるようだ?
      • Apple Color Emoji ではつぎの様なppem, dpiの組み合わせのstrikeがあった
ppem 20 32 40 48 64 96 160
dpi 72 72 72 72 72 72 72
画像サイズ 20x20 32x32 40x40 48x48 64x64 96x96 160x160
  • glyph データレコードは次のものからなる
    • 画像の左下の原点が画面上でどこに表示されるか指定するらしい originOffsetX, originOffsetY
    • 画像のエンコード形式を指定する graphicType (‘jpg ’, ‘pdf ’, ‘png ’, ‘tiff’のいずれか)
    • 画像データ(バイト列)
  • あるグリフに画像データがいくつかのstrikeの中の一つででも定義されていれば画像で表示され、どのstrikeの中でも定義されていなければアウトラインで表示されるらしい。
    • …が現在のMac OS Yosemiteでは実際には常にアウトラインが(定義されていれば)表示される。

手順

というわけで、実際にフォントをつくってみる。Aをカラービットマップで表示するようにする。

画像の用意

次の画像を用意した。サイズは512x512。
f:id:nixeneko:20150607003719p:plain

ひな形の作成

まずひな形となるTTFフォント nxTokiACF_base.ttf をFontForgeで作成した。作成方法の詳細は省略。
Units/EMを800に指定した。グリフについてはAに800の幅を設定したのみ。フォントの名前などを適当に設定。など。

次に TTX でTTFフォントをXMLファイル(.ttx)にダンプする。

ttx -o nxTokiACF.ttx nxTokiACF_base.ttf
XMLファイルの編集

出力されたXMLファイル nxTokiACF.ttx を編集する。

Apple Color Emoji.ttf に値を合わせるため hhea テーブルの ascent を 800 に、 descent を -250 に設定した。ただし合わせる必要があるのか分からない。要検証。

  <hhea>
    <tableVersion value="1.0"/>
    <ascent value="800"/>
    <descent value="-250"/>
    ...

他にも Apple Color Emoji.ttf を参考に設定をいじった部分があるが、あまりよく分かってない。


次にカラービットマップを追加する。これは 'sbix' テーブルによって設定されるので、それに従って作成する。
フォントが描画されるサイズによって表示される画像を変えることもできるが、面倒なので大きなサイズ(512x512)の画像一つだけにした。フォントの表示サイズによって表示されるビットマップを変えるには、ppemを変えたstrikeを他にも用意し、それらの中で対応する大きさのビットマップを設定するとよい。
strike について、dpiを72にし、ppemを画像サイズと同じにするとよさそうなので、512x512の画像と併せてppemを512としている。

次のようなXMLコードを挿入する。場所は<ttFont>~</ttFont>のタグの直下ならどこでも良さそうだが<gasp>~</gasp>の後においた。

  <sbix>
    <version value="1"/>
    <flags value="00000000 00000001"/>
    <strike>
        <ppem value="512"/>
        <resolution value="72"/>
        <glyph name=".notdef"/>
        <glyph name=".null"/>
        <glyph name="nonmarkingreturn"/>
        <glyph name="space"/>
        <glyph graphicType="png " name="A" originOffsetX="0" originOffsetY="0">
            <hexdata>
               (ここに16進ダンプが入ります)
            </hexdata>
        </glyph>
    </strike>
  </sbix>

「(ここに16進ダンプが入ります)」は実際にはPNG画像のバイナリデータを16進数の文字列にダンプしたものが入る。
この16進ダンプには次のようなPythonスクリプトを使って行うことができる。

# coding: utf-8
import binascii, sys

def dump(filename):
    with open(filename, 'rb') as f:
        bin = f.read()
        hexdump = binascii.hexlify(bin)
        print(hexdump)

if __name__ == '__main__':
    argvs = sys.argv
    if len(argvs) != 2:
        quit()
    else:
        dump(argvs[1])

ダンプ後の文字列は非常に長くなるので貼り付けた後はフォントの編集が面倒になる。適当に参照を書いておいて後でスクリプトで置換するなどするといいのではないかと思う。
実際に<hexdata>~</hexdata>の代わりに次の様に書いておき、Pythonスクリプトで16進ダンプに置換するようにした。

            <hexdata src="bitmaps/512/A.png"/>
コンパイル

編集したXMLファイルを TTX でTTFフォントにコンパイルする。

ttx nxTokiACF.ttx

するとTTFフォント nxTokiACF.ttf が出力される。
これを Mac OS X Yosemite などで開くとビットマップが表示され、カラーフォントとして動作するのがわかる。

課題、疑問点

  • Apple Color Emoji では Units/EM が 800, Ascender が 800, Descender が -250 となっている。フォントとして変な値に思うがどうしてこのような設定になっているのか。またそうしなかった場合何か不具合が生じるのだろうか。
  • ビットマップがどの位置に表示されるのか。アウトラインに何も設定しない場合、ビットマップの原点(左下端)がベースラインのやや下になるようだ。また、アウトラインを設定した場合、そのy座標の最小値よりもやや下に表示されているように見える。この下がる幅については詳細不明。要検証。
    • Apple Color Emoji をみるかぎり絵文字がビットマップで表示されるグリフに対しては glyf テーブルに左下(0,0)と右上(800,800)に点が打たれている。
  • Apple Color Emoji はビットマップがすべて正方形である。正方形でないビットマップを設定するとどうなるのだろうか。
  • Apple Color Font はWebフォントとして使用しようとするとブラウザに搭載されたサニタイザで 'sbix' の情報が削除されてしまうらしく、Webフォントでは使えないようだ。

その他