README.euc
NOTE: WRITTEN IN EUC-JP!

モナーフォント TTF 版の作成方法と解説, by 1@2ch
$Id: README.euc,v 1.2 2002/09/14 21:07:53 euske Exp $


このドキュメントでは TrueType フォントの変換や開発に興味のある方を
対象に、モナーフォントを TTF ファイルに変換する方法、
またこのために用いる一連のツールの簡単な使用法を説明します。
なお、UNIX と TrueType フォントに対するそれなりの知識を仮定しています。


0. 作成方法

モナーフォント TTF 版のコンパイルは、いまのところ標準的な Unix 環境と
Cygwin で確認できています。MacOSX では未確認ですが、基本的な
Unix コマンドと perl5 が使えれば動くでしょう。

  1. ttfsrc/Makefile を編集し、sed, perl などのパスを設定する。
     (ふつうはとくに変更しなくても大丈夫のはずです)

  2. ttfsrc に cd し、make する。
     mona-mac.ttf (Mac用) と mona-win.ttf (Windows用) の 
     TTF ファイルが生成されます。
     所要時間は作者の環境 (Linux-2.2, PIII, 500MHz) で 1〜2分です。


1. TTF に関するイントロダクション

TTF は BDF にくらべてはるかに複雑な形式です (参考URL)。そのため、
BDF から TTF への変換は、完全に全自動というわけにはいきませんでした。
以下ではモナーフォント TTF 版を作成する際に作者が気づいた点を
まとめてあります。

モナーフォント TTF 版は、もともと X11 用に開発された
BDF 版のモナーフォントを、Macintosh および Windows でも
使えるようにしたものです。最初に TrueType ファイルを作るさいの
基礎知識を説明します。

TrueType フォントに必要な情報はおおきく分けて
4種類に分けられます。

   a. グリフ (文字の形状)
   b. メトリックス (グリフをどのように配置するかという情報)
   c. 文字マップ (特定の文字コードとグリフとの対応づけ)
   d. その他管理用の情報

TrueType フォントファイル (TTF) は、「テーブル」とよばれる
分割されたデータ領域からなり、各領域には上のような情報が
別々に格納されています (といっても、たいていのテーブルは
内容的には依存しあっています)。各テーブルは 4バイトの名前
(cmap, EBLC, glyf など。大文字小文字は区別される) をもち、
TTF ファイルのヘッダにある「TTF ディレクトリ」にそのオフセッットが
格納されています。

そのため TTF をいじるためには、まず TTF内の各テーブルを
抽出・変更するツールが必要になります。これが ttfls, ttfcat,
ttfunpack, ttfpack, ttfsum のツール群です。
(いっぽう TrueType Collection (TTC) ファイルは、おおざっぱにいえば
複数の TTF ファイルをまとめたものです。ただし、ただ単純にまとめた
わけではなくて、場所の効率を上げるために複数の TTF から
同一のテーブルを共有できるようになっています。付属のツール
ttcunpack はこれを複数の ttf ファイルに分割します)

つまり TTF ファイルの作成するためには、フォントに必要な
各情報のテーブルを作成する必要があるわけですが、ややこしいことに
TTF の用途によって、必要なテーブルは違っています。

本来、TrueType フォントは (その定義からして) アウトラインフォントの
はずです。しかし画面上の見た目をよくするために、特定のフォントサイズに
対してはあらかじめ作成したビットマップを「埋め込む (embed)」ことが
できます。

さらに Apple はすべてのフォントを TTF として扱うために
「アウトラインを持たない (ビットマップのみの) TrueType フォント」という
存在も許しました。よって、TrueType フォントには大きくわけて
3つのタイプがあることになります。それぞれ必要なテーブルが違います:

  a. アウトラインのみのフォント:
     glyf, loca などのアウトライングリフが必要。

  b. アウトライン + embedded bitmap のフォント:
     glyf, loca に加えて、bloc(EBLC), bdat(EBDT) などの
     ビットマップグリフが必要。

  c. ビットマップのみのフォント:
     bloc(EBLC), bdat(EBDT) のみが必要。

モナーフォント Mac 版は c. のタイプですが、こまったことに Windows NT では
アウトラインを持たない TrueType フォントは禁止されているようです。
そのためここではダミーのアウトライン情報を入れてごまかすことにしました。
よって Windows 版はダミーのアウトライン (すべての文字が同じ形) を
ふくんだ b. のタイプになっています。これらの違いは、
フォントファイル中に glyf, loca, cvt の各テーブルがあるかどうか、だけです。

さて、TrueType は最初 Apple 社によって考案されたものですが、
その後 Windows でも取り入れられるようになりました。ただし
厄介なことに、プラットフォームによって必要なテーブルは異なっています。
さらに MacOS における bloc, bdat の各テーブルは、Windows では
それぞれ EBLC, EBDT という名前で呼ばれています。ただし今では
MacOS も Windows 形式と互換性があるらしいので、モナーフォントでは
「基本的には Windows 形式で作り、つぎに Macintosh 用にそれを
チューニングする」ことを目標にしました。


2. 必要なテーブル

まず、参考資料を読むとビットマップフォントの TTF を作るためには、
最低限以下のテーブルが必要だということがわかりました。

 1. EBDT (Embedded Bitmap DaTa - MacOS では bdat) テーブル:
    ビットマップフォントのグリフが羅列されている領域。
    ビットマップを埋めこんだフォントには必須。
    用途や種類に応じて 7種類のフォーマットが定められている。
    なお EBDT にはメトリックス情報は含まれておらず、
    また、各グリフへのインデックスも含まれていない
    (これらは EBLC に含まれている)。EBDT は EBLC に強く依存している。
    MacOS では、各グリフの幅はここにある hadvance の値が使われる
    (Windows ではこの値は無視され、かわりに hdmx あるいは 
    hmtx の値が使われる)。
    BDF ファイルから直接作成。

 2. EBLC (Embedded Bitmap LoCation - MacOS では bloc) テーブル:
    ビットマップフォントのメトリックスと、各グリフへのインデックスが
    格納されている領域。ビットマップを埋めこんだフォントには必須。
    用途や種類に応じて 7種類のフォーマットが定められている。
    BDF ファイルから直接作成 (ただし縦書き用のメトリックスは適当)。

 3. cmap (Character MAPping) テーブル:
    特定の文字コードとグリフの対応づけ。
    すべてのフォントに必須。
    cmap 内は複数のサブテーブルに分かれており、異なるプラットフォームで
    複数の異なる文字コードの対応づけを格納できる。
    サブテーブルにはエンコードに応じていくつかのフォーマットが
    用意されているが、Windows ではなぜか Format 2 はサポートされない。
    Format 4 を使う必要がある。MacOSX の Cocoa では、Unicode の cmap を使う
    (Windows 用のサブテーブルがあればそれが使われるらしい)。
    MacOSX の Carbon では、QuickDraw が使うフォントは cmap に
    Roman と Japanese のサブテーブルを含んでいなければならない。
    BDF ではグリフに jisx0201, jisx0208 のエンコードが対応づけられている
    ので、これらを抽出し shift-jis あるいは unicode に変換して作成した。

 4. head (MacOS ビットマップフォントでは bhea) テーブル:
    管理用の雑多な情報。unitsPerEm は重要で、
    TrueType で長さを扱うさいの固定小数点表現の精度を指定する。
    この値はほかのテーブルでの固定小数点表現すべてに影響する。

で、これらの情報は基本的には BDF ファイルにも含まれているものなので、
これらを BDF から抽出し、各テーブルの規定フォーマットに
変換するスクリプトを書いたのですが、残念ながらこれだけでは TrueType 
フォントとしてはまだ不十分です。いろいろな試行錯誤をしてみた結果、
さらに以下のようなテーブルが必要だということがわかりました。

 5. OS/2 テーブル:
    管理用の雑多な情報。
    Mac では使われないが、Windows ではこのテーブルがないと表示されない。
    Windows での ascent, descent は、このテーブルにある
    usWinAscent, usWinDescent がそれぞれ使われる。
    EBLC にあるメトリックス内の ascent, descent は無視される。
    また usWeightClass, usWidthClass にはそれぞれ
    「Regular (400)」「Medium (5)」を指定しないと表示されない。
    Regular というのは、フォント選択ダイアログにおける「標準」のこと。
    ulCodepageRange では Japanese を指定すること。

 6. name テーブル:
    フォントに関する情報が文字列として入っているテーブル。
    おもにフォント名だが、copyright やライセンス情報などもここに含まれる。
    name テーブルには Windows 用、MacOS 用の platformID を
    指定したエントリをそれぞれつくっておくこと。
    MacOS 用のエントリは、文字コードが Japanese (Shift-jis) でいいが、
    Windows 用のエントリは Unicode (UTF16) にする必要がある。
    name がないと Mac, Windows ともにフォントとして認識してもらえない。
    また、エンコードがおかしいと Windows の場合はクラッシュ。

 7. maxp (MAXimum Profile) テーブル:
    TrueType アウトラインのレンダリング時に必要な最大メモリ量などを
    記しておくテーブル。アウトラインがなくても必要らしい。
    適当に作っても動くが、numGlyphs だけは他のテーブルからも参照される
    重要な値。
    (2002/3/22) 18番の名無しさんのご指摘によると、WindowsNT4.0 (2000以前)
    ではなぜか numGlyphs の値は実際のグリフ数より 1 だけ多い必要がある
    ようです。
    
 8. post (POSTscript) テーブル:
    印刷時に、このフォントをどの PostScript フォントに置きかえるか
    というような情報。
    適当に作っても動く。

 9. hhea, vhea (Horizontal/Vertical metrics table HEAder) テーブル:
    後述の hmtx, vmtx テーブルのためのヘッダ。
    なぜわざわざ別テーブルになっているのかは謎。

10. hmtx, vmtx (Horizontal/Vertical MeTriX) テーブル:
    アウトラインフォントのメトリックスが入っているヘッダ。
    本来ビットマップフォントしか使わないなら必要ないはずだが
    (ビットマップフォントのメトリックスは EBLC に入っている)、
    Windows ではたとえビットマップフォントであっても
    hmtx, hhea, vmtx, vhea の各テーブルがないと何も表示されない。
    モナーフォントでは、16pt のグリフ幅を 1.0 に正規化して作成。

11. EBSC (Embedded Bitmap Scaling Control) テーブル:
    ビットマップフォントを拡大縮小する際に、
    どのdestinationサイズに対してどのsourceサイズを使うか、という情報。
    Windows ではこれがないと元々のサイズ以外ではまったく表示されなくなる。
    また、このテーブルがあっても、ここで指定されていない
    フォントサイズについては何も表示されない。
    とりあえず使われそうなサイズだけ適当に指定。

12. hdmx テーブル:
    Windows で使われる、ビットマップフォントのグリフ幅。
    まったく同じ情報が EBLC にも入っているはずだが、なぜかそちらは
    無視されている (Mac では EBLC の情報が使われる)。
    このテーブルがない場合は hmtx テーブルのメトリックスが
    そのフォントサイズに正規化されて使われるが、これは少ないポイント数では
    たいてい誤差が生じるので汚くなる。
    いっぽう MacOS では、ビットマップフォントのグリフ幅は EBLC の hadvance が
    使われる (Windows ではこちらは無視される)。
    BDF ファイルから各グリフ幅を取りだして作成。

さらにさらに、Windows NT 系列では、アウトラインとして
以下のテーブルが必要です。

13. glyf テーブル:
    アウトラインフォントのグリフが含まれる。
    実際にはアウトラインは座標値ではなくプログラムとして表現されており、
    その方法は非常に複雑。今回、ダミーの glyf テーブルは PfaEdit を
    用いて 1文字だけのフォントを生成し、その glyf テーブルを必要な数だけ
    繰り返して作成した。(dummy.sfd はそのとき使った PfaEdit のファイル)

14. loca テーブル:
    アウトラインの各グリフへのインデックス。
    すべてのアウトライングリフが空でも、このテーブルの長さは
    グリフの数に比例する。

15. cvt  テーブル:
    glyf 内のアウトラインインストラクションで使われる定数を
    格納するらしい。現在はグリフが空なのでこれも空ファイル。


3. 雑多な制約

 ・ 以下の条件が満されないと、Windows ではそもそもまともな
    フォントとして扱ってもらえない。

    a. TTF ディレクトリに記載された各テーブルのチェックサムが正しい
       (ただし head テーブルを除く。理由は以下参照)。
    b. TTF ファイル全体 (TTFディレクトリを含む) のチェックサムが
       0xB1B0AFBA であること (このために、ttfpack は head テーブルの 
       checkSumAdjustment を自動的に調整する)。
    c. 格納されているテーブルの順番が OpenType Recommendations に
       従っていること。

 ・ また、Carbon ではプロポーショナルの全角フォントは使えない
    (つまり Monafonts は原理的に無理)。


4. Makefile の動き

ttfsrc/ にある Makefile は、上のようなテーブルを BDF から自動的に
生成し、ターゲットとして TTF ファイルを生成します。この Makefile は
モナーフォントに特化されたものですが、これ以外の BDF フォントを
TTF に変換するのにも使えるでしょう。以下にその動作を簡単に説明します。

まず、モナーフォント 12, 14, 16 pt のフォントファイルから共通の文字データを
くくり出します。X11 では、異なるフォントサイズやスタイルのフォントは
別々の BDF ファイルとして管理されることになっています。なので
あるフォントサイズには含まれている文字が、別のサイズには含まれない
といった事態が発生します。いっぽう TTF は、あるフォントの文字は
すべてのサイズで共通しているという (まっとうな) 仮定をしています。
異なるサイズのグリフは EBDT にまとめられています。
そこで、commonchars を使ってモナーフォント 12, 14, 16 pt に共通の
文字コード (common.enc) をとりだし、つぎに pickchars を使って
共通なグリフをそれぞれ mona12.bit, mona14.bit, mona16.bit に
格納します。

これら 3つのファイルでは、すべての同一な文字のグリフ番号は共通に
なっています。また、一番最初のグリフ (グリフ番号 0) は未定義文字の
ためのグリフで、これは Windows と同じく全角なかぐろ「・」になっています。
グリフ 0 に使う (BDF中での)文字コードは defaultchar.enc で定義されています。

つぎに mona12.bit, mona14.bit, mona16.bit からそれぞれメトリックスと
グリフデータをまとめた TTF テーブル EBLC, EBDT を作成します
(make_EBLC, make_EBDT が使われる)

また、cmap を作成するために、BDFにおける jisx0208 の文字コードを
いったん shift-jis, unicode に変換し、グリフ番号と対応づけます。
このファイルが cmap-ascii.src, cmap-sjis.src, cmap-unicode.src です。
これらから make_cmap を使ってひとつの cmap テーブルを構築します。

さらに Windows 用に hhea, hmtx, vhea, vmtx, hdmx テーブルを作成します。
これらは 16pt BDF のメトリックスを使って計算されます。なお、このさいに
グリフの数を表す一時ファイル、numglyphs を生成しています。これは
あとで maxp を生成するときにも使われます。

あとは雑多なヘッダの類 (head, OS/2, post, maxp, EBSC) です。
これらは BDF の内容が変わってもほとんど変化しないので、
ほぼ固定した値が使われます。name テーブルにはビルドの日付とバージョン番号が
自動的に組みこまれます。

glyf.src をビットマップグリフの数だけ繰り返して
ダミーの glyf テーブルと loca テーブルを作成します。

最後にこれらのテーブルを ttfpack でひとつの TTF ファイルにまとめて
完成です。glyf, loca, cvt の各テーブルを含めた mona-win.ttf と
それらを含まない mona-mac.ttf を作成します。


5. 付属ツールの説明

すべてのツールは perl5 で書かれています。複数のファイルからなる
スクリプトもあるため、シェルから直接実行する場合は、環境変数 PATH と
PERLLIB がそれぞれ ttftools ディレクトリを見るようにしてください。

ttf* で始まるツールは ttfファイル自体を操作するツールです。
disp_* で始まるツールは各テーブルの表示 (解析用)、
make_* で始まるツールは各テーブルの生成をおこないます。
なお、これらは cmap, EBLC, EBDT などのテーブル内の
フォーマットをすべてサポートしているわけではありません。

- TTF/TTC ファイルそのものを操作するツール

ttcunpack  ttcfile  destdir
	TTC ファイルを TTF に分割し、destdir 内に展開する。
	各 ttf のテーブルは destdir/0, destdir/1, ... の
	ディレクトリ内に展開される。

ttfcat  ttffile  type1  type2 ...
	TTF ファイルの指定されたテーブルの typr1, type2 ... の内容を
	stdout に出力する。

ttfls  ttffile
	TTF ファイルのテーブル一覧 (テーブル名、オフセット、チェックサム) を
	表示する。

ttfunpack  ttffile  destdir
	TTF ファイルの各テーブルをファイルごとに切り分ける。
	destdir/ 以下には各テーブルの名前がついたファイルが作られ、
	destdir/ttfdir にテーブル名の一覧とTTFフォントタイプが格納される。
	なお、UNIX ではファイル名中にスラッシュは使えないため、
	テーブル名中の / は _s に変換される。
	テーブル名中の _ は _u に変換される。

ttfsum  file1  file2  ...
	与えられた file1, file2 ... のチェックサムを出力する。
	これは TTF ディレクトリで使われるチェックサムと同じ計算方法。

ttfpack  ttftype  table1  table2 ...
	(ttfpack で分割された)各テーブルをひとつの TTF ファイルに統合し、
	stdout に出力する。テーブルは引数で指定した順番で保存されるので、
	OpenType recommendations にある順番にしたがうこと。
	ファイル名中の _s は / に変換される。
	ファイル名中の _u は _ に変換される。

- 各テーブルを表示・解析するツール

disp_EBLC_EBDT  EBLC  [ EBDT i ]
	EBLC/EBDT テーブルの内容を可読形式でstdoutに出力。
	これらのファイルはシーク可能である必要がある。stdinはダメ。
	EBLC だけを指定すると、テーブルに格納されている
	いくつかのフォントサイズのインデックスの一覧を表示する。
	EBDT とインデックス i(>=0) を指定すると、先頭から i番目の
	サイズのグリフ一覧を BDF類似形式で出力する。
	なお、表示できる EBLC の indexFormat は 1,2,3,5、
	EBDT の imageFormat は 5,6,7 に限られている。

disp_cmap  ファイル
	cmap テーブルの内容を可読形式で出力する。
	この形式は make_cmap で使う形式とは互換性がない。
	入力ファイルはシーク可能である必要がある。stdinはダメ。
	なお、表示できる cmap のサブテーブルフォーマットは
	いまのところ 0,2,4 のみ。

disp_EBSC  { ファイル | - }
	EBSC テーブルの内容を可読形式でstdoutに出力。
	この形式は make_EBSC で使う形式とは互換性がない。

disp_hmtx  { ファイル | - }
	hmtx/vmtx テーブルの内容を可読形式で出力する。
	この形式は make_hmtx/make_vmtx で使う形式とは互換性がない。

disp_hdmx  { ファイル | - }
	hdmx テーブルの内容を可読形式で出力する。
	この形式は make_hdmx で使う形式とは互換性がない。

disp_OS_s2  { ファイル | - }
disp_head  { ファイル | - }
disp_hhea  { ファイル | - }
disp_maxp  { ファイル | - }
disp_name  { ファイル | - }
disp_post  { ファイル | - }
disp_vhea  { ファイル | - }
	OS/2, head, hhea, maxp, name, post, vhea テーブルの内容を
	可読形式で出力する。
	この形式は make_* コマンドと互換性がある。

- 各テーブルを生成するツール

make_EBLC  サイズ1  BDF1  サイズ2  BDF2 ...
	複数の BDF ファイルからメトリックスを抽出し、
	ビットマップのインデックスを計算して EBLC テーブルを作成、
	stdout に出力する。現在のところ indexFormat1 のテーブルしか
	作れない。
	ここで渡す形式は disp_EBLC_EBDT コマンドの出力結果とは互換性がない。

make_EBDT  BDF1  BDF2  ...
	与えられた複数の BDF から EBDT テーブルを生成し stdout に出力する。
	EBDT の各ビットマップへのインデックスは EBLC に依存している。
	必ず、各 BDF の順番は make_EBLC に与えたのと同じにすること。
	ちなみに現在のところ imageFormat 6 のテーブルしか作れない。

make_cmap  エンコード1  format1  platformID1  platformSpecificID1  languageID1
		...
	   エンコードn  formatn  platformIDn  platformSpecificIDn  languageIDn
	与えられた各エンコードから、指定された format で 
	cmap サブテーブルを生成し、ひとつの cmap テーブルにまとめて
	stdout に出力する。各サブテーブルに対して、format, platformID, 
	platformSpecificID, languageID をそれぞれ指定すること。
	なお現在のところサポートする format は 0,2,4 だけである。
	ここで渡す形式は disp_cmap コマンドの出力結果とは互換性がない。

make_EBSC  { ファイル | - }
	与えられたソースから EBSC テーブルを生成し、
	stdout に出力する。与える形式は ttfsrc/EBSC.src を参照のこと。
	ここで渡す形式は disp_EBSC コマンドの出力結果とは
	互換性がない。

make_hmtx  { ファイル | - }  ppem  headのunitsPerEm値
make_vmtx  { ファイル | - }  ppem  headのunitsPerEm値
	与えられた BDF ファイルから hmtx/vmtx テーブルを生成し、
	stdout に出力する。その BDF ファイルのサイズを ppem で指定すること。
	BDF 中のメトリックススは unitsPerEm に正規化される。
	ここで渡す形式は disp_hmtx/disp_vmtx コマンドの出力結果とは
	互換性がない。

make_OS_s2  { ファイル | - }  [ パラメータ1=値1  パラメータ2=値2 ... ]
make_head  { ファイル | - }  [ パラメータ1=値1  パラメータ2=値2 ... ]
make_hhea  { ファイル | - }  [ パラメータ1=値1  パラメータ2=値2 ... ]
make_maxp  { ファイル | - }  [ パラメータ1=値1  パラメータ2=値2 ... ]
make_name  { ファイル | - }  [ パラメータ1=値1  パラメータ2=値2 ... ]
make_post  { ファイル | - }  [ パラメータ1=値1  パラメータ2=値2 ... ]
make_vhea  { ファイル | - }  [ パラメータ1=値1  パラメータ2=値2 ... ]
	OS/2, head, hhea, maxp, name, post, vhea テーブルを
	指定されたソースから生成し stdout に出力する。このさい、
	パラメータをコマンドラインから直接渡すこともできる。
	ここで渡す形式は disp_* コマンドの出力結果と互換性がある。


- 補助的なツール

commonchars bdfファイルリスト1 : bdfファイルリスト2 : ...
	各 BDF ファイルリストに共通して含まれている文字コードを取り出し、
	stdoutに出力する。

pickchars  encodings  bdf1  bdf2 ...
	encodings に含まれる番号のグリフを bdf1, bdf2 ... から取り出し、
	stdoutに出力する。

repeatfile  回数  繰り返すファイル
	指定されたファイルを指定された回数だけ繰り返す。
	ダミーの glyf を作るのに使われる。

mktestsjis  sjisコード表
	sjis のテスト用文字テーブル (html) をstdoutに出力する。

mktestunicode  unicodeコード表
	unicode のテスト用文字テーブル (html) をstdoutに出力する。

jis2ascii  encodings
	jisx0201/jisx0208 のエンコードの ascii 部分だけ取り出し、
	stdout に出力。

jis2sjis  encodings
	jisx0201/jisx0208 のエンコードを shift-jis に変換し、
	stdout に出力。

jis2unicode  encodings
	jisx0201/jisx0208 のエンコードを unicode に変換し、
	stdout に出力。


6. 参考URL

以下はこれらのツールをつくる際に参考にした資料です。
基本的には、ttftools は作者がこれらの web ページを読み、
既存のいろいろなフォントファイルを解析しながらつくりました。

Apple TrueType: http://developer.apple.com/fonts/
TrueType の本家である Apple のサイト。すこし情報が古く、
また Windows に関する記述はあまりありませんが、
文字のデザインに関する指針からレンダリングエンジンの動きまで
よい説明があります。TTF形式に関する説明は 6章ですが、
アウトラインインストラクションの説明には 2〜5章がさかれています。
アウトラインを直接いじる人は必読でしょう。

Adobe OpenType:
http://partners.adobe.com/asn/developer/type/opentype.html
同じく TTF形式に関する説明があります。こちらは
Windows よりの説明です。Windows で正しく認識させる TTF ファイルを
つくるためには、ここに書かれている Recommendations に従う
必要があります。

Microsoft TrueType Specifications:
http://www.microsoft.com/typography/tt/tt.htm

Watanabe明朝:
http://packages.debian.org/unstable/x11/ttf-xtt-watanabe-mincho.html

PfaEdit:
http://pfaedit.sourceforge.net/
多機能 TrueType フォントエディタ。多くのフォント形式に対応しており、
TTF のアウトラインも作成できる。ただしまだ不安定。
