アンチックフォントを作る: グリフの変形と合成

グリフを変形して合成
前回作ったアンチックフォントでは、ひらがな・カタカナが、縦書き時に少し大きく感じるので、ひらがな・カタカナのグリフを少し縮小したいと思います。

使うのは、AFDKO の rotatefont コマンドです。

rotatefont は、フォントのグリフを変形して、別のフォントに出力することができます。
フォントの変換を行う tx コマンドをベースにして作られているので、tx が対応しているフォントの読み込み・出力ができます。

なお、前回作ったアンチックフォントを元にして、任意のグリフを変形した後、そのグリフのみを再合成するやり方もありますが、今回は、源ノ角ゴシックと源ノ明朝を使って最初から合成します。
ひらがな・カタカナのグリフを変形して出力
まずは、源ノ明朝のひらがな・カタカナのグリフを変形して、そのグリフのみを含んだフォントを出力します。

各説明は後で行うので、とりあえず、hirakana.txt を用意した後、以下のコマンドを実行してください。

>> char2name.py (前回使ったものと同じ)

[hirakana.txt]
u:3041-3096,30a1-30fa,31f0-31ff,1b150-1b152,1b164-1b167

## rotatefont 用のグリフ指定ファイルを出力

$ python3 char2name.py hirakana.txt serif-ginfo.txt -g vert -r 30 30 > rotate.txt

## 指定グリフを変形して出力

$ rotatefont -cff -row -matrix 0.94 0 0 0.94 0 0 -rtf rotate.txt SourceHanSerifJP-Bold.otf hirakana.cff
変形について
rotatefont では、回転角度とオフセット位置、または、変換行列を指定して、グリフの座標を変換できます。
今回はグリフの縮小を行うので、変換行列を使います。

今回の場合、グリフの幅は全角幅のままにして、グリフの形だけ縮小したいので、本来であれば、「変形前に、原点を左下からグリフの中央に移動して、その状態で縮小を行い、最後に原点を元に戻す」、というやり方が正しいのですが、rotatefont では、変形時の原点位置を変更することができないので、「原点は左下のままで縮小を行い、縮小によって減った幅分を余白として移動する」というやり方で行います。

位置を移動しないと、縮小した分、グリフが左下に寄ります。
縮小後の移動数
グリフの座標値は、1 em の単位を元に、数値がセットされています。
OpenType (CFF/CID) における 1 em は基本的に 1000 なので、1000 が全角幅となります。

今回は、グリフを 0.94 倍に縮小するので、縮小後のグリフ幅は、1000 * 0.94 = 940 となります。

グリフの送り幅(原点から次のグリフへの幅)は、日本語グリフであれば、ほとんどが全角幅の 1000 となるので、縮小によって減った幅は、1000 - 940 = 60 となります。
その減った幅を 1/2 にして、余白として移動するので、60 / 2 = 30 を、オフセット移動します。
rotatefont 用のグリフ指定ファイル
rotatefont では、対象とするグリフを、-g LIST または -rtf FILE で指定できます。
グリフが多数の場合は、コマンドラインで指定するのは不便なので、今回はファイルで指定します。

1行で1つのグリフの情報を指定し、各行は空白で区切って、
「<入力グリフ名> <出力グリフ名> <変更する送り幅> <X offset> <Y offset>」の5つの値を指定します。

グリフ名は、CID の場合は 10 進数の値です。
送り幅は、元のグリフのままにしたい場合は、None を指定することができます。
X,Y の offset は、座標の相対移動幅です。

※フォントファイルには、常に .notdef のグリフが必要となるので、CID 0 も含める必要があります。
char2name.py で出力
char2name.py で -r <xoffset> <yoffset> オプションを指定すると、rotatefont 用のグリフ指定ファイルを出力します。
xoffset と yoffset は、各グリフのオフセット移動幅です。

-g vert で、ひらかなの縦書き用のグリフも対象に加えています。

出力結果は、以下のようになります。
送り幅はすべて None (変更なし) とします。
また、グリフ名は変更しないので、同じ値をセットします。

0 0 None 0 0
# U+3041 (ぁ)
1460 1460 None 30 30
# U+3042 (あ)
1461 1461 None 30 30
...
# U+31FF (ㇿ) <vert>
64621 64621 None 30 30

1行目は .notdef (CID = 0) のグリフです。
.notdef は常に含める必要があるので、.notdef も同時に変形されてしまいますが、合成時に対象外とすればよいので、問題ありません。

'#' の行はコメントとなり、下のグリフの Unicode と文字、GSUB 置換の feature が記述されています。
各グリフを編集したい場合は、参考にしてください。
rotatefont
rotatefont コマンドで、源ノ明朝の指定グリフを 0.94 倍に縮小し、CFF 形式で、hirakana.cff ファイルに出力します。

$ rotatefont -cff -row -matrix 0.94 0 0 0.94 0 0 -rtf rotate.txt SourceHanSerifJP-Bold.otf hirakana.cff

-cffCFF 形式で出力します。
-row送り幅を元のグリフのままにします。
※ -matrix の前に指定してください。
-matrix a b c d e f変形行列のパラメータを6個の数値で指定します。
小数点以下有効です。
※ -rtf の前に指定してください。

グリフの座標を (x,y) とすると、変形後の座標 (x', y') は、以下の式で計算されます。
x' = a * x + c * y + e
y' = b * x + d * y + f
-rtf FILE対象グリフをファイルで指定します。

出力形式やファイル指定のオプションは tx コマンドと同じなので、tx -u でオプションを表示してください。
ファイルを2つ指定した場合、入力ファイルと出力ファイル名になります。

変形行列は、拡大縮小の場合は、a = X の倍率、d = Y の倍率となります。他はすべて 0 にします。
psautohint
rotatefont でグリフを変形した場合、90 度単位の回転や移動などの単純な変形の場合は、変形後の形に合わせて、グリフのヒント情報が自動で再セットされます。
しかし、複雑な変形を行った場合は、グリフの現在のアウトライン座標を元に、ヒントを再計算する必要があります。

ヒントというのは、ヒンティングで使われる情報です。
フォントを小さいサイズで描画する時などは、アウトラインが潰れたりする場合がありますが、そうならないように、見栄え重視でアウトラインを調整するための情報となります。

AFDKO の psautohint コマンドを使うと、フォントの各グリフのヒント情報を、アウトラインから自動で判断して、セットできます。

$ psautohint hirakana.cff

コマンドにフォントファイルだけを指定すると、すべてのグリフが対象となり、ヒント情報をセットした後、フォントが上書きされます。
別のファイルに書き込みたい場合は、-o FILE オプションを付けます。
ヒントをセットするグリフを指定したい場合は、-g LIST, --glyphs-file FILE などで指定します。

今回の場合は、ひらかなのグリフを変形したので、rotatefont で出力したファイルのヒント情報を再計算して、上書きします。
グリフの確認
一度グリフを確認したい場合は、fontplot コマンドなどで PDF を出力できます。
なお、グリフのヒント情報を確認したい場合は、hintplot コマンドを使います (使い方は fontplot などと同じ)。

$ fontplot2 -o out.pdf -gpp 50 hirakana.cff
合成とフォント作成
次に、mergefonts でグリフを合成します。
「変形したひらかなグリフ」「変形しない明朝のグリフ」「ゴシック体」の3つに分けて合成することになります。

[others.txt] (UTF-8)
c:!?#$&"'()~
c: ゙ ゚゛゜ゝゞ・ーヽヾ
c:–—―‘’“”‥…′″※‼⁇⁈⁉、。〃〜〝〟〱〲〳〴〵〻〽
c:!"#&'()*,.:;?@{}~

cidfontinfo は、前回使ったファイルと同じです。

## ひらかなのグリフのマッピングファイルを出力

$ python3 char2name.py hirakana.txt serif-ginfo.txt -g vert -m sans-ginfo.txt > merge-hirakana.txt

## 変形しない明朝のグリフのマッピングファイルを出力

$ python3 char2name.py others.txt serif-ginfo.txt -g vert,hwid -m sans-ginfo.txt > merge-others.txt

## (merge-*.txt の1行目にフォント辞書名を記述)

## 合成

$ mergefonts -cid cidfontinfo merge.cff merge-hirakana.txt hirakana.cff merge-others.txt SourceHanSerifJP-Bold.otf SourceHanSansJP-Medium.otf

まず最初に、"merge-hirakana.txt hirakana.cff" で、変形したひらかなのグリフをセットします。
次に、"merge-others.txt SourceHanSerifJP-Bold.otf" で、変形しない明朝の他のグリフをセットします。
最後に、残りのグリフを "SourceHanSansJP-Medium.otf" で埋めます。
makeotf で OpenType を作成
後は、前回と同じように、makeotf で OpenType フォントを作成します。

$ makeotf -f merge.cff -ff features.JP -ch UniSourceHanSansJP-UTF32-H -ci SourceHanSans_JP_sequences.txt -omitMacNames