TBD

フォント Computer Modern Typewriter Text Bold の METAFONT からの生成について

aghtex の \ttfamily 系フォント用に Computer Modern [1] の Typewriter Text 書体一式を METAFONT ソースを弄って生成したことについて。

★折角なので生成したフォントファイル (TTF形式) を aghtex_cmttxx10.zip においた。 フォント名から中身が分かるように以下の様に命名規則を定めた。

aghtex_cmFFBSDD.ttf

但し FF は書体を指定するアルファベット二文字で Typewriter Text の場合は tt ということにする。 B は太さを表し、細字なら l (light) 普通なら m (medium) 太字なら b (bold) 極太なら h (heavy) ということにした。 S は形状を表し、通常なら n (normal) 斜体なら s (slanted) イタリックなら i (italic) Small-caps なら c (caps) ということにした。 DD は整数で印刷する時に想定するポイント数で今回は 10 だけ調整込みで生成した。

★aghtex に組み込んだ。

\begin{tabular}{c||c|c}
\verb+\ttfamily+& 普通 & 太字 \\ \hline \hline
直立 & \ttfamily Hello world! & \ttfamily\bfseries Hello world! \\
斜体 & \ttfamily\slshape Hello world! & \ttfamily\bfseries\slshape Hello world! \\
イタリック & \ttfamily\itshape Hello world! & \ttfamily\bfseries\itshape Hello world! \\
Small-caps & \ttfamily\scshape Hello world! & \ttfamily\bfseries\scshape Hello world!
\end{tabular}

但し、aghtex では Small-caps はフォントではなくて CSS の font-variant-caps を使っている。 ところで実際にブラウザで試すと @font-facefont-style: italicfont-style: oblique のフォントは独立に設定できないようだ… (Chrome, Firefox, IE, Edge, WebKit で確認)。

前調査

段落モードでは1書体につき6字体必要

aghtex でも \ttfamily に対して $\LaTeX 既定の書体 Computer Modern Typewriter Text (cmtt) を使いたい。 記事 [2] でも述べたが $\LaTeX の段落モードでは family x series x shape の組み合わせでフォントを指定する。 新しく \ttfamily に対応するためには、(1 family につき) 2 series x 4 shapes = 8 種類のフォントが必要になる。 small-caps に関しては CSSfont-variant(-caps): small-caps を使うことにしても 2 series x 3 shapes = 6 種類のフォントが必要である。 一つ Regular なフォントを用意したら自動的に他を synthesize してくれたら良いのだが、 Web fonts の synthesize はブラウザによってまちまちなので、やはり自分で用意しなければならない。

Computer Modern Typewriter Text の足りない字体

先に調べた通り AMSFonts に付属している Computer Modern には cmtt (Computer Modern Typewriter Text) の太字版がない [2]。 一方で Computer Modern Unicode (CMU) [3] には太字と太字イタリックや細字斜体などがある。 しかし太字斜体がどこにもない。 自分で作るしかないのかなと考える。一応 FontForge (フォント編集ソフト) [4] に輪郭を太らせる機能があることは知っている。

Computer Modern は METAFONT で定義されている

元々 Computer Modern は METAFONT で書かれた [1] そうだ。 CMU のページによると CMU も METAFONT ソースから生成しているそうなので CMU のソースを確認してみる。 色々調べた結果、恐らく CMU におけるフォント生成手順は以下のようになっている。

CMU におけるフォント生成手順 for Typewriter Text の Bold (Bold Italic)

  1. ectb.mf (ectx.mf): CMU のソースに含まれるファイル。これが Bold (Bold Italic) のアルファベットの METAFONT ソースである。
  2. ectb.pfb (ectx.pfb) 生成: 上のファイルを mftrace に入れて得られる。 mftrace の中では一旦 mf で字形をラスタライズして、その輪郭を autotrace というプログラムでなぞらせて PostScript を生成している。 その PostScript を t1asm などのコマンドを用いて Type 1 (Binary) 形式のフォントファイルに変換する。
  3. cmuntb.sfd (cmuntx.sfd) 生成: 上のファイル + 他の文字 (ギリシャ文字やその他のヨーロッパ文字) を含むファイル ??tb.pfb (??tx.pfb) をくっつけて FontForge ファイルを生成する。
  4. cmuntb.ttf (cmuntx.ttf) 生成: 最終的なフォントファイル。

METAFONT について調べる [5,6]。 昨今一般的なアウトラインフォントではなくストロークフォントの様だ。 つまり、字形の輪郭ではなくて字画の中心線の情報を保持する。 但し、ペンの形状などを指定することができる。 METAFONT はテキスト形式のプログラムになっていて人の手で記述できるようになっているようだ。 "一次連立方程式を解いてくれる" 機能もあって、 CAD みたいに点の関係を与えるだけで方程式を解いて位置を確定してくれる。

CMUectb.mf の中を覗くとパラメータの設定だけして他の mf を呼び出している。

% ectt.mf
%
%%%%中略(パラメータの設定)%%%%
generate exroman %%%%<-他のmfを呼び出している?%%%%

endinput;

AMSFonts に含まれる tt のソースも複数確認してみたが似たような形である。 つまり一連の Computer Modern のフォントは、文字の定義は全て一括で行っていて、 但しパラメータを変えて様々なスタイルの字形を生み出しているということらしい。 つまり、このパラメータを弄るだけで好きな太さ・形状の Computer Modern フォントを生成できるのでは。

METAFONT を生成して ttf に変換する

スクリプトを書いて生成を行った。 生成するだけならば以下のような雰囲気でできる (コマンドはお使いの環境に合わせて適宜解釈して下さい)。

$ sudo dnf install texlive mftrace
$ git clone git@github.com:akinomyoga/aghfonts.git
$ cd aghfonts
$ ./generate_ttfamily.sh

以下はスクリプトの中でやっていること。

1 パラメータを線形補外して *.mf を自動生成する

Computer Modern のソースにはパラメータがたくさんある。 "文字の太さ" みたいな分かりやすいパラメータはなくて、 字体各部分に対応する値を1つ1つ手で調整する。気が遠くなる。

面倒なので手に入るソースに現れるパラメータ値の差分を取って、 線形補間・補外してパラメータを決定することにした。以下のソースを元にする。

  • amsfonts/cm/cmtt*.mf (Typewriter Text Regular),
  • cm-unicode-0.7.0/ectb.mf (Typewriter Text Bold),
  • cm-unicode-0.7.0/ectx.mf (Typewriter Text Bold Italic),
  • amsfonts/cm/cmtcsc10.mf (Typewriter Text Small-caps)

注意点としては ectb.mf 及び ectx.mf に書き込まれているパラメータ値は fontsize 10 の時だけしか調整されていないということ。 他の fontsize の値は Regular な Typewriter Text の時の値と同じになっている。

適当にスクリプトを書いてmfを生成する。 以下のような感じの .mf ファイルを {細字, 通常, 太字, 極太} ✕ {通常, 斜体, イタリック, Small-caps} ✕ {8pt, 9pt, 10pt, 12pt} で 4x4x4 = 64 種類生成した。

% THIS IS UNOFFICIAL COMPUTER MODERN SOURCE FILE cmtt10.mf BY K MURASE.
% IT MUST NOT BE MODIFIED IN ANY WAY UNLESS THE FILE NAME IS CHANGED!

% Computer Modern Typewriter Text for use with 10 point
if unknown cmbase: input cmbase fi

font_identifier:="AGHTEX_CMTTBC"; font_size 10pt#;

u#:=21.0/36pt#;                            % unit width
%%%%%%%%%%%%
%%%%中略%%%%
%%%%%%%%%%%%
 lower.fudge:=0.8;                   % factor applied to weights of heavy characters

%------------------------------------------------------------------------------

generate csc                    % switch to the driver file

2 mftrace*.mf から *.ttf に変換する

CMU に倣って mftrace*.pfb を生成したい。Fedora に mftrace を入れた。

$ sudo dnf install mftrace

mftracegenfonts.sh の真似をして呼び出してみる。 しかし t1asm でエラーになって動かない。t1utils を reinstall しても変わらない。 使い方が悪いのかと思って色々やったが Ubuntumftrace を入れてみると普通に動いた。 結局、t1utils [7] をソースから自分でビルドして入れたら Fedora でも動くようになった。

$ git clone git@github.com:kohler/t1utils.git
$ cd t1utils
$ autoreconf -i
$ ./configure --prefix=$HOME/opt/t1utils
$ make install
$ ln -s ~/opt/t1utils/bin/t1asm ~/bin/

単に mftrace --formats=ttf example.mf としたら mf から ttf ファイルを直接生成してくれた。

3 FontForge スクリプトでメタ情報埋め込み

完成したファイルを見るとフォントのメタ情報が色々欠けているので、 コマンドラインで設定できるツールを探す。 Perl で書かれた FontUtils というのがあるらしいが結局どうやって入れたら良いのか分からなかったのでやめた。 検索すると Windows で使える ttfname3 [9,10] というのがあったようだがソースコードが見つからなかったので Linux では使えない。 あと、XML なので操作を書くのが面倒だ。

結局 FontForge スクリプト [11] で処理することにした。 ついでに自動ヒントなども付加するようにしてみる。

以下は実際にシェルスクリプトFontForge スクリプトを呼び出している部分を抜粋したもの (勿論各シェル変数には適切な値が設定されている)。

fontforge -lang=ff -script <<EOF
Open("$input")
SetFontNames("$key", "$ttffamily", "$ttffull", "$ttfsub", "$copy", "$version")
#CIDSetFontNames("$key", "$ttffamily", "$ttffull", "$ttfsub", "$copy")
SetTTFName(0x409, 0, "$copy")
SetTTFName(0x409, 1, "$ttffamily")
SetTTFName(0x409, 2, "$ttfsub")
SetTTFName(0x409, 3, "$ttfid")
SetTTFName(0x409, 4, "$ttffull")
SetTTFName(0x409, 5, "Version $version")
SetTTFName(0x409, 13, "The SIL Open Font License, Version 1.1.")
SetTTFName(0x409, 14, "http://scripts.sil.org/OFL")
SetOS2Value("Weight", $os2weight)
#SetOS2Value("StyleMap", $os2style)

# Automatical Adjustment
SelectWorthOutputting()
CanonicalContours()
CanonicalStart()
#ClearHints()
#AutoHint()
#AutoInstr() #自動ヒンティング命令を出力すると表示が変なのでoff

Generate("$output", "ttf", 0x200, -1)
EOF

FontForge の関数一覧はページ [12] にある。SetTTFName で設定する値についてはページ [13] を参照した。 FontForge による自動ヒンティング命令を出力するとレンダリング結果がおかしいので、ヒンティング命令は出力しないことにした。

結果

以下は自分のディスプレイ用の ClearType の画像なので、他のディスプレイだと色がついたり滲んだり掠れたりして見えるかもしれない。

通常 (上から Light, Medium, Bold, Black)

f:id:akinomyoga:20191212015921p:plain
aghtex Computer Modern Typewriter Text Regular
斜体 (上から Light, Medium, Bold, Black)
f:id:akinomyoga:20191212020030p:plain
aghtex Computer Modern Typewriter Text Oblique
イタリック (上から Light, Medium, Bold, Black)
f:id:akinomyoga:20191212020058p:plain
aghtex Computer Modern Typewriter Text Italic
Small-caps (上から Light, Medium, Bold, Black)
f:id:akinomyoga:20191212020120p:plain
aghtex Computer Modern Typewriter Text Small-caps

最後に

普段なら適当に調べるだけ調べて「将来的なメンテナンスのコストと見返り」などなど考えて諦めるところだが、記事 [1] にしてしまったので中途半端は駄目な気がしてフォント作成までしてしまった。書いて思うのはフォント作成よりも記事執筆の方が時間がかかる。しかし、アウトプットは大切な気がする。時間を無駄にした気もするし、しかしこういった時間の使い方も大切にしなければならないとも思う。

アウトプットには時間がかかる。成果を上げることを考えていると、すぐに簡単にアウトプットできないくらいに成果が溜まってしまう。そう考えると研究も本当は一日でできる程度の内容に留めて、一日の研究成果を時間をかけて論文にする、というぐらいがバランスが良いのかもしれない。