パスワードを忘れた? アカウント作成
13851478 journal
日記

m_nukazawaの日記: TrueTypeフォントフォーマット 生成と所感 2

日記 by m_nukazawa

同人誌「ゼロから作るTrueTypeフォントファイル」を4月の技術書典6で出す予定なので本の前にコードを書いている。
目標はドロー・ペイント系等びアプリで読めるフォントファイルを生成する方法を同人誌にすること。

少し前まで行き詰まってフォーマット解析を兼ねてafdko(ttxdump)の気の利いたクローンを書いていた。
今は字形を含む生成ファイルがFontForgeで開けるようになった。
これから、足りないTableを足せばUbuntuフォント管理などで読めるファイルになるのではないかと考えている。
本には最低限FontForge以外で読める状態のファイルの作り方までは収録したい。

以下、フォーマットへの所感など。
まとめていない雑文なので興味のある向きへ。

フォントファイルの仕様(以下SPEC)はMSとAppleからそれぞれ(以下MSSPECとAppleSPEC)公開されている。英語。Adobeも公開しているらしいが追っていない。
MSSPECがOpenType、AppleSPECがTrueType。
日本語情報は読んでみたというのがブログで有る。
ターゲットはTrueTypeとしたが、主にMSSPECを読んでいる。
TrueTypeなのはOpenTypeにはOS/2Tableという如何にもな歴史的経緯と、PostTableという厄介そうな字形テーブルが必要で、これらを扱わなくて済みそうと判断したため。
OpenTypeのSPECはTrueTypeのSPECをまるごと含んでいる、らしい。

名前が付いていない概念もあり、開発の便宜的にこちらで独自に名前を付けているものがある。例えば以下で要素とか属性とか言っているのがそれ。

#
収録文字数・字形などプロパティ毎にTableというデータ構造が定義されている。
フォントファイルは大まかにはTableバイト列を繋げたもの。
ファイルの先頭に収録Tableを索くためのインデックスが置かれている。
ビッグエンディアン。

#
ある要素の情報が、構造体配列ではなく各配列に分散(MSSPECではparallel array)して置かれている。
例えばCmapTable内のSubTable要素すごく雑に書くとこういう感じ。
### 構造体配列版
```
CmapSubtable{int startCode, int stopCode};
CmapTable{
        CmapSubtable subtables[12];
};
```
### parallel array版
```
CmapTable{
        int CmapSubtable_startCode[12];
        int CmapSubtable_stopCode[12];
};
```
バイナリ生成がやりづらい。属性毎のテーブルを個別の一時バッファに作って最後に連結する。
8番目のsubtableを取り出す、という場合は属性をそれぞれ取りに行かなければならない。
CPUキャッシュにも乗りずらくなると思うのだが、昔はこれが良かった理由があったのだろうか?

要素数により配列の末尾でない要素のbyte長が変わる。
バイナリ表現をマップした構造体で取り回すことはできない。

#
上記のparallel arrayに加えて、単純な辞書やflagを用いた圧縮がある。
今回は(開発中の)拡張性と汎用性を意図して、要素列は後から追加していけるデータ構造になるよう書いている。
これとエンディアン変換があるため、バイナリ生成の前段に中間表現を用意してやる必要がある。

# 他にデータキャッシュがある。log()や、あるいは*2程度の演算をすれば他の属性値から生成できる値が、検索の高速化を目的に収録されている(とMSSPECには書いてある)。
# reserve(予約)やset X(値Xに固定)、deprecated(廃止)、があちこちに含まれている。歴史的経緯。
# いちばんすごいのはGlyfTable(typoではない)の字形データフォーマット。圧縮のために読み書きの面倒な作りになっている。同じ配列内で要素のByte数すら異なる。
# 変な固定小数点数がある。(単に自分の不勉強では?)

開発にはC言語を使っている。使い慣れている言語の中で、ビット・バイト操作が楽なので。
エンディアン変換のヘルパは用意しておくとよい。(32bit変数と16bit配列)

ByteArrayという名前を付けてuint8_tの配列でデータを生成している。
lengthやoffsetもよく使うので、後ろの方のデータ部ByteArrayを先に作ってからヘッダ部ByteArrayを作る、最後に連結する、という手順になる。

# まとめ
こんなことしている場合じゃないのだけれど。みんなもやろうフォントファイルバイナリ生成。

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
  • by Anonymous Coward on 2019年03月03日 22時05分 (#3574172)

    恐らく今回の対象外でしょうが、ヒンティングがまた面倒臭かった記憶があります。

    フォント作る側の立場では、SVGフォントがシンプルでいいですね。反面、機能不足でWebフォントとしても普及しませんでしたが。

    • 絵文字がそちら側らしいという話を聞いていたのでSVGフォントがやりたかったのですが、OpenType側のようだったので今回は諦めた次第です。

      ヒンティングは将来的にもやらないかなと思っています。自分には用途がないため。
      TrueType命令が広いプラットフォームで使えればいろいろしてみたかったです。

      親コメント
typodupeerror

人生の大半の問題はスルー力で解決する -- スルー力研究専門家

読み込み中...