🗡️
FontForge のスクリプト機能を利用してフォントにグリフ置換機能を追加する
はじめに
FontForge を使ったフォントの合成方法などは調べると見つかるのですが、OpenType の GSUB フィーチャを扱った情報はあまり無いようでしたので、私が理解した (つもりの) 範囲で記事にしました。
FontForge のドキュメントとともにご覧下さい。
0. 準備
今回は DejaVuSansMono.ttf に実験台となっていただきます。サンプルスクリプトと同じディレクトリに置きます。
1. サンプルスクリプトの内容
- GSUB、GPOS フィーチャを全て消去
- sups、subs タグを新規に作成し、「1」に付けて上付き、下付き文字に置換できるようにする
- 「1」の タグを「2」にコピーして上付き、下付き文字に置換できるようにする
- 「A」に ss01 タグを付けて、コードポイントが割り当てられていない外字に置換できるようにする
2. スクリプトと解説
sample0.pe
inputName="DejaVuSansMono.ttf"
outputName="DSUBtestMono0.ttf"
# フォントファイルを開く
Open(inputName)
# 既存タグの削除
# GSUB フィーチャを全て削除
lookups = GetLookups("GSUB")
i = 0
while (i < SizeOf(lookups))
Print("Remove GSUB_" + lookups[i])
RemoveLookup(lookups[i])
i += 1
endloop
# GPOS フィーチャを全て削除
lookups = GetLookups("GPOS")
i = 0
while (i < SizeOf(lookups))
Print("Remove GPOS_" + lookups[i])
RemoveLookup(lookups[i])
i += 1
endloop
# 新規にタグを追加
# 「1」に subs タグを追加
Print("Add subs lookup")
## subs タグを新規追加
lookupName = "'subs' 下つき文字" # ルックアップ名に命名規則等は無さそう
AddLookup(lookupName, "gsub_single", 0, [["subs",[["DFLT",["dflt"]]]]])
### gsub_single: 置換方法 (1つのグリフを別の1つのグリフに置換)
### subs: フィーチャタグ名 (下付き)
### DFLT: 用字系名 (デフォルト)
### dflt: 言語系名 (デフォルト)
lookupSub = lookupName + "サブテーブル"
AddLookupSubtable(lookupName, lookupSub) # ルックアップの下位にサブテーブルが必要
## 追加した subs タグを「1」に追加
origin = 0u0031 # 1
replace = 0u2081 # 下付き 1
Select(replace)
glyphName = GlyphInfo("Name") # 置換先のグリフ名を取得
Select(origin)
AddPosSub(lookupSub, glyphName) # タグと置換先のグリフ名を置換元に付加
# 「1」に sups タグを追加
Print("Add sups lookup")
## sups タグを新規追加
lookupName = "'sups' 上つき文字"
AddLookup(lookupName, "gsub_single", 0, [["sups",[["DFLT",["dflt"]]]]])
lookupSub = lookupName + "サブテーブル"
AddLookupSubtable(lookupName, lookupSub)
## 追加した sups タグを「1」に追加
origin = 0u0031 # 1
replace = 0u00b9 # 上付き 1
Select(replace)
glyphName = GlyphInfo("Name")
Select(origin)
AddPosSub(lookupSub, glyphName)
# 既存タグの流用
# 「2」に「1」のタグをコピーする
## 「1」に付加されているフィーチャタグを全て取得
Select(0u0031) # 1
lookups = GetPosSub("*")
## 「2」にタグを追加
Print("Copy sups lookup")
origin = 0u0032 # 2
replace = 0u00b2 # 上付き 2
Select(replace)
glyphName = GlyphInfo("Name")
Select(origin)
AddPosSub(lookups[0][0], glyphName) # 「1」から取得した1番目のタグ (sups) と置換先のグリフ名を付加
Print("Copy subs lookup")
origin = 0u0032 # 2
replace = 0u2082 # 下付き 2
Select(replace)
glyphName = GlyphInfo("Name")
Select(origin)
AddPosSub(lookups[1][0], glyphName) # 2番目のタグ (subs) と置換先のグリフ名を付加
# 外字への置換
# 「A」に ss01 タグを追加
origin = 0u0041 # A
replace = 1114166 # GSUB フィーチャを削除したことで使われることのなくなったグリフの ID を指定
## ss01 用の外字グリフを作成
Print("Make ss01 glyphs")
Select(origin); Copy() # A をひっくり返したグリフをサンプルとして作成
Select(replace); Clear(); DetachAndRemoveGlyphs()
Paste(); Rotate(180)
SetWidth(1233)
Print("Add ss01 lookup")
## ss01 タグを新規追加
lookups = GetLookups("GSUB"); numlookups = SizeOf(lookups)
lookupName = "'ss01' スタイルセット"
AddLookup(lookupName, "gsub_single", 0, [["ss01",[["DFLT",["dflt"]]]]], lookups[numlookups - 1])
### lookups[numlookups - 1]: 既存の最後のルックアップ名を指定することで末尾に追加
### (省略した場合は先頭に追加)
lookupSub = lookupName + "サブテーブル"
AddLookupSubtable(lookupName, lookupSub)
Select(replace)
glyphName = GlyphInfo("Name")
Select(origin)
AddPosSub(lookupSub, glyphName)
# フォントファイルを生成
Generate(outputName)
Close()
3. 実行結果
元の DejaVu Sans Mono。
たくさんフィーチャが実装されています。
スクリプト実行!
fontforge -script sample0.pe
生成されたフォント (DSUBtestMono0.ttf) 。ずいぶんすっきりしました。
また一番最後のグリフがスクリプト内で作成した外字に入れ換わっています。
4. フォントの動作確認
FontGoggles で確認します。
右側に実装してあるフィーチャのタグが並んでいます。緑色で ON、赤色で OFF、灰色でデフォルトです。
アプリケーションによりますが、通常 sups、subs、ss はデフォルトで OFF です。
問題なく動作しているようです。
おわりに
次回は文脈依存の置換機能の実装に挑戦します。
Discussion