[120] 
[[OpenType]]
ではいろいろな[[文字コード]]が使われます。

* 仕様書

[REFS[
-
[1] [CITE@en-us[cmap - Character To Glyph Index Mapping Table ([[OpenType]] 1.9) - Typography | Microsoft Docs]]
([[PeterCon]], [TIME[2022-08-16T01:57:58.000Z]])
<https://docs.microsoft.com/en-us/typography/opentype/spec/cmap>
-
[2] [CITE@en[Character to Glyph Mapping Table - [[TrueType]] Reference Manual - Apple Developer]]
([[Apple Inc.]], [TIME[2022-07-12T17:06:26.000Z]], [TIME[2022-08-16T01:58:07.176Z]])
<https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6cmap.html>
-
[121] 
[CITE@ja-jp[[[name]] - Naming table (OpenType 1.9) - Typography | Microsoft Learn]], [[PeterCon]], [TIME[2022-12-31T07:50:08.000Z]] <https://learn.microsoft.com/ja-jp/typography/opentype/spec/name#naming-table-header>

]REFS]

* 概要

[39] 
[[OpenType]] における[[文字コード]]には2つの側面があります。

- [40] 1つは、[[フォント]]に関係する[[文字列]]データの記述に使われるものです。
例えば [CODE[name][name (OpenType)]] [[表][OpenType表]]の[[フォント名]]が関係します。
- [41] 1つは、[[フォント]]に格納された[[グリフ]]データの参照 (利用)
方法としての[[文字]]の記述に使われるものです。
具体的には [CODE[cmap]] [[表][OpenType表]]が[[文字コード]]と[[グリフID]]の対照表となっています。

[42] 
[CODE[name][name (OpenType)]] [[表][OpenType表]]と
[CODE[cmap]] [[表][OpenType表]]は、
利用する[[文字コード]]を記述し、その[[文字コード]]によって[[文字]]を記述または参照しています。

[43] 
その他のいくつかの[[文字]]データは[[符号化方式]]が[[決め打ち]]です。

- [44] [[タグ][OpenTypeタグ]]は [[UTF-8]] (ただし [[ASCII]] のみ) です。
- [118] [CODE[meta][meta (OpenType)]]のテキストデータは [[UTF-8]] です。
- [45] [[グリフ名]]
- [136] [CODE[name][name (OpenType)]] の[[言語タグ]]は [[UTF-16BE]] です。
- [38] その他、 [[UTF-16BE]] が使われることがあります。

[119] 
[CODE[GSUB]] や [CODE[GPOS]] では[[グリフID]]が使われます。
[[文字コード]]と[[グリフ]]符号の違いに注意。
[[OpenType]] の[[グリフID]]は個々の[[フォント]]が独自に決定できる[[フォント]]内部の記述用のもので、
[[情報交換]]には適しません。
(ただし[[グリフ名]]と[[CID]]も参照。)

* 文字符号化

[49] 
[CODE[cmap]] [[表][OpenType表]]には異なる[[文字符号化]]の[[部分表]]を含められます。
[[文字符号化]]は、
([CODE[platformID]], [CODE[encodingID]], [CODE[language]])
の3つの値の組で識別されます。
[SRC[>>1]]


[68] 
[[Unicode部分表]]とその他の何種類かの[[部分表]]は、
[[Unicode]] の[[符号位置]](列)から[[グリフID]]への対応関係を表します。
その他の[[部分表]]は、
[[非Unicode]]の[[文字符号化]]から[[グリフID]]への対応関係を表します。

;; [69] 現在ではほぼすべての実装が [[Unicode]] を使って [CODE[cmap]]
を引いています。以前 ([[平成時代]]初期頃まで) は[[非Unicode]]
の実装もありました。
現在では[[非Unicode]]の [CODE[cmap]] [[部分表]]を含まない[[フォント]]も多いです。
[[MacRoman]] の [CODE[cmap]] [[部分表]]を含む[[フォント]]も多いですが、
[[互換性]]のためというよりは、[[互換性]]が必要だった時代の名残りの慣習と思われます。
現在使われている[[フォント]]の [[MacRoman]] [CODE[cmap]]
は使い物にならないおかしなデータのことも多いです。



** [CODE[platformID]]

[50] 
[DFN[[CODE[platformID]]]]
は、
次のいずれかです。

[FIG(table)[ [51] [CODE[platformID]]

:v: [[数値]]
:n: 名前 [SRC[>>1, >>121]]
:name:[CODE[name][name (OpenType)]] [SRC[>>121]]
:cmap:[CODE[cmap]] [SRC[>>1]]
:note: メモ

:v:[N[0]]
:n:Unicode
:name:○
:cmap:○

:v:[N[1]]
:n:Macintosh
:name:○
:cmap:○

:v:[N[2]]
:n:[I[ISO [deprecated__&&]&&__]]
:note: [[OpenType]] 1.3 から[RUBYB[[[非推奨]]][deprecated]]
[SRC[>>1]]
:cmap:○

:v:[N[3]]
:n:Windows
:name:○
:cmap:○

:v:[N[4]]
:n:Custom
:cmap:○

:v:[ [N[240]], [N[255]] ]
:note:[[利用者定義]]の[[プラットフォーム]]に[RUBYB[[[予約]]][reserved]]
[SRC[>>1]]
:cmap:○
:name: >>135

]FIG]

[55] 
[CODE[platformID]] は [CODE[encodingID]] の[[名前空間]]を区別する役割がありますが、
それ以外の意味も処理方法も規定がありません。例えば [[Linux]]
の実装が [[Windows]] [CODE[platformID]] を使ってはいけないということはありません。
[[プラットフォーム]]ごとに[[文字コード]]の体系がまったく違っていた旧時代の[[遺物]]と考えるべきなのでしょう。

[53] 
すべての値に対応しなければならないとする規定はありません。
未対応のものは無視して構わないと思われます。

[52] 
未知の値に遭遇したときどう処理するべきか不明確です。
それが含まれるものは無視するのが妥当でしょう。

[54] 
利用者定義の値について、使い方に何の規定もありません。
[CODE[encodingID]] は好きに使って良いのでしょう。
未知の値は無視して構わないと考えるのが妥当でしょう。

[74] 
[F[[CODE[platformID]]]] [N[1]] ([[Macintosh]])
の 
[CODE[cmap]] [[部分表]]はかつての [[Macintosh]] では[RUBYB[[[必須]]][required]]でしたが、
現在の [[Apple]] の[[プラットフォーム]]では[RUBYB[[[非推奨]]][discouraged]]です。
[SRC[>>1]]


** [CODE[encodingID]]

[70] 
[DFN[[F[[CODE[encodingID]]]]]]
の意味は
[F[[CODE[platformID]]]] に依存します。
[CODE[encodingID]]
には次のものがあります。

[FIG(table)[

:p:[F[[CODE[platformID]]]]
:e:[F[[CODE[encodingID]]]]
:o:[CITE[OpenType]] の説明 [SRC[>>1]]
:r:制限 [SRC[>>1]]
:u:[[Unicode部分表]]
:note:メモ

:p:[N[0]] ([[Unicode]])
:e:[N[0]]
:o:[[Unicode 1.0]] semantics
:r:[RUBYB[[[非推奨]]][deprecated]] [SRC[>>1, >>121]]
:u:○
:note:[[UTF-16BE]] [SRC[>>121]]

:p:[N[0]] ([[Unicode]])
:e:[N[1]]
:o:[[Unicode 1.1]] semantics
:r:[RUBYB[[[非推奨]]][deprecated]] [SRC[>>1, >>121]]
:u:○
:note:[[UTF-16BE]] [SRC[>>121]]

:p:[N[0]] ([[Unicode]])
:e:[N[2]]
:o:[[ISO/IEC 10646]] semantics
:r:[RUBYB[[[非推奨]]][deprecated]] [SRC[>>1, >>121]]
:u:○
:note:[[UTF-16BE]] [SRC[>>121]]

:p:[N[0]] ([[Unicode]])
:e:[N[3]]
:o:[[Unicode 2.0]] and onwards semantics, [[Unicode BMP]] only
:r:[CODE[cmap]]: 
[[部分表]] [F[[CODE[format]]]] [N[4]], [N[6]] で使う[RUBYB[べき][should]] [SRC[>>1]],
[CODE[name][name (OpenType)]] [SRC[>>121]]
:u:○
:note:[[UTF-16BE]] [SRC[>>121]]

:p:[N[0]] ([[Unicode]])
:e:[N[4]]
:o:[[Unicode 2.0]] and onwards semantics, [[Unicode]] full repertoire
:r:[CODE[cmap]] :
[[部分表]] [F[[CODE[format]]]] [N[10]], [N[12]] で使う[RUBYB[べき][should]] [SRC[>>1]],
[CODE[name][name (OpenType)]] [SRC[>>121]]
:u:○
:note:[[UTF-16BE]] [SRC[>>121]]

:p:[N[0]] ([[Unicode]])
:e:[N[5]]
:o:[[Unicode Variation Sequences]]
:r:[CODE[cmap]] :
[[部分表]] [F[[CODE[format]]]] [N[14]] でのみ使う[RUBYB[べき][should]] [SRC[>>1]]
([CODE[name][name (OpenType)]] にはなし)
:u:○

:p:[N[0]] ([[Unicode]])
:e:[N[6]]
:o:[[Unicode]] full repertoire
:r:[CODE[cmap]] :
[[部分表]] [F[[CODE[format]]]] [N[13]] でのみ使う[RUBYB[べき][should]] [SRC[>>1]]
([CODE[name][name (OpenType)]] にはなし)
:u:○

:p:[N[0]] ([[Unicode]])
:e:[N[10]]
:note:
[[Unicode符号点]]。
[[仕様書]]にないが利用例あり。
:u:○

:p:[N[0]] ([[Unicode]])
:e:その他
:u:○

:p:[N[1]] ([[Macintosh]])
:e:[[script manager code]]
:r:
[CODE[cmap]] : [RUBYB[非推奨][discouraged]] [SRC[>>1]],
[CODE[name][name (OpenType)]]

:p:[N[2]] ([[ISO]])
:e:[N[0]]
:o:7-bit [[ASCII]]
:r:
[CODE[cmap]] : [RUBYB[[[非推奨]]][deprecated]]

:p:[N[2]] ([[ISO]])
:e:[N[1]]
:o:[[ISO 10646]]
:r:
[CODE[cmap]] : [RUBYB[[[非推奨]]][deprecated]]

:p:[N[2]] ([[ISO]])
:e:[N[2]]
:o:[[ISO 8859-1]]
:r:
[CODE[cmap]] : [RUBYB[[[非推奨]]][deprecated]]

:p:[N[2]] ([[ISO]])
:e:その他

:p:[N[3]] ([[Windows]])
:e:[N[0]]
:o:[[Symbol]]
:note:[SEE[ [[symbol encoding]] ]]
:r:
通常は [CODE[cmap]] [F[[CODE[format]]]] [N[4]]。
新たには [[Unicode]] を使う[RUBYB[べき][should]]。

:p:[N[3]] ([[Windows]])
:e:[N[1]]
:o:[[Unicode BMP]]
:u:○
:r:非 [[BMP]] [RUBYB[使用禁止][must not]]

:p:[N[3]] ([[Windows]])
:e:[N[2]]
:o:[[ShiftJIS]]

:p:[N[3]] ([[Windows]])
:e:[N[3]]
:o:[[PRC]]

:p:[N[3]] ([[Windows]])
:e:[N[4]]
:o:[[Big5]]

:p:[N[3]] ([[Windows]])
:e:[N[5]]
:o:[[Wansung]]

:p:[N[3]] ([[Windows]])
:e:[N[6]]
:o:[[Johab]]

:p:[N[3]] ([[Windows]])
:e:[N[7]]
:o:Reserved

:p:[N[3]] ([[Windows]])
:e:[N[8]]
:o:Reserved

:p:[N[3]] ([[Windows]])
:e:[N[9]]
:o:Reserved

:p:[N[3]] ([[Windows]])
:e:[N[10]]
:o:[[Unicode]] full repertoire
:u:○

:p:[N[3]] ([[Windows]])
:e:その他

:p: [N[4]] (Custom)
:e:[ [N[0]], [N[255]] ]
:o:
[CODE[cmap]] : OTF Windows NT compatibility mapping
:r:
[CODE[cmap]] [F[[CODE[format]]]] [N[0]], [N[6]] で[RUBYB[なければ][must]]。
新たに使う[RUBYB[べきではない][should not]]。

:p: [N[4]] (Custom)
:e:その他

:p:[ [N[240]], [N[255]] ]
:note:
[CODE[cmap]] : [[利用者定義]]に[[予約]]

:p:その他

]FIG]

[67] 
[CITE[OpenType]] [[仕様書]]では
[CODE[cmap]]
[[表][OpenType表]]の
[DFN[Unicode[RUBYB[[RUBY[部][ぶ]][RUBY[分][ぶん]][RUBY[表][ひょう]]][subtable]]]]という語が使われています。
[F[[CODE[platformID]]]] [N[0]]
と
[F[[CODE[platformID]]]] [N[3]]
[F[[CODE[encodingID]]]] [N[1]], [N[10]]
を表すとされています。
[SRC[>>1]]

[75] 
また [[Windows]] 用の[[フォント]]を作成するときは
[DFN[[RUBYB[[[Unicode]] [CODE[cmap]] [RUBY[部][ぶ]][RUBY[分][ぶん]][RUBY[表][ひょう]]][Unicode [CODE[cmap]] subtable]]]]を常に使う[RUBYB[べき][should]]ともされています。
この [[Unicode]] [CODE[cmap]] [[部分表]]は
[F[[CODE[platformID]]]] [N[3]]
[F[[CODE[encodingID]]]] [N[1]], [N[10]]
を意味するとされています。
[SRC[>>1]]

[123] 
[[Windows]] 用[[フォント]]
の
[CODE[name][name (OpenType)]]
については、
[F[[CODE[platformID]]]] [N[3]]
で
[F[[CODE[encodingID]]]] [N[1]] ([[Unicode]] フォント)
または
[F[[CODE[encodingID]]]] [N[0]] ([[Symbol font]])
とする[RUBYB[べきです][should]]。
[SRC[>>121]]

[122] 
[CODE[name][name (OpenType)]]
における
[F[[CODE[platformID]]]] [N[3]] ([[Windows]]) 
においては、
[CODE[encodingID]]
は、
[CODE[cmap]] の
[F[[CODE[platformID]]]] [N[3]] ([[Windows]]) 
の
[CODE[encodingID]]
と一致している[RUBYB[べきです][should]]。
[SRC[>>121]]


[78] 
[[Unicode]] の [[BMP]] のみと全体とは [CODE[format]] が違えば区別可能なはずです。
にも関わらず [CODE[encodingID]] と [CODE[format]] 
の両方に違う値を指定させて区別しています。
[CODE[format]] [N[13]] 専用の [CODE[encodingID]] もそうです。
[CODE[format]] だけでの区別では実装上の問題があったのでしょうか。

** Windows 符号化

[124] 
[CODE[name][name (OpenType)]]
の文字列は、
[F[[CODE[encodingID]]]] が [N[3]] ([[Windows]])
の場合、
[[UTF-16BE]]
で符号化しなければ[RUBYB[なりません][must]]。
[SRC[>>121]]

[125] 
これはつまり、 [CODE[cmap]] の [F[[CODE[encodingID]]]] と同じ値を指定する (>>122)
だけで、その値自体にはそれほど意味がなく、
値に関わらず [[UTF-16BE]] を使わなければならないということのようです。

[126] 
古い [[CJK]] [[フォント]]はこの規定に反していることがあります。
例えば [[MingLi]]
は、
[[ラテン文字]]名を [[UTF-16BE]] で[[符号化]]しながらも[[中文]]名は
[F[[CODE[encodingID]]]] [N[4]] ([[Big5]]) で文字列を [[CP950]]
で符号化していました。
[SRC[>>121]]

[127] 
これは [F[[CODE[platformID]]]] [N[1]] ([[Macintosh]])
が実際に指定された通りの[[符号化]]となるのと違う点です。

[128] 
さて、 [[OpenType]] の仕様はこの状況をどう処理するべきなのか何も語っていません。
現在となっては [F[[CODE[platformID]]]] [N[3]] ([[Windows]])
のデータを含む[[フォント]]は希少となっているようですが、
古い[[フォント]]を扱う必要がある (可能性がある) [[ソフトウェア]]は、
何らかの方針を立てて対処しなければなりません。

[129] 
[[CJK]] の[[コードページ]]なら[[コードページ]]通りの[[符号化]]、
それ以外なら [[UTF-16BE]]、としてしまっていいのでしょうか。
それなら楽なのですが、 [[CJK]] の[[コードページ]]で [[UTF-16BE]]
の[[フォント]]も出回っているなら、[[文字コード自動判定]]が必要となります。


-*-*-

[146] なお、
[CODE[OS/2][OS/2 (OpenType)]] [[表][OpenType表]]にはカバーしている[[コードページ]]を記述できます。

[145] 
[CITE@ja-jp[OS/2 - OS/2 and Windows metrics table (OpenType 1.9) - Typography | Microsoft Learn]], [[PeterCon]], [TIME[2023-01-01T12:55:55.000Z]] <https://learn.microsoft.com/ja-jp/typography/opentype/spec/os2#cpr>


** [CODE[platformID]] [N[4]]


[SEE[ [[OTF Windows NT compatibility mapping]] ]]



** 各IDの実利用例

[24] 
互換性のためか 
[CODE[platformID]] = 0 (Macintosh),
[CODE[encodingID]] = 0 ([[MacRoman]])
で、
[N[0x100]], [N[0x101]]
だけの 
[CODE[cmap]]
部分表が含まれる[[フォント]]がままあります。

[32] 
[CITE[[[Nishiki-teki]]]]
は
[CODE[platformID]] = 0 ([[Unicode]]),
[CODE[encodingID]] = 10
という 
[CODE[cmap]] subtable
を持っています。
でも
[CODE[platformID]] 0 [CODE[encodingID]] 10
は
[[Microsoft]] の仕様書にも [[Apple]] の仕様書にも載っていません。

[33] 
中身は [[Unicode]] のようです。
[CODE[platformID]] = 3 ([[Windows]])
だと
[CODE[encodingID]] = 10 が [[Unicode]] 
なので、
それの誤りなのでしょうか。


[34] 
[CITE[Makoto Comic]]
にも
[CODE[platformID]] = 0 ([[Unicode]]),
[CODE[encodingID]] = 10
があります。

* 言語ID

[130] 
[CODE[name][name (OpenType)]] では3種類の[[言語符号]]の体系が使われています。
[CODE[cmap]] ではそのうち1種類 (の変種) が使われています。
なお [[OpenType]] の他の場所では他の体系も使われています。
[SEE[ [[OpenTypeにおける言語]] ]]

-*-*-

[131] 
[CODE[name][name (OpenType)]] の項目を表す
[CODE[NameRecord]]
の
[DFN[[F[[CODE[languageID]]]]]]
は[[言語][自然言語]]を表します。

[132] 
[F[[CODE[languageID]]]] の値の意味は当該
[CODE[name][name (OpenType)]] 
[[表][OpenType表]]の
[F[[CODE[version][name (TrueType)]]]]
と
[CODE[NameRecord]]
の
[F[[CODE[platformID]]]]
に依存して決まります。
[SRC[>>121]]

[141] 
[CODE[name][name (OpenType)]]
で
[F[[CODE[platformID]]]] が [N[0]] ([[Unicode]]) 
の場合、
[F[[CODE[languageID]]]] [N[0]] を使うことができます。
この値は特定の[[言語]]を表しません。
[SRC[>>121]]

[143] 
[CODE[name][name (OpenType)]]
で
[F[[CODE[platformID]]]] が [N[1]] ([[Macintosh]]) 
の場合、
[F[[CODE[languageID]]]] 
には
[[Macintosh language ID]]
を指定できます。
[SRC[>>121]]

[144] 
[CODE[name][name (OpenType)]]
で
[F[[CODE[platformID]]]] が [N[3]] ([[Windows]]) 
の場合、
[F[[CODE[languageID]]]] 
には
[[Windows language ID]]
を指定できます。
[SRC[>>121]]

-*-*-

[133] 
[CODE[name][name (OpenType)]]
の
[F[[CODE[version][name (OpenType)]]]]
には 
[N[0]] と [N[1]]
がありますが、
[N[1]] のとき、
[[IETF言語タグ]]を任意個設定できます。
各 [CODE[NameRecord]]
はこの[[言語タグ]]を参照することによって[[言語][自然言語]]を記述できます。
[SRC[>>121]]

[134] 
[CODE[version][name (OpenType)]] [N[1]] では、
[F[[CODE[languageID]]]]
は
[N[0x8000]]
[[以上]]のとき、 [[言語タグ]]を表すと解釈され、
それ[[未満]]のとき、
[F[[CODE[platformID]]]]
依存の[[言語符号]]と解釈されます。
[SRC[>>121]]

[140] 
[CODE[version][name (OpenType)]] [N[0]] では、
[F[[CODE[languageID]]]]
は原則として
[N[0x8000]]
[[未満]]の値を使わなければ[RUBYB[なりません][must]]。
[SRC[>>121]]

[142] 
[CODE[version][name (OpenType)]] [N[0]] の
[F[[CODE[languageID]]]]
でも、
例外的に、
[F[[CODE[platformID]]]]
が
[ [N[240]], [N[255]] ]
のときは
[N[0x8000]]
[[以上]]の値を使うことが禁止されていません。
[SRC[>>121]]

;; [135] [CODE[name][name (OpenType)]] の [CODE[platformID]]
の規定には利用者定義が使えるとは書かれていない ([CODE[cmap]] の方にだけ書かれている)
のですが、このような規定があるのは謎です。

[137] 
[[IETF言語タグ]]を設定したときは、
[F[[CODE[languageID]]]] 
ではそれを [N[0x8000]], [N[0x8001]], ... といった値で参照できます。
数値は[[言語タグ]]が記述された順序で割り振られていきます。
[SRC[>>121]]

[138] 
指定された値に対応する[[言語タグ]]が存在していないときは、
[[言語]]は未知となります。そのような値は使う[RUBYB[べきではありません][should not]]。
[SRC[>>121]]

;; [139] [[OpenType]] 仕様にしては珍しく[[エラー処理]]らしきものが(少しだけ)決められています。
[[言語]]が未知ということは、特定の[[言語]]の値を探す処理では無視されるべきなのでしょうし、
どんな[[言語]]でもいいような処理では受理されるべきなのでしょう。
(未知の[[言語]]だから[[致死的エラー]]とすることも、必ずしも否定されていませんが...
ニュアンスとしてはそれはあまり好ましい挙動ではなさそうです。)



-*-*-

[93] 
[CODE[cmap]]
[[部分表]]の
[DFN[[F[[CODE[language]]]]]] 
は[[文字符号化]]の[[言語]]を表します。

[92] 
[F[[CODE[platformID]]]] [N[1]] ([[Macintosh]])
''以外''の
[CODE[cmap]] [[部分表]]の
[F[[CODE[language]]]]
は、
[N[0]]
でなければ[RUBYB[なりません][must]]。
[SRC[>>1]]

[94] 
[F[[CODE[platformID]]]] [N[1]] ([[Macintosh]])
の
[CODE[cmap]] [[部分表]]の
[F[[CODE[language]]]]
は、

- [RUBYB[言語依存][language-specific]]のとき、 [[Macintosh language ID]] + [N[1]]
- 言語依存でないとき、 [N[0]]

とします。
[SRC[>>1]]

[95] 
[[Mac OS Roman]]
[CODE[cmap]]
では、
言語依存の符号化ではありませんから、
[N[0]] 
としなければ[RUBYB[なりません][must]]。
[SRC[>>1]]

[EG[
[96] 
[[Mac OS Turkish]]
[CODE[cmap]]
では、
[[Turkish]] の [[Macintosh language ID]] が [N[17]]
なので、
[F[[CODE[language]]]]
は
[N[18]]
とします。
[SRC[>>1]]



]EG]

[105] 
[F[[CODE[language]]]] 
は
[F[[CODE[format]]]]
依存の[[部分表]]に属しています。
ということは古い
[[Macintosh]]
でしか使われていないこの欄をいつまでも残しておく必要も無さそうなものですが、
新しそうな
[CODE[format]]
でもそのまま引き継がれています。

[106] 
ただし
[CODE[format]] [N[14]]
には
[CODE[language]]
欄がありません。この [CODE[format]] だけ
[[Unicode]]
に完全に依存している
(= [CODE[language]] があってもまったく使いようがない)
関係なのでしょうかね。
(他は、少なくても理屈の上では、
[[Unicode]] に限定されていないので使い道がないとはいえない。)



* [CODE[cmap]] 表

[111] 
[CODE[cmap]] は一部例外を除き、1つの[[文字]] (を表す[[符号位置]]、[[ビット組合せ]])
に対して1つの[[グリフ]]を与える[[写像]]です。

;; [112] 
[[言語]]的な理由や[[文字コード]]設計の事情で複数の[[文字]]を1つの[[グリフ]]で表したい場合
([[合字]])
や、
[[書体]]設計的な事情で1つの[[文字]]を複数の[[グリフ]]で表したい場合には、
[CODE[cmap]] だけでは実現できず、 [CODE[GSUB]]
(または [[shaping engine]] による文字前処理) 
との組み合わせが必要となります。

-*-*-

[56] 
[CODE[cmap]] [[表][OpenType表]]の [DFN[[F[[CODE[encodingRecords]]]]]]
に含められる [DFN[[CODE[EncodingRecord]]]]
は、
その
[F[[CODE[platformID]]]],
[F[[CODE[encodingID]]]],
[F[部分表]]の [F[[CODE[language]]]]
の優先順で[[整列]]しなければ[RUBYB[なりません][must]]。
[SRC[>>1]]
ここでの[[順序]]は[[数値]]の小さい順と思われます。

[57] 
[CODE[cmap]] [[表][OpenType表]]にあっては
[CODE[EncodingRecord]]
の
[F[[CODE[platformID]]]],
[F[[CODE[encodingID]]]],
[F[部分表]]の [F[[CODE[language]]]]
の組み合わせは、
高々1回しか出現[RUBYB[でき][may]]ません。
[SRC[>>1]]

[58] 
[[順序]]が不適切な場合や重複を含む場合にどう処理するべきなのかは定かではありません。
[[順序]]を無視する実装もあり得ますし、
求めるものより大きな値が出現したら探索を止める実装もあり得ます。
最初の一致を採る実装も、[[無作為]]に選ぶ実装もあり得ます。
エラーにする実装もあり得ます。
主要な実装はどうしているのでしょうか?

[59] 
各[[部分表]]は、
[F[[CODE[format]]]] が [N[14]] の場合を除き、
排他的であります。
つまり[[応用]]は、そのうちの1つだけを選び、他を無視する[RUBYB[べき][should]]です。
[SRC[>>1]]

[60] 
[[Unicode部分表]]が含まれる場合で、
16ビットの 
[F[[CODE[format]]]]
のものと
32ビットの
[F[[CODE[format]]]]
のものが両方含まれるなら、32ビットの[[部分表]]に含まれる[[文字]]は、
16ビットの[[部分表]]に含まれる[[文字]]の[[超集合]]である[RUBYB[べき][should]]です。
[[応用]]は、
32ビットの[[部分表]]を使う[RUBYB[べきです][should]]。
[SRC[>>1]]

;; [61] 仕様上は要求されていませんが、常識的に考えて32ビットの[[部分表]]のうち
[ [CODE[U+0000]], [CODE[U+FFFE]] ]
の部分と16ビットの[[部分表]]が一致しているべきです。

[63] 
[F[[CODE[platformID]]]] が違い
[F[[CODE[format]]]]
が同じ
[[Unicode部分表]]が含まれる場合、
[[応用]]はそのいずれを選んでも[RUBYB[構いません][may]]が、
その[[フォント]]の利用時にどの[[部分表]]が選ばれるかは一貫している[RUBYB[べきです][should]]。
[SRC[>>1]]


[97] 
明示的には定められていませんが、その趣旨からして、
未対応の組み合わせが出現しても、
実装は黙って無視するべきと思われます。

[98] 
指定されたすべての組み合わせが未対応の場合にどうするかは定められていません。
エラーとしてまったく受理しない実装もあるかもしれませんし、
黙って他の[[フォント]]にフォールバックするような実装戦略もあるかもしれません。

;; [62] 複数の[[部分表]]を含めても[[応用]]が使うのは1つだけです。
これによって対応する[[文字コード]]が異なる[[プラットフォーム]]で共通して使える[[フォント]]を提供できるというわけです。
実際に多くの[[フォント]]がそうしていますが、
一方で敢えて重複した[[部分表]]を含めない[[フォント]]もあります。
([CODE[format]] [N[14]] を除けば)
もはや[[プラットフォーム]]の違いによる互換性の問題はおおむね解消しており、
必要だからというより今までそうしてきたからというところが大きそうです。



** [CODE[format]]

[47] 
[CODE[cmap]]
[[表][OpenType表]]の
[DFN[[F[[CODE[format]]]]]]
は[[文字コード]]から[[グリフID]]への[[写像]]の記述方法を表します。
[SRC[>>1]]

[48] 
多くの方法が定義されていますが、新しい[[フォント]]はそのうちの
[N[4]], [N[12]]、
用途により
[N[13]], [N[14]]
が適切です。
それ以外は新しい[[フォント]]には[RUBYB[推奨されません][not recommended]]。
[SRC[>>1]]

[104] 
いくつかの 
[CODE[format]]
は[[データ構造]]上、
矛盾した値を記述することができます。
例えば開始よりも終了が小さな値の範囲を記述できたり、
小さい順に[[整列]]と規定されている (が構文上は無視できる)
ことがあります。
それらの一部は仕様書上で明確に禁止されています。
しかし禁止されている場合や当然に異常とみなされる場合に、
どう処理するべきかは明確ではありません。
(これは [CODE[cmap]] に限らず [[OpenType]] 全般でそうです。)

*** [CODE[format]] [N[0]] (1バイト符号)

[4] 
[CODE[format]] = 0 : 
[ [N[0x00]], [N[0xFF]] ]
の[[ビット組合せ]]に対応する[[グリフID]]が順番に格納されています。
[SRC[>>1, >>2]]

[100] 
古い [[Macintosh]] ではこれが標準でした。 [SRC[>>1]]

[5] 
新しい [[Apple]] の[[プラットフォーム]]では必須ではありません。 [SRC[>>1]]
今はあまり使われていません。
対応していない実装もあります。

*** [CODE[format]] [N[2]] (1バイトと2バイトの多バイト符号)

[6] 
[CODE[format]] = 2 : 
1バイト (8ビット) または2バイト  (16ビット) 
の[[多バイト符号]]に対応する[[グリフID]]が順番に格納されています。
[SRC[>>1, >>2]]

[99] 
記述のない[[バイト]]は[[グリフID]] [N[0]] に対応するものと解釈されます。
[SRC[>>1]]

[101] 
[[CJK]] の[[非Unicode]]の[[多バイト符号]]に適していました。
[SEE[ [[シフトJIS型符号]] ]]

[7] 古い時代に用いられていたもので、今はあまり使われていません。
対応していない実装もあります。

*** [CODE[format]] [N[4]], [N[6]], [N[12]], [N[10]], [N[13]] (16ビット符号と32ビット符号)

-
[8] 
[CODE[format]] = 4 :
16ビット符号用。
[SRC[>>1, >>2]]
-
[9] 
[CODE[format]] = 6 :
16ビット符号用。
[SRC[>>1, >>2]]
-
[17] 
[CODE[format]] = 12 :
32ビット符号用。
[SRC[>>1, >>2]]
-
[14] 
[CODE[format]] = 10 :
32ビット符号用。
[SRC[>>1, >>2]]

[11] 
4, 6 は [[Unicode BMP]] 用,
12, 10 は [[Unicode]] 全体に使われています。

[10] 
4, 12 は連続した[[符号位置]]に[[グリフID]]が割り当てられた密なもの、
6, 10 は疎なものに適した[[データ構造]]になっています。

[28] 
6
に対応していない実装もあります。

[16] 
10 はあまり使われておらず、 
[[Windows]] は対応していません。
[SRC[>>1, >2]]

[20] 
当初 4 が使われ後に 12 が使われるようになった経緯のため、
古い実装は 12 に対応していません。
多くの[[フォント]]は 4 と 12 の両方の [CODE[cmap]] 部分表を含めているようです。
(そうできると明記されていますが、必須ではありません。 [SRC[>>1]])
古い実装は 4 の方を見るので、 [[BMP]] の[[文字]]だけは使えます。


[64] 
[F[[CODE[format]]]] が [N[4]] と [N[6]]
の
[[Unicode部分表]]を同時に含める[RUBYB[べきではありません][should]]。
[F[[CODE[format]]]] が [N[10]] と [N[12]]
の
[[Unicode部分表]]を同時に含める[RUBYB[べきではありません][should]]。
これらの場合、 [N[4]] や [N[12]] を使う[RUBYB[べきです][should]]。
[SRC[>>1]]

[76] 
[[Windows]] ([CODE[platformID]] [N[3]])
で
[[Unicode]] [[BMP]]
のみ対応する[[フォント]]は、
[F[[CODE[encodingID]]]] [N[1]]
[F[[CODE[format]]]] [N[4]]
[[部分表]]を使わなければ[RUBYB[なりません][must]]。
[SRC[>>1]]

[77] 
[[Windows]] ([CODE[platformID]] [N[3]])
で
[[Unicode]] 非 [[BMP]]
に対応する[[フォント]]は、
[F[[CODE[encodingID]]]] [N[10]]
[F[[CODE[format]]]] [N[12]]
[[部分表]]を使わなければ[RUBYB[なりません][must]]。
[SRC[>>1]]



[15] 
[CODE[format]] = 13 は [CODE[format]] = 12 の変種。
複数の連続した[[符号位置]]の範囲を1つの[[グリフID]]に割り当てる。
[SRC[>>1, >>2]]

[18] 
[[last-resort]] font 
(適当な[[グリフ]]を用意できないときに代替[[グリフ]]を提供するための[[フォント]])
用とされています。
その性質上ほとんど使われておらず、
対応していない実装もあります。

[73] 
[F[[CODE[format]]]] [N[13]]
[[部分表]]は、
[F[[CODE[platformID]]]] [N[0]]
[F[[CODE[encodingID]]]] [N[6]]
でのみ使う[RUBYB[べきです][should]]。
[SRC[>>1]]

- [147] [CITE@en-GB[The Typekit Blog | Introducing Adobe Blank]], [TIME[2020-07-28T21:33:01.000Z]], [TIME[2023-05-02T08:40:10.206Z]] <https://blog.typekit.com/2013/03/28/introducing-adobe-blank/>
- [148] [CITE@en-US[1,111,998 to 1 → Adobe Blank 2]], [TIME[2020-11-19T06:22:25.000Z]], [TIME[2023-05-02T08:41:20.984Z]] <https://ccjktype.fonts.adobe.com/2015/04/adobe-blank-2.html>

-*-*-

[149] 
[F[[CODE[format]]]] [N[4]]
のとき最後に [F[[CODE[startCode]]]] [N[0xFFFF]],
[F[[CODE[endCode]]]] [N[0xFFFF]]
の segment が必須です。
[SRC[>>1]]

[150] 
妥当な[[写像]]でもそうでもなくても構わない [SRC[>>1]] とされます。
つまり [CODE[U+FFFF]] 用の[[グリフ]]情報を含めることも、
含めないこともできますが、
どちらの場合も機械的にこの segment が必要となります。

-*-*-

[154] 
[[Chrome]] も [[Firefox]] も、指定された[[符号]]が仕様通り[[昇順]]になっていないとき、
構文解析エラーとして[[フォント]]を無視します。
[[Chrome]] は[[開発者ツール]]に [CODE[cmap]] のエラーである旨のみを表示しますが、
それくらいしか情報がありません。
[[Firefox]] は[[開発者ツール]]に符号の値を表示してくれます。
[TIME[2023-08-27T02:54:40.600Z]]

-*-*-

[164] 
[CODE[format]] [N[12]] と [CODE[format]] [N[13]]
の両方があるとき、
[[Chrome]] も [[Firefox]] も [CODE[format]] [N[13]] の方は無視します。
[CODE[cmap]] 中の順序は関係ありません。
([CODE[format]] だけによって決まるのか [CODE[encodingID]] などでも決まるのかはよく分かりません。)


-*-*-

[114] 
[CODE[format]] [N[4]] 
の[[部分表]]のサイズ上限を超えるような[[フォント]]を作ろうとすると、
[[AFDKO]] の [CODE[makeotf]]
は最初の2つの segment だけ残して後は捨ててしまいます。 [SRC[>>113]]

[115] 
[[Windows]] 
の[[メモ帳]]や [[Microsoft Excel]]
は
[CODE[format]] [N[4]] 
が存在すること、という
[[heuristics]]
を実装しています。
それへの対処として、
[CODE[format]] [N[12]]
を使うときでも
[CODE[format]] [N[4]]
[[部分表]]を含めなければなりません。
[SRC[>>113]]
(その場合でも [CODE[format]] [N[12]] が使われるので、
[CODE[format]] [N[4]] は不完全でも存在していればOKらしいです。)


[REFS[
- [113] 
[CITE@en[GitHub - adobe-type-tools/[[Adobe-KR]]: The Adobe-KR-9 Character Collection]], [TIME[2022-09-29T11:52:44.000Z]] <https://github.com/adobe-type-tools/Adobe-KR/#special-notes-5>

]REFS]

- [116] [CITE@en[[[GitHub]] - trueroad/HaranoAjiFonts-generator: 原ノ味フォント生成プログラム / Harano Aji Fonts generator]], [TIME[2022-09-29T15:48:27.000Z]] <https://github.com/trueroad/HaranoAjiFonts-generator#cmap>

>原ノ味フォント 20200516 から、KR のみ format 4 と format 12 に対し、 Unicode コードポイントで一つだけ抜けている (両隣は存在するが該当箇所は存在しない)ものに .notdef を割り当てる加工をしています。 これは、何もしないと format 4 のサイズが 64 KB を超えてしまい、 ttx でのフォント生成が例外で落ちてしまったためです。 format 12 はサイズの問題がないし format 4 の情報もすべて含んだ上位互換なので、 format 4 がなくてもいいだろうと削除してみたら落ちなくなりましたが、 Windows がフォントとして認識してくれません。 仕方なく format 4 の仕様書とにらめっこしてサイズを低減する方法を模索し、 上記の処理を入れました。 なお format 12 も BMP の範囲は format 4 と同じである必要があるため、 BMP 範囲内のみ同じ処理を入れてあります。

>原ノ味フォント 20200612 から、 [SNIP[]]KR で入れていた Unicode コードポイントで一つだけ抜けているものに .notdef を割り当てる加工 をやめ、代わりに Adobe-KR のドキュメントに記載されている format 4 から CJK Unified Ideographs (U+4E00..U+9FFF) と CJK Compatibility Ideographs (U+F900..U+FAFF) のブロックを削除する方法に変更しました。 これは .notdef を割り当てる加工をしていて、 かつ(関係ないはずの) GPOS テーブルが存在すると、 なぜか Windows がフォントを認識してくれないことが分かったためです。 OpenType 仕様的には(というか Windows 向けとしては) format 4 と format 12 の BMP 部分は一致するようにするのが推奨されていますが、 サイズ的に収まらないので仕方がなく Adobe お勧めの対処法に従った処理を行ったものです。


*** [CODE[format]] [N[8]] (16ビットと32ビットの混合符号)


[12] 
[CODE[format]] = 8 :
16ビットまたは32ビットの符号用。
[SRC[>>1, >>2]]

[103] 
上位が [N[0x0000]] となる32ビット符号に
[[グリフ]]を割り当てることも禁止はされていません。
しかし [N[0x0000]] と上位 [N[0x0000]] の32ビット符号の両方に[[グリフ]]を割り当てることは[RUBYB[禁止][may not]]されています。
[SRC[>>1]]
そのような場合にどうするべきなのかは不明。


[13] 
[CODE[U+10FFFF]] まで使う [[Unicode]] を想定したものでした。


[102] 
この
[CODE[format]]
はあまり使われていません。
対応していない実装もあります。
[RUBYB[非推奨][discouraged]]とされています [SRC[>>1]]。

*** [CODE[format]] [N[14]] (Unicode 異体列)

[21] 
[CODE[format]] = 14 :
[[UVS]]
用。
[SRC[>>1, >>2]]

[22] 
他の [CODE[format]] と違って入力が1つの[[文字]] ([[符号位置]])
ではなく2つの[[文字]] ([[符号位置]])。
[[Unicode]] の[[異体列]]の専用の仕組みになっています。
(2, 8 の入力は多バイトであっても1文字。 4, 6, 10, 12, 13 も同じ。
4, 6, 8, 10, 12, 13 は [[Unicode]] 想定であっても、専用ではない。)

[23] 
同じく複数の [[Unicode文字]]で1つのものを表現する[[結合列]]や[[合字]]は
[CODE[GSUB]] 
で[[グリフ]]レベルの操作を使っていますが、 [[VS]] 
だけなぜか専用の仕組みが [CODE[cmap]] に[[文字]]レベルで追加されました。


[25] 
[[異体列]]に対し「[[異体選択子]]なしと同じ」を指定するものと、
[[グリフID]]を指定するものの2種類の指定方法があります。
前者が得られた場合には他の
[CODE[cmap]] 部分表を使って再探索することになります。

[26] 
実際の[[フォント]]は前者の方法を使わずすべて後者の方法によるものと、
前者の方法を適宜使うものがあります。
前者を使った方がデータ量はいくらか少なくなるのでしょうが、
[[グリフ]]取得が少し遅くなります。
といっても現在の[[計算機]]の性能からみればどちらの差分もほとんど誤差みたいなものでしょう。

;; [27] その誤差みたいな節約のために前者の方法を導入してるのが無駄に思えるのですが、
[[OpenType]] の複雑性の中ではそれも誤差みたいな複雑性かもしれませんw

[29] 
[[VS]] は[[日本語]]や[[蒙古文字]]の表示には必須の機能ですが、
[[欧米]]では必要とされないことや、
比較的歴史の浅い機能であることから、
14 に対応していない実装もあります。

[30] 
[[日本語]]用[[フォント]]で多くの文字を含んだものにはよく使われています。

;; [31] 14 を使わなくても [CODE[GSUB]] でも対応できますが
(そちらの方が対応してる実装は多いかも知れませんが)、
そのような[[フォント]]があるのかは不明。


[65] 
[[Unicode部分表]]が使われる場合、
[F[[CODE[platformID]]]] [N[0]]
[F[[CODE[encodingID]]]] [N[5]]
[F[[CODE[format]]]] [N[14]]
の[[部分表]]で [[UVS]] に対応することができます。
[F[[CODE[format]]]] [N[14]]
[[部分表]]は、
[F[[CODE[platformID]]]] [N[0]]
[F[[CODE[encodingID]]]] [N[5]]
でのみ使う[RUBYB[べきです][should]]。
[SRC[>>1]]



;; [66] とだけしか定められてはいないのですが、
[[Unicode部分表]]がないときは [CODE[format]] [N[14]]
は使えないということでしょうか。
(実用上それ以外で [CODE[format]] [N[14]] を使いたいことはなさそうですが。)

[71] 
[[UVS]] は、[CODE[cmap]] [[表]]で [F[[CODE[format]]]] [N[14]] [[部分表]]で指定する[RUBYB[べき][should]]です。
[SRC[>>1]]

;; [72] この「べき」[[規定]]の意味するところは不明瞭です。
[CODE[GSUB]] による [[UVS]] の実装を否定する趣旨と理解していいのでしょうか。

[117] [CITE@ja[利用者:emk - GlyphWiki]], [TIME[2022-10-14T10:19:13.000Z]] <https://glyphwiki.org/wiki/User:emk#i0>

>Windows 7でIVSを認識させるには、以下の条件をすべて満たす必要があるようです。 


[165] 
[[Chrome]] も [[Firefox]] も、
[[異体選択子]]が0個だとエラーとして[[フォント]]を無視します。
従って1つも [[VS]] を含まない[[フォント]]では
[CODE[format]] [N[14]] [[部分表]]全体を省かなければなりません。
[TIME[2023-11-04T03:01:28.900Z]]

[155] 
仕様書上は特に制限されているようには読めませんが、
[[Chrome]] も [[Firefox]] も[[異体選択子]]以外の[[符号位置]]が書かれていると、
[CODE[cmap]] の構文解析エラーとして[[フォント]]を無視します。
[TIME[2023-08-27T03:44:41.300Z]]

[156] 
[[Chrome]] でも [[Firefox]] でも[[漢字]] + 通常 [[SVS]], [[漢字]] + [[IVS]] はうまく動作しますが、
[[漢字]] + [[蒙古文字自由異体選択子]]は動作しません。

- [157] [CODE(charname)@en[FVS1]], [CODE(charname)@en[FVS2]], [CODE(charname)@en[FVS3]]
があってもエラーにはなりませんが、[[グリフ]]は使われず、
[[基底文字]]だけが表示されます。
- [158] [CODE(charname)@en[FVS4]] は [CODE[cmap]] にあるだけで構文解析エラーになって、
[[フォント]]が無視されます。
-- [160] [[Firefox]] の[[開発者ツール]]によると、
[[UVS]] [CODE[cmap]] の最大数が259 ([CODE(charname)@en[FVS4]] 以外の[[VS]]の総数)
になっているようです。
それを超えないとしても不正な[[VS]]扱いでエラーにはなります。
- [159] [CODE(charname)@en[FVS4]] があるとき[[Firefox]]では[[基底文字]]だけが表示されますが、
[[Chrome]]では[[基底文字]]と[CODE(charname)@en[FVS4]]が同じ位置に重なった状態で、選択に対しては1文字扱いで、表示されます。


[79] 
[CITE[Chrome]] は以前よりも制限が厳しくなったようです。
いつ変わったのか、どれが新しい制限かはわかりませんが、
次のような挙動を確認できます。
[TIME[2026-01-25T12:10:52.00Z]]

- [84] 
[[Webフォント]]の検査のエラーメッセージ全般が以前より詳しく親切になっています。
- [80] 
ある[[IVS]]について、その[[基底文字]]が [CODE[cmap]] にあって [[IVS]] が [CODE[cmap]] 
にない場合、以前の [CITE[Chrome]] と現在の [CITE[Firefox]] 
はその[[基底文字]]の[[グリフ]]を使っていましたが、現在の [CITE[Chrome]]
では次の[[フォント]]を調べます。
-- [81] 従って [F[[CODE[format]]]] [N[13]] ですべての[[符号位置]]に[[グリフ]]を割り合てているとしても、
[[IVS]] があるとその[[フォント]]は使われず次の候補の[[IVS]] の[[グリフ]]が使われることがあります。
-- [82] 
[[URO]] + [[IVS]] ではこの挙動になりますが、 [[URO]] + [[SVS]]
では少し挙動が違うようにも見え、更なる検証が望まれます。
- [83] 
[F[[CODE[numVarSelectorRecords]]]] の最大が [N[256]]
([[SVS]] + [[IVS]] の最大値か)
で、それを超えると[[開発者コンソール]]にエラーが表示され、
その[[フォント]]は使われません。
- [85] 
[F[[CODE[numUnicodeValueRanges]]]]
が [N[236]]
を超えるとエラーメッセージなしでその[[フォント]]は無視されます。
[F[[CODE[numUnicodeValueRanges]]]]
に上限があるのか、
それとも他の長さ超過などが主因なのかは不明です。
-- [86] 
同じ[[フォント]]が [CITE[Firefox]] では正常動作するので、
[[OpenType]] [[フォント]]として壊れてはいないはず。
-- [90] 
>>83 >>85 の制限があるため、
[N[60416]]
個の[[符号位置]]しか default UVS を設定できません。
-
[89] 
[CODE[UnicodeRange]]
の
[F[[CODE[startUnicodeValue]]]]
が
[N[0]] 
だとエラーメッセージが表示され、その[[フォント]]は無視されます。
[N[1]]
[[以上]]にする必要があります。
これは [CITE[Chrome]] でも [CITE[Firefox]] でも同じ挙動です。
- [87] 
[CODE[cmap]] [F[[CODE[format]]]] [N[14]] の [F[[CODE[length]]]]
は、
仕様書では「Byte length of this subtable (including this header)」
と説明されていて、 [[subtable]] がどこまでを指すのか不明瞭ですが、
[CODE[VariationSelector]]
で [CODE[Offset32]] で参照されている[[表]]の末尾までが入っていなければなりません。
-- [88] 長すぎてそれより先に余分にバイト列を置いて含めていても、
長さ不一致でエラーになります。






-*-*-

[367] 
[[TTF]] / [[OTF]] の[[異体列]]用 [CODE[cmap]] format 14 
に対応していないソフトウェアが意外とあります。

[368] 
[CITE[[CODE[opentype.js]]]] では [[API]] がなく存在自体が無視されます。

[369] 
[CODE[ttfdump]] や [[Typr]] は存在することだけ知らせて中身は dump してくれません。

[370] 
[CODE[Font::TTF]] は普通に対応しています。






*** [CODE[format]] の実利用例


[3] 
[CITE@en[[[GitHub]] - nixeneko/nxTokiACF]], [TIME[2022-08-16T01:59:19.000Z]] <https://github.com/nixeneko/nxTokiACF>

[CODE[format]] = 0, 4

[19] [CITE@en[Release Version 14.000 Release · unicode-org/last-resort-font · GitHub]], [TIME[2022-08-16T02:36:51.000Z]] <https://github.com/unicode-org/last-resort-font/releases/tag/14.000>

[CODE[LastResort-Regular.ttf]]
は
7.89MB 
の[[フォント]]。
[CODE[format]] = 12 と [CODE[format]] = 4 (空)。

[CODE[LastResortHE-Regular.ttf]]
は
506KB
の[[フォント]]。
[CODE[format]] = 13 ([CODE[platformID]] [N[3]], [CODE[encodingID]] [N[10]]), 
[CODE[format]] = 4 ([CODE[platformID]] [N[3]], [CODE[encodingID]] [N[1]]) (空)。

(ファイルサイズの違いは [CODE[format]] の違いに起因するものではない。)

** グリフID

[46] 
[CODE[cmap]] では、
[[フォント]]中に対応する[[グリフ]]を持たない[[文字コード]]は[[グリフID]]
[N[0]]
に[[写像]]する[RUBYB[べきです][should]]。
[SRC[>>1]]
[SEE[ [[グリフID]] ]]


[151] 
この規定と関係するのかどうか、実装によっては [CODE[cmap]] で[[グリフID]] [N[0]]
に対応付けるように設定しても、無視される (ように見える) ことがあります。
それが仕様通りの動作なのかどうかはよくわかりません。

[152] 
[[グリフID]] [N[0]] のとき未実装とみなして他の[[フォント]]に[[フォールバック]]しているのかもしれません。


[153] 
[[Chrome]] で [F[[CODE[format]]]] [N[13]] の[[フォント]]で全[[符号位置]]を[[グリフID]] 
[N[0]] にしても、エラーにはなりませんが、その[[グリフ]]は使われずに他の[[フォント]]で表示されます。
[[フォント]]内の[[グリフ]]が [N[0]] 
1個だけではだめなのかと他の[[グリフ]]を入れてみても変わりません。
[[グリフID]] [N[0]] 以外に設定すればちゃんと使われるので、
[[グリフID]] [N[0]] を使ったことに起因するのは間違いありません。




** 処理

[107] 
[CODE[cmap]]
は[[文字のレンダリング]]のために[[フォント]]の[[グリフ]]を取得する過程の1つとして参照されます。
[SEE[ [[文字のレンダリング]] ]]

[108] 
[CODE[cmap]] の[[写像]]を引く[[入力]]となる[[文字コード]]は、
必ずしも[[情報交換]]に使う
[[Unicode文字列]]を構成する[[Unicode符号位置]]の列そのものではないことに注意が必要です。

[109] 
[[bidi]] に関係して[[鏡像化]]のための[[符号位置]]の書き換えが事前に発生していることがあります。
[SEE[ [[書字方向依存グリフ]] ]]

[110] 
その他 [[shaping]] に属する前処理で[[符号位置]]の変更が事前に発生していることがあります。
[SEE[ [[shaping engine]] ]]

* グリフから文字コードへ

[168] 
[CODE[cmap]] は[[文字コード]]から[[グリフID]]への変換表です。
その逆方向、[[グリフID]]から[[文字コード]]への変換方法は規定されていません。

[169] 
ところが何らかの方法で[[グリフID]]から[[文字コード]]に変換できることを期待する処理がいくつかあります。
[[1対1対応]]が成り立たないときどうするべきなのかは不明です。

[SEE[ [[expt]], [[hngl]] ]]

* 関連

[3] 
[[TrueType]] の [CODE[cmap]] と
[[CIDFont]] の [[CMap][CMap file]]
は、
似たような用途ですが、
技術的にはまったくの別物です。
正式な表記は[[大文字と小文字]]で区別できますが、
俗に
cmap, CMAP, CMap 
と混用されているので、文脈で注意して区別するしかありません。

[35] [CITE@ja-jp[OpenType glyph processing (part 2) - Typography | Microsoft Docs]], [[alib-ms]], [TIME[2022-08-27T08:46:01.000Z]] <https://docs.microsoft.com/ja-jp/typography/develop/processing-part2#cmap-table>


[36] >>35 公式ドキュメントですが、ここでは [CODE[CMAP]] になっています。
[CODE[cmap]] にしないと正常動作しないと思いますが、どうなんでしょう。


* メモ





[37] [[Character-level mirroring]] では [CODE[cmap]] で得られる値が [N[0]] か検査します。


[161] [[開発者ツール]]で見られるエラーは [[Chrome]] より [[Firefox]] の方が親切です。
[TIME[2023-08-27T13:05:20.000Z]]

[162] 
[CITE@en[gecko-dev/gfx/ots/src/cmap.cc at master · mozilla/gecko-dev · GitHub]], [TIME[2023-08-27T13:04:47.000Z]] <https://github.com/mozilla/gecko-dev/blob/master/gfx/ots/src/cmap.cc>

[163] 
そしてエラーのより詳しい意味は >>162 のソースを見るとわかります。


[166] 
[CITE@en[How to decode namerecord? · Issue #956 · MicrosoftDocs/typography-issues · GitHub]], [TIME[2024-05-25T06:02:16.000Z]] <https://github.com/MicrosoftDocs/typography-issues/issues/956>

[167] 
[CITE@en[Fonts without Microsoft-platform cmaps use Mac NameRecord · Issue #679 · libass/libass · GitHub]], [TIME[2024-05-25T06:04:11.000Z]] <https://github.com/libass/libass/issues/679>

