/
667.txt
361 lines (289 loc) · 14.1 KB
/
667.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
[6]
[DFN[[[文字]]の[[レンダリング]]]]は、
単純に[[文字]]を並べていくだけに思えますが、
実は考えなければならないことがたくさんあって、
非常に複雑で難解な処理なのです。
* 文字とレンダリング
[16] [[文字]]の連続の[[レンダリング]]が個別の[[文字]] ([[グリフ]])
の[[レンダリング]]の連続とは異なることがあります。
[FIG(short list)[ [10] [[文字]]と表現の記述
- [[文字]]
- [[文字コード]]
- [[結合文字]]
- [[合成文字]]
- [CODE(charname)@en[GCC]]
- [[重ね打ち式文字合成]]
- [[書記素クラスター]]
- [CODE(charname)@en[ZWJ]]
- [CODE(charname)@en[ZWNJ]]
- [[制御文字]]
- [[空白文字]]
- [[スペース]]
- [[˥˩]], [[˩˥]]
- [[国旗]]
- [[肌の色]]
- [[ハングル字母]]の列による[[ハングル音節]]の表現
- [CODE[transcoding hint: group next [VAR[n]] characters]]
- [[IDS]]
]FIG]
[FIG(list middle)[ [8] [[文字のレンダリング]]
- [[連なり]]
- [[subtending mark]]
- [[語頭形]]、[[語末形]]など
-- [[アラビア文字]]、[[σ]]などの[[文字]]
-- [CODE[1st]] の[[上付き]] [CODE[st]] などの[[フォント]]ごとの文脈依存[[グリフ]]
- [[cursive]] な場合
-- [[アラビア文字]]など、それが一般的な[[書字体系]]
-- [[筆記体]]の[[ラテン文字]]や[[草書体]]の[[漢字]]・[[仮名]]など、そうも表現される[[書字体系]]
-- [CODE(charname)@en[ZWJ]]
- [[合字]]
- [[カーニング]]
- [[shaping]]
- [[グリフの選択]]
- [[鏡文字]]
- [[回転][回転 (書字方向)]]
- [[上下反転]]
- [CODE(charname)@en[SGR]]
- [[フォント]]
- [[機能][フォント機能]]
- [[斜体]]
- [[イタリック]]
- [[文字列座標]]
- [[ラスター化]]
- [[アンチエイリアシング]]
]FIG]
[FIG(short list)[ [12] [[文字]]の周辺
- [[語境界]]
- [[改行]]
- [[ハイフン付け]]
- [[改段落]]
- [[改行記号]]
- [[言語情報]]
- [[書字方向]]
- [[bidi]]
- [[ルビ]]
- [[interlinear annotation]]
-
[[行内構造]]
-[[アキ]]
-[[字間]]
- [[行揃え]]
-[[語間]]
-[[行間]]
-[[改行]]
-[[改段落]]
-[[禁則処理]]
- [[カーソル]]
- [[hit testing]]
- [[置換要素]]
- [[基線][基線 (文字)]]
]FIG]
* フォント依存文字
[FIG(short list)[ [1] [[フォント]]依存文字
- [CODE(char)[U+005C]]
- [CODE[~]]
- [[フォント機能]]
- [[包摂規準]]
- [[ビルマ文字]]
- [[PUA]]
- [[EUDC]]
- [[DRCS]]
- [[機種依存文字]]
- [[Unicode非互換割当]]
- [[外字]]
]FIG]
* OpenType の処理モデル
[35]
[CODE[cmap]] を参照する時点では、
[[文字列]]の転送・保管等に使う[[符号化方式]] (いわゆる[[外部コード]])
ではなく[[フォント符号化]]を知っている必要があります。
[[Unicode]] の場合、 [[UTF-8]] [[バイト列]]や
[[UTF-16]] [[サロゲートペア]]等ではなく、
[[Unicode符号点]]の列です。
[36]
[CODE[cmap]] は[[文字コード]](列)から[[グリフID]]への[[写像]]です。
ほとんどの場合は1つの[[文字]] ([[符号点]]) が入力ですが、
[[異体列]]は1つの[[異体列]]が入力となります。
従って
[CODE[cmap]]
を引くには、
入力の[[文字列]]を ([[異体列]]とそれ以外の[[文字]]) の列に分解する必要があります。
[37]
また、[[異体列]]から [CODE[cmap]] を引いた出力は
「[[基底文字]]と同じ[[グリフ]]」
という回答かもしれませんから、
[[基底文字]]の[[符号点]]で
[CODE[cmap]]
をもう一度引かなければなりません。
(普通は同じ[[フォント]]の [CODE[cmap]] で[[基底文字]]を引けば適切な[[グリフID]]が返ってくるはずですが、
[[データ構造]]的に保証はされていませんから、エラー処理が必要となります。)
[32]
[[Windows]]
は[[サロゲートペア]], [[bidi]],
[[用字系]]依存の [[shaping]] (文字前処理を含む。)
を
[[Uniscribe]]
で実装し、
[[OpenType Layout]]
による[[グリフ]]の置換と位置決定を
[[OTLS]]
で実装する、
という2段階構造になっているようです。
[30]
[[Uniscribe]]
は[[アラビア文字]],
[[ヘブライ文字]],
[[タイ文字]]については、
古い [[OS]]
が対応していた
[[OpenType Layout]]
以前の[[フォント]]にも対応しています。
[SRC[>>31]]
[34]
[[鏡像化]]は [CODE[cmap]] を参照する時点でも処理が必要です。
[SEE[ [[書字方向依存グリフ]] ]]
[33]
[CODE[vert]] を使った[[レンダリング]]や[[縦書き]]対応していない[[フォント]]の[[レンダリング]]には、
取得した[[グリフ]]データの[[回転][回転 (書字方向)]]が必要となります。
[SEE[ [[縦書きグリフ]] ]]
[38] [[グリフ位置決定]]
[42]
[[機能][フォント機能]]については、
[[justification]] のために適当な[[行]]長を実現すべく、
[[グリフ]]の置き換えや位置調整を適用し直すことがあります。
[SEE[ [[JSTF]] ]]
=
[44]
[CODE[MERG]] の指定に従い[[グリフ]]列を併合します。
=
[45]
[[アンチエイリアシング]]の処理を適用します。
[REFS[
-
[31] [CITE@ja-jp[OpenType glyph processing (part 2) - Typography | [[Microsoft]] Docs]], [[alib-ms]], [TIME[2022-08-27T13:16:47.000Z]] <https://docs.microsoft.com/ja-jp/typography/develop/processing-part2#uniscribe-in-detail>
]REFS]
** OpenType Layout の処理モデル
[14]
[[OpenType Layout]] [[フォント]]を使って[[文字]]を表示する[RUBYB[文章処理クライアント][text-processing client]]は、
次のようにして[[文字列]]から[[グリフ]]列を得るとされています。
[SRC[>>13]]
[FIG(steps)[
=
[15]
[[フォント]]の [CODE[cmap]] [[表][OpenType表]]に基づき、
[[文字符号]]列を[[[RUBYB[グリフ索引][glyph index]]][グリフID]]列に変換します。
=
[17]
[[フォント]]の [CODE[GSUB]] [[表][OpenType表]]に基づき、
[[グリフ]]列を編集します。
=
[18]
[[フォント]]の [CODE[GPOS]] [[表][OpenType表]]と
[CODE[BASE]] [[表][OpenType表]]に基づき、
[[グリフ]]の[RUBYB[位置][position]]を決定します。
= [19]
[RUBYB[[[設計座標]]][design coordinates]] (高解像度で装置非依存)
で装置非依存[RUBYB[[[改行]]][line break]]を決定します。
= [20]
[[利用者]]の指定がある場合、
[[フォント]]の [CODE[JSTF]] [[表][OpenType表]]に基づき、
[RUBYB[[[行揃え]]][justifies the lines]]をします。
= [21]
[[グリフ]]の[[行]]を[[ラスター化]]し、
[RUBYB[[[装置座標]]][device coordinates]] (出力装置の[[解像度]]に対応するもの)
に[[グリフ]]群を[[レンダリング]]します。
]FIG]
[22]
[[OpenType]] [[仕様書]]ではこのうち最後の出力だけを [[OS]]
の処理とし、他を文章処理クライアントの処理としています。
[SRC[>>13]]
[[装置]]依存の処理かどうかで区分しているのでしょうか。
[[Windows]] の場合他の処理も [[OTLS]] を使って実装でき、
広い意味では全体が [[OS]] の範疇であります。
逆に出力が[[ハードウェア]]でなく[[画像ファイル]]等なら全体が[[応用]]レベルで実装されていることもありそうです。
[REFS[
- [13] [CITE@ja-jp[Advanced typographic tables - OpenType Layout (OpenType 1.9) - Typography | [[Microsoft]] Docs]], [[PeterCon]], [TIME[2022-08-28T02:47:24.000Z]] <https://docs.microsoft.com/ja-jp/typography/opentype/spec/ttochap1#text-processing-with-opentype-layout-fonts>
]REFS]
* レンダリング処理と文字性の維持
[23]
[[文字列]]を[[グリフ]]列に変換し[[レンダリング]]する一連の処理により、
異なる[[文字]]が同じ[[グリフ]]で表現されたり、
複数の[[文字]]が[[合字]][[グリフ]]に置き換えられたり、
[[表示順]]が[[論理順]]の[[文字列]]の位置関係から入れ替わっていたりしますが、
多くの場合に元の[[文字]]との対応関係を保持し続ける必要があります。
[EG[
[24] 例えば[[文字列の選択]]からの[[コピー]]を実現するためには、
選択した[[グリフ]]列から元の[[文字列]]が復元できる必要があります。
]EG]
;; [25]
異なる[[文字列]]が同じ[[グリフ]]になったり、
[[文字コード]]があっても表示には直接反映されなかったりもするので、
[[グリフ]]の列だけを使って[[文字列]]を生成するのは困難で、
入力の[[文字]]と出力の[[グリフ]]の対応関係を保持するのが一般的みたいです。
;; [29]
[[PDF]] が作り方により、
または表示ソフトウェアの品質により、
[[コピペ]]でおかしな[[文字列]]が生成されることがある、
というのはよく知られた問題です。
[27]
[[bidi]] や [[shaping]] の処理では[[文字]]の順序が入れ替わって表示の順序が作られます。
関係性は相当複雑になるものの、元の[[文字]]との対応付けはできます。
[26]
[[OpenType Layout]] では文章処理クライアントが[[文字]]と[[グリフ]]の関係を追跡し続けることになっています。
[SRC[>>13]]
[[合字]][[グリフ]]に置き換えられて複数[[文字]]が1[[グリフ]]にまとめられたりすることはあるものの、
対応付けを維持したままの [CODE[GSUB]] による置換は容易に実現できます。
[28]
[[OpenType]] [[フォント]]は[[合字]]における[[キャレット]]位置の情報を持つことが出来ます。
複数の[[文字]]が1つの[[グリフ]]にまとめられていても、
[[文字]]単位で[[選択範囲][文字列の選択]]を指定することができます。
[SEE[ [[キャレット]] ]]
ただしそのような情報が欠けていることもありますし、
[[グリフ]]が図形的に[[文字]]単位に分割できない場合もあります。
そのときは不自然な挙動になってしまいます。
[40]
[[OpenType]] [CODE[GPOS]] [F[[CODE[lookupType]]]] [N[5]]
(Mark-to-Ligature Attachment Positioning, MarkLigPos)
は[[合字グリフ]]上の [[anchor point]] をいくつか指定できます。
[[マークグリフ]]の[[配置]]に当たっては、
そのいずれかの [[anchor point]] を選ばなければなりません。
[SEE[ [[グリフ位置決定]] ]]
[41]
[[shaping engine]] による文字前処理や
[CODE[GSUB]] による[[グリフ]]の置き換えがあると、
[[合字グリフ]]と[[マークグリフ]]の元になった[[基底文字]]と[[結合文字]]の関係 (など)
は[[グリフ]]列から読み取れなくなってしまうかもしれません。
しかし実装はその関係性を追跡しておかなければ[RUBYB[なりません][must]] [SRC[>>39]]。
[[基底文字]]が[[合字グリフ]]のどの部分に変化したかに応じて、
[[結合文字]]に由来する[[マークグリフ]]をどの [[anchor point]]
を使って[[配置]]するかを決定します。
[REFS[
- [39]
[CITE@ja-jp[[[GPOS]] — Glyph Positioning Table (OpenType 1.9) - Typography | Microsoft Docs]], [[PeterCon]], [TIME[2022-09-07T13:06:36.000Z]] <https://docs.microsoft.com/ja-jp/typography/opentype/spec/gpos#lookup-type-5-mark-to-ligature-attachment-positioning-subtable>
]REFS]
* セキュリティー
[4] [[文字のセキュリティー]]参照。
[3] [CITE@ja[あるUNICODE文字がAppleデバイス上でアプリを破壊する――iOS、Mac、Watchの主要ソフトすべてに影響 | TechCrunch Japan]]
([[Taylor Hatmaker]]著, [TIME[2018-02-19 16:13:56 +09:00]])
<http://jp.techcrunch.com/2018/02/16/2018-02-15-iphone-text-bomb-ios-mac-crash-apple/>
[5] [CITE@ja[#PS4 特定の文字列のメッセージを受け取るとクラッシュする事案が多数発生しているらしい…対処法はあるようなのでやってみて - Togetter]]
([TIME[2018-10-15 21:56:42 +09:00]])
<https://togetter.com/li/1276875>
[7] [CITE@ja[AppleのOSをクラッシュさせる文字列がまた見つかる | スラド IT]]
([TIME[2020-04-26 11:17:35 +09:00]])
<https://it.srad.jp/story/20/04/25/2016238/>
* テスト
[2] [CITE@en[unicode-org/text-rendering-tests: Test suite for text rendering]]
([TIME[2017-05-16 13:12:37 +09:00]])
<https://github.com/unicode-org/text-rendering-tests>
* 関連
[9] [[レタリング]]とは違います。
* メモ
[11] [CITE@en[Text Rendering Hates You]], [TIME[2021-07-07T04:15:13.000Z]], [TIME[2021-11-15T08:57:15.274Z]] <https://gankra.github.io/blah/text-hates-you/>
[43] [CITE@ja[ケケモコソカメニハさんはTwitterを使っています: 「Qtさんフォールバックフォントを選ぶときに隣接する文字を考慮するらしく、こういうことが起きます。 スクリーンショットの状況はUbuntu Monoが◆を持っていないため。左の◆はDejaVu Sans Mono、aはUbuntu Mono、「あ」と右の◆はNoto Sans Mono CJK JP。 https://t.co/AKD9HfhYiJ」 / Twitter]], [TIME[午前3:39 · 2022年11月9日][2022-11-08T18:39:28.000Z]], [TIME[2022-11-09T04:52:53.000Z]] <https://twitter.com/ytomino/status/1590051393716768768>
[46] [CITE[クメール文字が書けない - Helpfeel社のScrapboxを一部公開]], [TIME[2023-07-06T09:34:07.000Z]] <https://scrapbox.io/nota-private-sample/%E3%82%AF%E3%83%A1%E3%83%BC%E3%83%AB%E6%96%87%E5%AD%97%E3%81%8C%E6%9B%B8%E3%81%91%E3%81%AA%E3%81%84>
[47]
[[文字]] (の情報システム上での表現) の知識がない技術者が設計すると >>46 のようなことが起きる。
欧米の技術者がシステムを設計するとアジア人が使えないものができるのと同じ原理。
[48]
[[書記素クラスター]]にうまく分割できればいいみたいな話になってるけど、それで[[語頭形]]とかの表示ちゃんとできてるんだろうか?