[41] OpenType Layout >>48, >>40 (OTL) >>40 の機能 (フィーチャー, フォント機能) は、 OpenType フォントを使って各用字系、言語の適切な文字のレンダリングを行うためのグリフ置換や位置調整を行うもので、 そのための情報が各フォントに格納されています。
[43] OpenType Layout における機能は組版的な能力各種を表すものと説明されています。 >>37
[98] 機能は、 フォント中のグリフをある用字系や言語で文章を layout するためどのように使うかの情報を提供するものです。 >>6
[99] 例えばアラビア文字のフォントでは initial glyph form (語頭形のグリフ) に置換する機能を持つかもしれませんし、 漢字のフォントではグリフを垂直に位置付けする (縦書きの) ための機能を持つかもしれません。 >>6
[44] 機能は正しい文字のレンダリングに必須となるものもあれば、 利用者 (著者) の要望に応じてオプションで適用できるものもあります。
[45] 機能を活性化すると、 グリフを条件に応じて他のグリフに置き換えたり、 グリフの位置を調整したりします。 その規則はフォント依存であり、フォント内にそのための情報が入っています。
[47] 機能は低水準の操作とされており >>37、 必ずしもそれだけで正しい文字のレンダリングができるわけではなく、 事前に shaping が必要になります。
[22] 各機能はタグ (機能タグ) で識別されます。 >>6
[100]
OpenType では表, 用字系, 言語などでタグが使われています
[101] 慣習として、登録されている機能タグはすべて小文字を使っています。 >>6 実際には数字も使われているので、これは大文字を使わないという意味のようです。 英数字以外は使われていません。
[102] 4つのASCII大文字の機能タグは、 事業者空間として予約されています。 フォント事業者は、 私的な機能の識別のためにこれを使うことができます。 私的な機能の相互運用性は保証されません。 >>6
[112]
Microsoft は、フォント開発者が登録済みの機能の機能を実装するときは登録済みの機能タグを使うことを推奨しつつも、
フォント開発者が自身で機能を定義し登録することも認めています。
>>6
[113] 登録申請する機能は、 機能タグによって明確に識別される単一の機能性を持たなければなりません。 >>6
[114] 機能性は、最低の有用性の水準において定義されるべきで、 登録済みの他の機能と明らかに異ならなければなりません。 >>6
[8]
OpenType フォントでは
GSUB
表 (グリフの置換),
GPOS
表 (グリフの位置の調整)
に情報が格納されています。
[71]
OpenType フォントでは、
BASE
表 (基線)
にも情報を格納できます。
[49]
なお、 OpenType Layout としては他に
JSTF
, GDEF
各表があります。
[52]
GSUB
表や
GPOS
表では用字系と言語系の組に対して適用される機能を指定できます。
[72]
GSUB
と GPOS
は、
用字系 → 言語系 → 機能 → lookup
という構造になっています >>73, >>76。
用字系と言語系が決まると、
それに対して適用可能な機能の一覧を取得できます。
[53]
GSUB
と GPOS
それぞれ、
用字系と言語系の組に対して高々1つの機能は必須と指定でき、
その他は任意となります。
>>51
[55] この「必須」をどう処理するべきかは定かではありません。例えば未知の機能タグのとき、 どう処理するのが適切なのか不明です。
[56] 「必須」は高々1つしか指定できません。1つの機能に複数の lookup を指定できるので機能性に制約はない >>51 と説明されています。仕様書のこの説明は謎で、 意味的に別の機能でも制約回避のために適当な機能タグでまとめてしまえということなのでしょうか。
[57] 実際のフォントでは言語系的に必須そうなものでもすべてを任意扱いにしていることが多いみたいです。 相互運用性を考えるとフォントごとにまちまちな「必須」で適当に機能が選ばれることを期待するより、 実装側で用字系と言語系 (と shaping engine の判断) に応じて適切な機能を有効にするべきなのでしょう。
[74]
GSUB
, GPOS
の各機能は、
それぞれ必ず適用するべきもの、
ある条件下で適用するべきもの、
著者が任意選択で適用できるもの、
と決められています。
[61]
GSUB
, GPOS
の各機能は、
それぞれまったく個別に適用するのではなく、
いくつかまとめて実行できます。
表中の lookup の配置によりフォント開発者は相互作用を制御できます
>>51。
[62] しかしすべての機能が一度にまとめて処理されるとは限りません。 全体的な処理のどの段階でどの機能を処理するかは OpenType 仕様としては決められていません。 >>51
[64] 実際上どうなっているのかは shaping 参照。
[75] 適用するべき機能を決定した後、 Feature Variation 表がある場合には、 それに従って適宜調整します。 >>73, >>76
[109] 機能によっては lookup の種別の提案が説明に含まれています。 しかしこれは推奨、提案に過ぎません。 lookup をどのように使って機能を実装するかは、 プラットフォーム、応用、フォント、フォント開発者によって違って構いません。 >>6
[110] 従ってフォントの実装はすべての機能とすべての lookup の種別の組み合わせがあり得ると想定する必要があります。 実際には実用に供されている実装の多くは問題なく対応できるようですが、 フォントを読み書きするライブラリーの類の中には lookup の種別によっては対処できないものもあるようです。
[60] 全体的な処理の流れは文字のレンダリング, shaping 参照。
[59]
GSUB
, GPOS
の処理方法は各項参照。
[103] OpenType 仕様書の機能タグの登録簿には、各機能の説明があります。
[105] しかし、グリフの置換や位置付けを適切に実装するために必要なすべての情報を提供していないことがあります。 >>6
[106]
また、フォントの GSUB
や GPOS
にも text processing において機能をいつどこに適用するべきかの情報が含まれていないことがあります。
[107] 多くの場合には text processing client は追加のデータが必要となります。 >>6
[108] すべてに於いて text processing client は機能の適用、結合、仲裁を経て結果をレンダリングすることに責任を有します。 >>6
[104]
例えば語頭形を表す init
について、 GSUB
にはそれをいつどこに適用するかの情報がありません。
アラビア文字の文章に於いては character context と joining 特性に基づき
connected letter group
の始まりを特定し、どのグリフに init
機能を適用して
initial glyph form に変更するかを text processing client は決めなければなりません。
>>6
[111] 機能におっては text layout software が機能とどう相互作用することが期待されるか、 機能固有の詳細を説明しているものもあります。 >>6
[66] 機能は、 機能引数群表を指定させることができます。 機能により必須とも、任意ともできます。 >>65
[67]
GSUB
表や
GPOS
表の機能表には
featureParamsOffset
欄があります。
欄の値は機能表の先頭からの Offset です。
>>65
[68]
機能において機能引数群表が定義されていない場合や、
定義されていても使用しない場合には、
NULL
としなければなりません。
>>65
[70]
必須なのに NULL
が指定された場合や、
定義されていないのに非 NULL
が指定された場合に実装がどう処理するべきかは不明です。
[42] 機能は OpenType 仕様書内の登録簿で規定されています >>6。
[38] 登録簿は期待される用法を書いているものの、 応用は他の仕様書や用途に応じて適宜仕立てして構わないとされています。 >>37
[15]
仕様書の登録簿の説明は実装に必要な情報が何も書かれていなかったり、
実装方法がわからないことが書かれていたり (GSUB
の結果文字コードが変わるから新旧とも覚えておけとか)
やばいのが多い...
[16] 似たようなものが違って説明されていて一貫性がないのが、 意図的なのかどうか判断つかないとか。
[17]
いろいろな機能が他の機能や利用者との相互作用で「override」
したりされたりすると説明されているのだが、
それが処理全体のどの段階で何をどうすることが意図されているのか判断しかねるのが多い。
例えば A の GSUB
が B の GSUB
を override するとして、
A と B が適用されたとき実装はどうするのが正解なのか。
フォントはどう作るのが正しいのか。
B が先にグリフを置換していたら override もなにも A
の適用の前提がなくなる可能性がある。
実装は B を抑制するべきなのか。
フォントは B の出力が A の入力に来ることを想定するべきなのか。
[32] CSS Fonts は一応 OpenType に限定しない形でフォントの特性の記述とその利用の方法を規定しつつも、 OpenType の機能との対応関係を示しています。 特性は OpenType の機能にほぼ対応するよう設計されていて、 将来の新しいフォント技術はそれを踏襲するよう要請しています。
[33] そのような建付けにした上で、 CSS としての各機能の説明やフォント開発者に対する推奨が仕様書で説明されています。 実質的に OpenType の機能の利用方法を補足説明するものとして利用できます。
font-feature-settings
(CSS)[29]
CSS では
font-feature-settings
プロパティーで適用する機能を指定できます。
>>30
[1] しっぽり明朝|商用・同人誌利用可能フリーフォント, , https://fontdasu.com/shippori-mincho/
GSUB
ss01
- ss02
(引数なし),
aalt ccmp dlig frac fwid hwid jp78 jp83 liga nlck ordn salt sups vert vkna vrt2
GPOS
abvm mark mkmk palt vpal
[2] GPOSのCursive Attachment Positioningについて - にせねこメモ, https://nixeneko.hatenablog.com/entry/2017/01/14/200258
[3] OpenTypeフォントで万年カレンダーをつくる - にせねこメモ, https://nixeneko.hatenablog.com/entry/2017/02/13/000000
(lookupType
1 substFormat
2,
lookupType
4 substFormat
1,
lookupType
6 substFormat
3)
(lookupType
1 substFormat
1)
GSUB
"
" (0x20
× 4), calt
, ccmp
, dlig
, fina
, frac
, init
, isol
, liga
, lnum
, locl
, medi
, vert
, vkna
, vrt2
, zero
(lookup 1 - 1, 1 - 2, 4 - 1, 6 - 2, 6 - 3)
GSUB
aalt
, ccmp
, frac
, fwid
, hwid
, ital
, jp78
, liga
, ordn
, sups
, trad
, vert
, vkna
, vrt2
(1, 2; 3, 1; 2, 1; 4, 1; 6, 3; 1, 1)
GSUB
:
aalt
, ccmp
, fwid
, hwid
, jp04
, jp78
, jp83
, jp90
, liga
, palt
, pwid
, salt
, ss01
, ss02
, ss03
, ss05
, ss06
, ss07
, ss11
, ss12
, ss20
, trad
, vert
, vkna
, vrt2
(1, 2; 3, 1; 4, 1; 1, 1)
GSUB
:
aalt
, ccmp
, dlig
, fwid
, hist
, hwid
, jp78
, jp83
, jp90
, liga
, locl
, nlck
, pwid
, vert
, vrt2
(1, 2; 3, 1; 4, 1; 1, 1)
GPOS
:
halt
, kern
, palt
, vhal
, vkrn
, vpal
(1, 1; 2, 1; 2, 2; 1, 2)
GSUB
:
aalt
, ccmp
, dlig
, expt
, frac
, fwid
, hojo
, hwid
, jp78
, jp83
, jp90
, liga
, nalt
, nlck
, numr
, ruby
, sups
, trad
, vert
, vrt2
, zero
(1, 2; 3, 1; 4, 1; 1, 1)
[25]
>>24 ruby
で「、」「。」の点が中央に移動します。
果たしてそれがルビに適したグリフと言えるのかは疑問。
GSUB
:
(空白4つ), abvf
, abvs
, akhn
, blwf
, blws
, ccmp
, clig
, half
, init
, liga
, nukt
, pref
, pstf
, psts
, rlig
, rphf
, vatu
(4, 1; 2, 1; 1, 2; 6, 3; 1, 1)
GPOS
:
abvm
, blwm
, mkmk
(4, 1; 6, 1)
GSUB
:
c2sc
, case
, ccmp
, cv01
, cv02
, cv03
, dnom
, frac
, liga
, locl
, numr
, onum
, pnum
, smcp
, ss01
, ss02
, subs
, sups
(7, 1 (1, 1); 7, 1 (1, 2); 7, 1 (2, 1); 7, 1 (4, 1); 7, 1 (6, 3))
GPOS
:
kern
, mark
, mkmk
(4, 1; 6, 1; 9, 1 (2, 1); 9, 1 (2, 2))
GSUB
:
dtls
, onum
, salt
, ssty
(1, 1; 1, 2; 3, 1)
[31] Iosevka, https://be5invis.github.io/Iosevka/
- 和文の句読点や括弧が連続したときのアキを自動調整するフォント。
- GPOSのchws/vchwで自動調整します。
[82] 西暦表記を元号による表記にするフォント: mottainaiDTP, http://mottainaidtp.seesaa.net/article/425166883.html
[83] 3桁ごとにカンマが発生するフォント: mottainaiDTP, http://mottainaidtp.seesaa.net/article/395328634.html
[94] 小数点以下の数字が小さく表示されるフォント: mottainaiDTP, https://mottainaidtp.seesaa.net/article/429751961.html?seesaa_related=category
[85]
BabelStone Han
liga
,
calt
[86] UnifrakturMaguntia, a Unicode Fraktur Font, , https://unifraktur.sourceforge.net/maguntia.html
ss
, cv
,
hlig
, dlig
,
tnum
, lnum
,
liga
, ccmp
[89] How to enable stylistic sets · tonsky/FiraCode Wiki · GitHub, https://github.com/tonsky/FiraCode/wiki/How-to-enable-stylistic-sets
[91] Download - Abyssinica SIL, https://software.sil.org/abyssinica/download/
cv
, 言語
[95] OpenTypeフォントで万年カレンダーをつくる - にせねこメモ, https://nixeneko.hatenablog.com/entry/2017/02/13/000000
[97] Details of available Stylistic Sets · Issue #246 · adobe-fonts/source-code-pro · GitHub, https://github.com/adobe-fonts/source-code-pro/issues/246
[19]
GSUB
lookup が適用された結果、直接または間接に、元の入力に戻ることもあります。
[40] OpenType glyph processing (part 1) - Typography | Microsoft Docs, alib-ms, https://docs.microsoft.com/ja-jp/typography/develop/processing-part1#opentype-fonts
[50] pango で縦書きとその能力, , https://cat-in-136.github.io/2016/04/pango-view-vertical-writing.html
[77] CSS での OpenType 機能の構文, https://helpx.adobe.com/jp/fonts/using/open-type-syntax.html
[92] Safari で Osaka フォントの表示不具合を CSS で対処 | Memorandom, , https://memorandom.whitepenguins.com/posts/safari-osaka/
[93] >>92 配置がずれる謎の不具合を palt
で回避する。なんかよくわからんけど
palt
を有効にすると文字幅計算方法が変わってまともになるってコト!?
[96] エディターで制御文字を表示したいとか、結合文字の点線を表示したいとか、 空き領域の符号位置を表示したいとか、みたいな目的で使える機能があればいいのになあ。