LookupList
次に、LookupList テーブルです。
ここには、対象のグリフを検索して、グリフの置き換えなどを行うためのデータが格納されています。
FeatureList で取得したインデックス値を使って参照します。
なお、ScriptList/FeatureList/LookupList は、「GPOS テーブル」でも同じように使われます。
ただし、この先で説明する LookupType の値やサブテーブルのフォーマットは、GSUB・GPOS でそれぞれ異なります。
ここには、対象のグリフを検索して、グリフの置き換えなどを行うためのデータが格納されています。
FeatureList で取得したインデックス値を使って参照します。
なお、ScriptList/FeatureList/LookupList は、「GPOS テーブル」でも同じように使われます。
ただし、この先で説明する LookupType の値やサブテーブルのフォーマットは、GSUB・GPOS でそれぞれ異なります。
テーブルデータ
LookupList
uint16 lookupCount | 以下の配列数 |
---|---|
Offset16 lookups[lookupCount] | Lookup テーブルのオフセット位置。 (LookupList の先頭を 0 とする) FeatureList テーブルで取得したインデックス値は、この配列の添字となる。 |
Lookup
uint16 lookupType | Lookup Type の番号 |
---|---|
uint16 lookupFlag | フラグ |
uint16 subTableCount | サブテーブルの数 |
Offset16 subtableOffsets[subTableCount] | 各サブテーブルへのオフセット位置。 (Lookup の先頭を 0 とする) |
uint16 markFilteringSet | lookupFlag で useMarkFilteringSet が ON の場合、 GDEF の MarkGlyphSets のインデックス (0〜)。 |
▼ lookupFlag
0x0001 | rightToLeft | GPOS lookup type 3 時でのみ使われる |
---|---|---|
0x0002 | ignoreBaseGlyphs | GDEF で定義された class = 1 (単一文字) のグリフを無視 |
0x0004 | ignoreLigatures | GDEF で定義された class = 2 (合字) のグリフを無視 |
0x0008 | ignoreMarks | GDEF で定義された class = 3 (マーク) のグリフを無視 |
0x0010 | useMarkFilteringSet | ON で、markFilteringSet が存在する |
0x00E0 | reserved | 予約 (0) |
0xFF00 | markAttachmentType | 0 でない場合、GDEF の MarkAttachClassDef で定義されたマークグリフのクラスと比較し、グリフのクラス値が異なる場合は、無視する |
Lookup Type
Lookup テーブルの lookupType は、「どのようなグリフをどのように処理するか」という値となります。
GSUB と GPOS で値の意味が異なります。
GSUB の場合は、以下のように定義されています。
GSUB と GPOS で値の意味が異なります。
GSUB の場合は、以下のように定義されています。
1 | Single Substitution | 単一のグリフを、別の一つのグリフに置き換えます。 一番単純な置き換えです。 |
---|---|---|
2 | Multiple Substitution | 単一のグリフを、別の複数のグリフに置き換えます。 合字分解などで使います。 |
3 | Alternate Substitution | 関連する複数のグリフの中から、任意で一つを選択して置き換えます。 |
4 | Ligature Substitution | 複数のグリフを、単一のグリフに置き換えます。 合字などで使われます。 |
5 | Contexual Substitution | 1つ以上のグリフを、文脈に応じて置き換えます。 |
6 | Chaining Contexual Substitution | - |
7 | Extension Substitution | Offset32 の位置にサブテーブルを格納するために使われます。 |
8 | Reverse Chaining Contexual Single Substitution | - |
Lookup のサブテーブル
Lookup テーブルには、サブテーブルが複数個格納されています。
そのサブテーブルのデータを使って、グリフの検索と置き換えを行います。
サブテーブルでは、Lookup Type ごとに、複数のフォーマットが定義されています。
(LookupType = 1 : format = 1,2.. など)
例えば、GSUB の「LookupType = 1」では、2種類のフォーマットが定義されており、format 1 or 2 のサブテーブルが複数個格納されています。
このデータの中から、対象となるグリフに適合するものを探し、そのフォーマットに応じた変換方法で、別のグリフへと変換します。
ここではまず、一番単純な LookupType 1 と 7 のサブテーブルを解説します。
そのサブテーブルのデータを使って、グリフの検索と置き換えを行います。
サブテーブルでは、Lookup Type ごとに、複数のフォーマットが定義されています。
(LookupType = 1 : format = 1,2.. など)
例えば、GSUB の「LookupType = 1」では、2種類のフォーマットが定義されており、format 1 or 2 のサブテーブルが複数個格納されています。
このデータの中から、対象となるグリフに適合するものを探し、そのフォーマットに応じた変換方法で、別のグリフへと変換します。
ここではまず、一番単純な LookupType 1 と 7 のサブテーブルを解説します。
LookupType 1 のサブテーブル
GSUB の「LookupType = 1」は、「単一グリフから単一グリフ」への変換を行います。
2種類のフォーマットが定義されています。
Coverage テーブルは、元となるグリフを検索するためのデータです。
このテーブル内で指定グリフが見つかった場合、そのフォーマットに従って、グリフを変換します。
2種類のフォーマットが定義されています。
Coverage テーブルは、元となるグリフを検索するためのデータです。
このテーブル内で指定グリフが見つかった場合、そのフォーマットに従って、グリフを変換します。
format 1
元のグリフ ID から指定値を増減させて、グリフ ID を取得します。uint16 substFormat | フォーマット番号 = 1 |
---|---|
Offset16 coverageOffset | Coverage テーブルへのオフセット位置。 (このサブテーブルの先頭を 0 とする) |
int16 deltaGlyphID | 元のグリフ ID から変換後のグリフ ID への増減値。 加算した後、0xFFFF で AND する必要があります。 |
format 2
置き換え後のグリフ ID は、配列から取得します。uint16 substFormat | フォーマット番号 = 2 |
---|---|
Offset16 coverageOffset | Coverage テーブルへのオフセット位置 (format 1 と同じ) |
uint16 glyphCount | 配列の数 |
uint16 substituteGlyphIDs[GlyphCount] | 変換後のグリフ ID の配列。 Coverage テーブルで示されるグリフ数と同じ数が必要。 Coverage format = 1 の場合は、グリフが見つかった位置の配列インデックス値を使う。 Coverage format = 2 の場合は、Coverage で算出されたインデックス値を使う。 |
LookupType 7 のサブテーブル
「LookupType 7」は、サブテーブルの合計サイズが 16 bit の範囲を超える場合に、Offset32 のオフセット位置にサブテーブルを格納するために使います。
uint16 substFormat | フォーマット番号 = 1 |
---|---|
uint16 extensionLookupType | 実体の LookupType。7 以外。 すべてのサブテーブルで、この LookupType が適用される。 |
Offset32 extensionOffset | 実体のサブテーブルへのオフセット位置。 (このサブテーブルの先頭を 0 とする) |
Coverage テーブル
対象となるグリフ (GSUB では、置き換え元のグリフ) を検索するためのデータです。
2種類のフォーマットがあります。
▼ RangeRecord
2種類のフォーマットがあります。
format 1
グリフ ID の配列から検索します。uint16 coverageFormat | フォーマット番号 = 1 |
---|---|
uint16 glyphCount | 配列の数 |
uint16 glyphArray[glyphCount] | グリフ ID の配列。数値の小さい順に並んでいる。 |
format 2
グリフ ID の範囲から検索します。uint16 coverageFormat | フォーマット番号 = 2 |
---|---|
uint16 rangeCount | RangeRecord の数 |
RangeRecord rangeRecords[rangeCount] | RangeRecord の配列。 グリフ ID の値は小さい順で、値の重複はしていない。 |
▼ RangeRecord
uint16 startGlyphID | 範囲の最初のグリフ ID |
---|---|
uint16 endGlyphID | 範囲の最後のグリフ ID |
uint16 startCoverageIndex | startGlyphID に対応した Coverage インデックス値。 Coverage Index = glyphID - startGlyphID + startCoverageIndex |
プログラム (1) - LookupList 一覧表示
>> 19a_gsub_lookuplist.c
LookupList テーブルデータの一覧を表示するプログラムです。
FeatureList を読み込んで、各 LookupList インデックスを参照している FeatureList の featureTag も一緒に表示しています ('aalt' 'ccmp' など)
ただし、同じ LookupList インデックスが複数のタグで参照される場合があるため ('vert' 'vrt2' など)、最初に参照された時のタグのみ表示しています。
また、FeatureList から参照されない LookupList インデックスが存在する場合もあります。
それらは、LookupType 5・6 で参照されます。
LookupList テーブルデータの一覧を表示するプログラムです。
---- LookupList ---- ==== [0] offset:110 | 'aalt' ==== {Lookup} lookupType <1> | lookupFlag:0x0000 | subTableCount:1 # {SubTable} offset:22912 | format <2> ==== [1] offset:118 | 'aalt' ==== {Lookup} lookupType <3> | lookupFlag:0x0000 | subTableCount:1 # {SubTable} offset:24352 | format <1> ==== [2] offset:126 | 'ccmp' ==== {Lookup} lookupType <4> | lookupFlag:0x0000 | subTableCount:1 # {SubTable} offset:950 | format <1>
FeatureList を読み込んで、各 LookupList インデックスを参照している FeatureList の featureTag も一緒に表示しています ('aalt' 'ccmp' など)
ただし、同じ LookupList インデックスが複数のタグで参照される場合があるため ('vert' 'vrt2' など)、最初に参照された時のタグのみ表示しています。
また、FeatureList から参照されない LookupList インデックスが存在する場合もあります。
それらは、LookupType 5・6 で参照されます。
プログラム (2) - LookupType 1 の置き換え情報表示
>> 19b_gsub_type1.c
LookupList の全データから、LookupType 1 のデータを読み込み、グリフの置き換え情報を表示するプログラムです。
「output.txt」に出力されます。
[] 内がグリフ ID で、() 内が Unicode 文字です。
グリフ ID に対応する Unicode がない場合は、(none) となっています。
LookupType 1 では、「substFormat = 1, 2」&「CoverageFormat = 1, 2」の4通りのフォーマットがあることになりますが、「源ノ角ゴシック」「源ノ明朝」では、この4通りすべてのフォーマットが存在していました。
LookupList の全データから、LookupType 1 のデータを読み込み、グリフの置き換え情報を表示するプログラムです。
「output.txt」に出力されます。
==== [47] ==== {Lookup} lookupType <1> | lookupFlag:0x0000 | subTableCount:1 # {SubTable} foramt <2> / {Coverage} format <2> [716] (―) U+2015 => [59887] (︱) U+FE31 [727] (‥) U+2025 => [59886] (︰) U+FE30 [728] (⋯) U+22EF => [59885] (︙) U+FE19 [890] (⎰) U+23B0 => [64408] (none) [891] (⎱) U+23B1 => [64409] (none) [1397] (、) U+3001 => [59877] (︑) U+FE11 [1398] (。) U+3002 => [59878] (︒) U+FE12 [1402] (〆) U+3006 => [64412] (none) [1404] (〈) U+3008 => [59901] (︿) U+FE3F [1405] (〉) U+3009 => [59902] (﹀) U+FE40 [1406] (《) U+300A => [59899] (︽) U+FE3D [1407] (》) U+300B => [59900] (︾) U+FE3E ...
[] 内がグリフ ID で、() 内が Unicode 文字です。
グリフ ID に対応する Unicode がない場合は、(none) となっています。
LookupType 1 では、「substFormat = 1, 2」&「CoverageFormat = 1, 2」の4通りのフォーマットがあることになりますが、「源ノ角ゴシック」「源ノ明朝」では、この4通りすべてのフォーマットが存在していました。
プログラム (3) - グリフ画像
「プログラム (2)」では、テキストで表示できないグリフも多数あるため、このままではすべてのグリフを確認できません。
そこで、FreeType を使って、グリフを描画します。
(ここでは、FreeType の使い方の解説は行いません)
>> 19c_gsub_glyph.c
fontfile.c、image.c、ftlib.c も併せてコンパイルしてください。
また、FreeType のライブラリをリンクしてください。
LookupList の全データの中から、LookupType 1 のデータを全て処理し、左に置き換え前グリフ、右に置き換え後のグリフを描画します。
「page<番号>.bmp」のファイル名で、BMP 画像で出力します。
そこで、FreeType を使って、グリフを描画します。
(ここでは、FreeType の使い方の解説は行いません)
>> 19c_gsub_glyph.c
fontfile.c、image.c、ftlib.c も併せてコンパイルしてください。
また、FreeType のライブラリをリンクしてください。
LookupList の全データの中から、LookupType 1 のデータを全て処理し、左に置き換え前グリフ、右に置き換え後のグリフを描画します。
「page<番号>.bmp」のファイル名で、BMP 画像で出力します。