GSUB テーブル (4) - LookupList [2]

GSUB LookupType 2〜4
ここでは、GSUB テーブルの LookupList の LookupType 2〜4 を解説していきます。
LookupType 2 (複数置換)
「LookupType 2」は、単一のグリフから、複数グリフへの置き換えを行います。
合字分解などで使われます。

日本語フォントではほぼ使われることはありませんが、「Source Code Pro」などのフォントで格納されています。

サブテーブルのフォーマットは1つです。

Format1
uint16 substFormatフォーマット番号 = 1
Offset16 coverageOffsetCoverage テーブルへのオフセット位置
uint16 sequenceCount配列の数
Offset16 sequenceOffsets[sequenceCount]Sequence テーブルへのオフセット位置。
(サブテーブルの先頭を 0 とする)

▼ Sequence
uint16 glyphCount配列の数。常に 0 より大きい。
uint16 substituteGlyphIDs[glyphCount]置換後のグリフ ID (複数個)。
テキストの左右順にかかわらず、最初のグリフは先頭の文字となる。

Coverage テーブルからグリフを1つ検索し、そのグリフに対応した Sequence テーブルから、置き換える複数のグリフ ID を取得します。
LookupType 3 (代替置換)
「LookupType 3」は、一つのグリフに対して、複数のパターンがある場合に、各グリフを列挙します。

「aalt」「nalt」などで使われます。

サブテーブルのフォーマットは1つです。

Format 1
uint16 substFormatフォーマット番号 = 1
Offset16 coverageOffsetCoverage テーブルへのオフセット位置
uint16 alternateSetCount配列の数
Offset16 alternateSetOffsets[alternateSetCount]AlternateSet テーブルへのオフセット位置。
(サブテーブルの先頭を 0 とする)

▼ AlternateSet
uint16 glyphCount配列の数
uint16 alternateGlyphIDs[glyphCount]グリフ ID の配列

データ構造的には、LookupType 2 と同じです。

元となるグリフを1つ検索し、それに対応する複数のパターンのグリフ ID を取得します。
LookupType 4 (合字置換)
「LookupType 4」は、複数のグリフを一つに合体した形のグリフを取得します。

アラビア語などで使われますが、日本語フォントでも、濁点や半濁点をつけたひらかなや、「セ・ン・チ → ㌢」といったグリフへの置き換えに使われます。

サブテーブルのフォーマットは1つです。

Format 1
uint16 substFormatフォーマット番号 = 1
Offset16 coverageOffsetCoverage テーブルへのオフセット位置
uint16 ligatureSetCount配列の数
Offset16 ligatureSetOffsets[ligatureSetCount]LigatureSet テーブルへのオフセット位置。
(サブテーブルの先頭を 0 とする)

▼ LigatureSet
uint16 ligatureCount配列の数
Offset16 ligatureOffsets[LigatureCount]Ligature テーブルへのオフセット位置。
(LigatureSet の先頭を 0 とする)

合字の優先順に並んでいる。

▼ Ligature
uint16 ligatureGlyph置き換える合字のグリフ ID
uint16 componentCount配列の数。
合体する前のグリフ数 (最初のグリフを含む)。
uint16 componentGlyphIDs[componentCount - 1]合体前の文字列のグリフ ID。
最初のグリフは除いて、2番目から。

まず、Coverage テーブルで、合体前の最初のグリフを検索します。

LigatureSet には、先頭文字に続く各グリフと、合体後のグリフのリストがあります。

componentGlyphIDs で、合体前の2番目以降のグリフを比較し、一致すれば、ligatureGlyph のグリフ ID に置き換えます。
プログラム
>> 21_gsub_type2.c

LookupList の全データから LookupType 2〜4 のデータを読み込んで、「output.txt」に置き換え情報を出力し、さらにそれらのグリフ画像を出力します。

横に並ぶグリフ数が多い場合は、端で切れる場合もありますが、ご了承ください。

==== [33] ====

{Lookup} lookupType <4> | lookupFlag:0x0000 | subTableCount:1

# {SubTable} format <1> / {Coverage} format <1>

[2] (!) U+0021
+ [2] (!) U+0021
= [736] (‼) U+203C

[2] (!) U+0021
+ [32] (?) U+003F
= [740] (⁉) U+2049

[17] (0) U+0030
+ [25534] (点) U+70B9
= [2271] (㍘) U+3358

[18] (1) U+0031
+ [17] (0) U+0030
+ [20669] (日) U+65E5
= [2417] (㏩) U+33E9
...

「源ノ明朝」では、「— (U+2014)」2つで2倍ダーシ「⸺ (U+2E3A)」にする合字や、「あ」などに濁点をつけた合字などがあります。

しかし、どういったグリフが格納されているかはフォントによって異なるため、これらをどのように使うかは、色々なフォントの情報を見て判断した方が良いでしょう。
LookupType 5, 6, 8
LookupType 5 については、格納されているフォントが見当たらなかったため、省略します。

LookupType 6 については、サブテーブル format = 3 で格納されているフォントがいくつかありました。
「源ノ明朝」では韓国語のグリフ、「Source Code Pro」ではラテン文字のグリフのデータがありましたが、日本語ではあまり使われていないようなので、省略します。

LookupType 8 に関しても、使われているフォントはあまりなさそうです。

というわけで、GSUB の解説は、これで終了します。
FT_OpenType_Validate() 関数
FreeType では、FT_OpenType_Validate() 関数を使って、GSUB などのテーブルデータをまるごと読み込むことができますが、ver 2.10.1 時点で、「源ノ明朝 (CJK セット版)」の GSUB を読み込もうとすると、エラーが出て取得できません。

FT_OpenType_Validate() 関数では、単にテーブルデータをそのまま読み込むだけではなく、テーブルデータ内部のすべての値を検証して、問題ないか調べているため、そこでエラーが出ていると思われます。

先にすべてのデータのエラー確認をしておくことで、データを読み込む時の処理を簡易化できるという利点はありますが、一つのエラーでテーブル全体が使えなくなるのは問題です。

そのため、GSUB テーブルなどは、フォントファイルから直接読み込んだ方が良いかと思います。