/
922.txt
805 lines (649 loc) · 34 KB
/
922.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
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
[61] [DFN[[CODE[GSUB]]]] は[[グリフ]]の置き換えを、
[DFN[[CODE[GPOS]]]] は[[グリフ]]の位置調整に関する情報を記述する
[[OpenType]] [[フォント]]の[[表][OpenType表]]です。
[104]
[DFN[[CODE[JSTF]]]]
は [[justification]] のための[[グリフ]]の置き換えや位置調整に関する情報を記述する
[[OpenType]] [[フォント]]の[[表][OpenType表]]です。
* 仕様書
[REFS[
-
[12]
[CITE@ja-jp[OpenType layout common table formats (OpenType 1.9) - Typography | [[Microsoft]] Docs]], [[PeterCon]], [TIME[2022-08-29T13:36:14.000Z]] <https://docs.microsoft.com/ja-jp/typography/opentype/spec/chapter2#features-and-lookups>
-
[67]
[CITE@ja-jp[OpenType layout common table formats (OpenType 1.9) - Typography | [[Microsoft]] Docs]], [[PeterCon]], [TIME[2022-08-30T11:17:29.000Z]] <https://docs.microsoft.com/ja-jp/typography/opentype/spec/chapter2#lookup-table>
-
[72]
[CITE@ja-jp[OpenType layout common table formats (OpenType 1.9) - Typography | [[Microsoft]] Docs]], [[PeterCon]], [TIME[2022-08-30T11:42:01.000Z]] <https://docs.microsoft.com/ja-jp/typography/opentype/spec/chapter2#common-structures-for-contextual-lookup-subtables>
- [1]
[CITE@en-us[GSUB — Glyph Substitution Table (OpenType 1.9) - Typography | Microsoft Docs]], [[PeterCon]], [TIME[2022-08-13T05:25:57.000Z]] <https://docs.microsoft.com/en-us/typography/opentype/spec/gsub>
-
[77]
[CITE@ja-jp[[[GPOS]] — Glyph Positioning Table (OpenType 1.9) - Typography | Microsoft Docs]], [[PeterCon]], [TIME[2022-09-04T12:39:10.000Z]] <https://docs.microsoft.com/ja-jp/typography/opentype/spec/gpos>
-
[103]
[CITE@ja-jp[[[JSTF]] — Justification Table (OpenType 1.9) - Typography | Microsoft Docs]], [[PeterCon]], [TIME[2022-09-08T09:23:07.000Z]] <https://docs.microsoft.com/ja-jp/typography/opentype/spec/jstf>
]REFS]
* 意味
[89]
[CODE[GSUB]] は [DFN[Glyph Substitution]] の意です。
[SRC[>>1]]
[76]
[CODE[GPOS]] は [DFN[Glyph Positioning]] の意です。
[SRC[>>77]]
* 構造
[5]
[CODE[GSUB]] には[[グリフ]]の置き換えのための対応表データが入っていて、
[CODE[GPOS]] には[[グリフ]]の利用に関係する[[座標]]等のデータが入っています。
[4]
[CODE[GSUB]],
[CODE[GPOS]]
とも似たような構造になっています。
末端のデータ等細部が微妙に違っているので注意が必要です。
[62]
どちらも、
まず対象となる[[用字系]]と[[言語系]]について、
それに関わる[[機能][フォント機能]]がいくつかあって、
[[機能][フォント機能]]における [[lookup]] がいくつかあり、
その [[lookup]] に条件と処理が書かれているという構造です。
[105]
[CODE[JSTF]]
は対象となる[[用字系]]と[[言語系]]について、
適用可能な調整がいくつかあるという構造です。
[CODE[JSTF]]
も
[[lookup]] を参照したり、含めたりできますが、
[CODE[GSUB]] や [CODE[GPOS]] とは構造が違います。
* 処理
[58] 表示処理全体の中での位置は[[文字のレンダリング]]参照。
[60] [[機能][フォント機能]]の選択方法は[[機能][フォント機能]]参照。
[85]
[CODE[GSUB]] の
[[lookup]] の条件に一致した場合は[[グリフ]](列)を[[グリフ]](列)に置き換えることになります。
このときどれがどれに変化したかはある程度追跡できる
(元の[[グリフ]](列)を得た大元の[[文字列]]との対応関係を知れる)
必要があります。
[SEE[ [[文字のレンダリング]] ]]
[81]
[CODE[GPOS]] の
[[lookup]] の条件に一致した場合に行うべき処理や
[[JstfMax lookup]] の解釈は、
[[グリフ位置決定]]を参照。
[159]
[[shaping]] において[[連なり]]に分割してから処理されるために、
[[用字系]]が違うと
[CODE[GSUB]]
が適用されないことがあるようです。
[SEE[ [[連なり]] ]]
* 機能
[8]
[CODE[GSUB]] [[表]],
[CODE[GPOS]] [[表]]は[[用字系]]や[[言語系]]に対して適用可能な[[機能][フォント機能]]を記述できます。
[SEE[ [[フォント機能]] ]]
[59]
[[機能][フォント機能]]に対して、実施されるべき操作を [[lookup]] として記述できます。
[46]
[CODE[GSUB]] [[表]],
[CODE[GPOS]] [[表]]には同じ[[タグ][機能タグ]]の[[機能][フォント機能]]を複数個含められます。
[[用字系]]や[[言語系]]に対してどの[[機能]]を適用するかを選択できますから、
同じ[[機能][フォント機能]]でも[[用字系]]と[[言語系]]に合わせて違う [[lookup]]
が適用されるようにできます。
* lookup
[144]
[DFN[lookup]] には[[グリフ]]列の一部分について一致するかしないかの条件と、
一致した場合に行う[[グリフ]](列)置換または[[グリフ]]の位置調整を記述できます。
[145]
[CODE[GSUB]] [[表][OpenType表]]と [CODE[GPOS]] [[表][OpenType表]]では、
それぞれの [DFN[[F[[CODE[LookupList]]]]]] 内に任意個含められます。
[SRC[>>103]]
[146] [F[[CODE[LookupList]]]] 中の [[lookup]] の出現順序 ([[索引]]) は、
- [147] 同じ[[表][OpenType表]]の[[機能][OpenType]]から参照するため
- [148] 同じ[[表][OpenType表]]の他の [[lookup]] から参照するため
- [149] [CODE[JSTF]] [[表][OpenType表]]の提案から参照するため
- [150] [[lookup]] 相互の適用順序を決めるため
... に使われます。
[151]
[CODE[JSTF]] [[表][OpenType表]]では、
各提案に行を長くする用と短くする用で各1つまで含められます。
[SRC[>>103]]
[152]
同じ [[lookup]] と呼ばれますが、
[CODE[GSUB]] [[表][OpenType表]]では[[グリフ]](列)の置換の記述のため、
[CODE[GPOS]] [[表][OpenType表]]では[[グリフ]]の位置調整の記述のため、
と少し構造が違います。
一致条件の部分が同じような意味、同じような構造でも、
[F[[CODE[lookupType]]]]
が両者で違っています。
-*-*-
[63]
[CODE[GSUB]] や [CODE[GPOS]] を適用するには、
[[用字系]], [[言語系]], [[機能][フォント機能]]から利用する
[[lookup]]
を決定します。
[SEE[ 選び方は[[フォント機能]] ]]
[64]
複数の [[lookup]] を適用する場合、
適用順序は
[CODE[LookupList]]
の出現順とします。
[SRC[>>12, >>67, >>1]]
1つの
[[lookup]]
で[[グリフ]]列を先頭から末尾まで処理し、
次の
[[lookup]]
へと進みます。
[SRC[>>67, >>1]]
ただし
[CODE[GSUB]] [F[[CODE[lookupType]]]] [N[8]]
は[[グリフ]]列の末尾から先頭に向かって処理します。
[SRC[>>1]]
[65]
[[フォント]]開発者は、
複数の[[機能][フォント機能]]を同時適用するときの相互作用を考慮して
[CODE[LookupList]]
中の [[lookup]] の順序を決められます。
1つの[[機能][フォント機能]]に複数の [[lookup]]
を結びつけることが出来ますから、
サンドイッチ式の適用も記述できます。
;; [66] ただし、全体の処理において[[機能][フォント機能]]ごとに複数回に分けて適用する場合もあり
[SEE[ [[フォント機能]] ]]、
その場合は[[フォント]]開発者の制御が及ばなくなります。
[68]
同時に複数の[[機能][フォント機能]]を適用する場合、
それらの [[lookup]] の[RUBYB[[[和集合]]][union]]を使います。
[SRC[>>67]]
つまり重複した [[lookup]] があるときは、1回分だけ適用されます。
[69]
なお、[[機能][フォント機能]]ごとに異なる部分[[グリフ]]列にのみ適用することができます。
[SRC[>>67]]
[70]
同じ [[lookup]] で異なる部分[[グリフ]]列に適用されるべきときはどうなるのでしょう。
適用対象の[[グリフ]]も[[和集合]]になるのでしょうか。
-*-*-
[78]
[[lookup]] には、
一致条件 (と一致時の挙動) を記述する[[部分表]]を1個[[以上]]含められます。
[SRC[>>77, >>1]]
[79]
各[[部分表]]はいくつかの種類があって、
[F[[CODE[substFormat]]]]
や
[F[[CODE[posFormat]]]]
によって区別されます。
どの形式によるかは記述方法の違いによるストレージ効率で選べます。
[[部分表]]ごとに違う形式も選べるので、
都合に応じて区分できます。
[SRC[>>77, >>1]]
[[部分表]]の構成の違いは [[lookup]] の挙動には直接影響しません。
;; [102]
ただし[[機能][フォント機能]]によっては実装状況が悪いのでこの形式でなければならない、
[[部分表]]は1個でなければならない、といった[[バッドノウハウ]]があるようです。
各[[機能][フォント機能]]の項参照。
[80]
とある入力が1つの [[lookup]] に含まれる複数の条件に一致することは、
明確には認められても禁止されてもいないようです。
その場合の挙動も不明です。
どんな入力にも高々1回だけ一致するようにするべきと思われます。
-*-*-
[13] [[lookup]]
は,
[CODE[lookupType]]
と
[CODE[substFormat]]
にもよりますが、
[[グリフ]]の列の一致条件を3通り記述できます。すなわち、
- [DFN[[RUBYB[[RUBY[後][あと]][RUBY[戻][もど]]り][backtrack]]]]する[[グリフ]]の0個以上の列
- [DFN[[RUBYB[[RUBY[入][にゅう]][RUBY[力][りょく]]][input]]]]の[[グリフ]]の1個以上の列
- [DFN[[RUBYB[[RUBY[先][さき]][RUBY[読][よ]]み][lookahead]]]]する[[グリフ]]の0個以上の列
[73]
ここで[[グリフ]]列は[[論理順]]とします。
[SRC[>>72]]
[14]
[[入力]]の[[グリフ]]列は、指定された処理が施される対象となります。
[15]
[[後戻り]]は[[入力]]の直前、
[[先読み]]は[[入力]]の直後にあるべき[[グリフ]]列で、
一致するかどうかの判断には使いますが、
処理の対象にはなりません。
[16]
一致した場合、[[入力]]の次の[[グリフ]]に進んで一致するかどうかの検査を繰り返します
[SRC[>>67, >>77]]。
[[先読み]]列があれば、その先頭からということになります。
[17]
ただし、
[CODE[GPOS]] の [CODE[lookupType]] [N[2]]
は2つの[[グリフ]]の組に対して値を設定するもので、
常に2つの[[グリフ]]が[[入力]]となるのですが、
第2[[グリフ]]に与えられた値がないときには、
その次の処理の[[入力]]は前の処理の第2[[グリフ]]からとなります。
[SRC[>>67, >>72, >>77]]
;; [18] 1つ [[lookup]] についての処理において、
[CODE[GPOS]] の組の指定の例外を除き、
[[入力]]列を処理して得られた出力に二重に処理が適用されることはありません。
[71]
[[先読み]]と[[後戻り]]が一致する[[グリフ]]は、
[[機能][フォント機能]]の適用対象となる[[グリフ]]でなくても構いません。
[SRC[>>67]]
[19]
[[入力]]の第2の[[グリフ]]以降[[先読み]]の最後の[[グリフ]]までの各[[グリフ]]の前、
あるいは[[後戻り]]の各[[グリフ]]の後には、
特定の種類の[[グリフ]]があったとしても、
一致判定においては無視する場合があります。
その条件は
[[lookup]]
の
[F[[CODE[lookupFlag]]]]
で記述されます。
- [20] [[lookup]] の [F[[CODE[lookupFlag]]]] の
[DFN[[CODE[IGNORE_BASE_GLYPHS]]]]
(ビット1)
が指定されている場合、
[CODE[GDEF]] [[表]]の[[グリフ級定義]]で [N[1]] (基底) とされた[[グリフ]]は無視します。
[SRC[>>1]]
- [21] [[lookup]] の [F[[CODE[lookupFlag]]]] の
[DFN[[CODE[IGNORE_LIGATURES]]]]
(ビット2)
が指定されている場合、
[CODE[GDEF]] [[表]]の[[グリフ級定義]]で [N[2]] (合字) とされた[[グリフ]]は無視します。
[SRC[>>1]]
- [22] [[lookup]] の [F[[CODE[lookupFlag]]]] の
[DFN[[CODE[IGNORE_MARKS]]]]
(ビット3)
が指定されている場合、
[CODE[GDEF]] [[表]]の[[グリフ級定義]]で [N[3]] (マーク) とされた[[グリフ]]は無視します。
[SRC[>>1]]
- [28]
[[lookup]] の [F[[CODE[lookupFlag]]]] の
[CODE[IGNORE_MARKS]]
が指定されていない場合、
-- [25] [[lookup]] の [F[[CODE[lookupFlag]]]] の
[DFN[[CODE[USE_MARK_FILTERING_SET]]]]
(ビット4)
が指定されている場合、
[[lookup]] の [DFN[[F[[CODE[markFilteringSet]]]]]]
を参照します。
[SRC[>>1]]
---
[26]
[DFN[[CODE[MarkFilteringSet]]]]
は
[CODE[uint16]]
です。
第[VAR[i]]ビットが[[マークグリフ集合群]]の第[VAR[i]]番の集合を表すと思われます。
---
[27]
指定された[[マークグリフ集合]]に''ない''[[マーク]]グリフは無視します。
[SRC[>>1]]
---
[30] ここでいう[[マーク]]は
[CODE[GDEF]] [[表]]の[[グリフ級定義]]で [N[3]] (マーク) とされた[[グリフ]]を指すと思われます。
--[29]
[[lookup]] の [F[[CODE[lookupFlag]]]] の
[CODE[USE_MARK_FILTERING_SET]]
が指定されていない場合、
--- [23] [[lookup]] の [F[[CODE[lookupFlag]]]] の
[DFN[[CODE[MARK_ATTACHMENT_TYPE_MASK]]]]
(ビット8 - ビット15)
が [N[0]] でない場合、
この16ビットを[[級値]]と解釈します。
[[マーク添付級]]が指定された値では''ない''[[マーク]]グリフは無視します。
[SRC[>>1]]
---- [24] ここでいう[[マーク]]は
[CODE[GDEF]] [[表]]の[[グリフ級定義]]で [N[3]] (マーク) とされた[[グリフ]]を指すと思われます。
;; [82] [F[[CODE[lookupFlag]]]] には他に [F[[CODE[RIGHT_TO_LEFT]]]]
[[フラグ]]がありますが、機能性は大きく違っています。
[34]
[[マーク]]系の機能が3つあります。
[[アラビア文字]]のように前後の文字との位置関係によって[[グリフ]]を変化させつつ、
主たる[[グリフ]]に付随する[[マーク]]は[[合字]]化の判定で適宜無視したりしなかったり、
といった条件を記述するために用意されているようです。
[35]
[[マーク添付級]]と[[マークグリフ集合]]は似たような機能ですが、
[[マークグリフ集合]]の方が記述能力が高い (複雑) です。
[[マークグリフ集合]]の方が後から追加された機能です。
[[マーク添付級]]だけでは不十分ということで追加されたのでしょうか。
[36]
[[グリフ級]]に基づく無視は
[CODE[GSUB]]
[CODE[lookupType]] [N[6]] と共にしばしば使われているようです。
[CODE[lookupType]] [N[6]]
では一致した[[入力列]]に更に他の [[lookup]]
を適用することになりますが、
このとき[[入力列]]の何番目の位置の[[グリフ]]であるかに依存して適用する
[[lookup]]
を決めます
([CODE[seqLookupRecords]])。
何番目であるかには、無視された[[グリフ]]を算入しません。
従って無視された[[グリフ]]の有無でどの [[lookup]] がどの[[グリフ]]に適用されるかは変化しませんし、
無視された[[グリフ]]には [[lookup]] が適用されません。
ただし一致した[[入力列]]の[[グリフ]]に対して [[lookup]]
を適用するときに、その [[lookup]] が前後の条件を記述していれば、
無視された[[グリフ]]の有無がその結果に影響を与える可能性はあります。
[37]
[CODE[GSUB]]
[CODE[lookupType]] [N[4]] (複数の[[グリフ]]の列から1つの[[合字]]への置き換え)
での利用も禁止されているわけではありませんが、
その意味するところは定かではありません。
無視して読み飛ばした[[グリフ]]も含めて[[入力列]]の全体が置き換えられるべきなのでしょうか?
[54]
[CODE[GPOS]] [CODE[lookupType]] [N[2]] ([[グリフ]]の組に対する位置調整)
での利用も禁止されているわけではありませんが、
どう適用されるべきなのか明確ではありません。
第1グリフは適用対象の[[グリフ]]の範囲が指定されますが、
第2グリフは任意(すべて)の[[グリフ]]が対象となり得ますから、
読み飛ばしとの相互作用をどうするべきか、
処理結果にいくつかの解釈が存在し得ます。
[56]
[CODE[GPOS]] [CODE[lookupType]] [N[4]], [N[5]], [N[6]]
は付加する[[マークグリフ]]と[[基底グリフ]], [[合字グリフ]],
基底となる[[マークグリフ]]との位置関係を調整するものです。
[[入力]]は付加しようとする[[マークグリフ]]です [SRC[>>77]]。
-
[83]
[CODE[GPOS]] [F[[CODE[lookupType]]]] [N[4]]
(Mark-to-Base Attachment Positioning, MarkBasePos)
では、
[[マークグリフ]]に対し、
[[グリフ]]列を遡って[[基底グリフ]]を探さなければ[RUBYB[なりません][must]]。
[SRC[>>77]]
-
[84]
[CODE[GPOS]] [F[[CODE[lookupType]]]] [N[5]]
(Mark-to-Ligature Attachment Positioning, MarkLigPos)
では、
[[マークグリフ]]に対し、
[[グリフ]]列を遡って[[合字グリフ]]を探さなければ[RUBYB[なりません][must]]。
[SRC[>>77]]
-
[86]
[CODE[GPOS]] [F[[CODE[lookupType]]]] [N[6]]
(Mark-to-Mark Attachment Positioning, MarkMarkPos)
では、
付加する[[マークグリフ]] mark1 に対し、
[[グリフ]]列を遡って基底となる[[マークグリフ]] mark2
を探します。
[SRC[>>77]]
[88]
[N[6]] では [F[[CODE[lookupFlag]]]] に応じて[[マークグリフ]] mark2 を探します。
[SRC[>>77]]
[87]
[N[4]] と [N[5]] も読み飛ばしとの相互作用がどう扱われるのが想定される挙動なのか不明瞭です。
-*-*-
[31]
[[入力列]],
[[先読み列]],
[[後戻り列]]として指定できる[[グリフ]]の列の長さ ([[グリフ]]の数)
には上限が規定されていません。
[[表]]に於いて個数を表す値が [CODE[uint16]] なので、
2[SUP[16]] - 1 が構造上の上限となります。
無視して読み飛ばす[[グリフ]]の個数にも上限が規定されていません。
[32]
実際の[[自然言語]]の記述に使うための[[フォント]]でそこまで長いものが必要にはなり得ませんから、
それよりずっと小さな、しかし十分大きな個数で探索を打ち切るような実装が普通でしょうし、
それをしないで杜撰に実装すると[[セキュリティー][文字のセキュリティー]]の問題にもなり得ます。
[33]
実際上どれくらいの長さが必要なのでしょうかね。
16個では少し心もとない気がします。
128個だと過大な気がします。
-*-*-
[51]
[CODE[GSUB]]
[CODE[lookupType]] [N[5]] は [CODE[lookupType]] [N[6]] に容易に書き換えられるようです。
[N[5]] の利用例が少ないのは [N[5]] の機能では不十分な場合が多いのでしょう。
[55]
[CODE[GPOS]]
は[[カーニング]]で
[N[2]]
が使われていることが多いようです。
[CODE[GPOS]]
[CODE[lookupType]]
[N[1]], [N[2]] しか対応していない実装もあります。
-*-*-
[47]
[[lookup]]
は[[機能]]から参照されて適用されるものと、
他の
[[lookup]]
から参照されるものとがあります。
[48]
[[入れ子]]の [[lookup]] は
[CODE[GSUB]]
[CODE[lookupType]] [N[1]] が多いですが、
[N[2]] の例もあります。
[49]
仕様書には[[入れ子]]にできる [CODE[lookupType]] の制限は特にないようですが、
どれも適用できるのか不安感はあります。
[52]
[CODE[GSUB]]
[CODE[lookupType]] [N[4]], [CODE[substFormat]] [N[1]]
を使った事例があります。
このとき入力の複数の隣接した[[グリフ]]が[[合字]]化された1つの[[グリフ]]に置き換えられることがあります。
[53]
もしその場合に[[入力列]]側で無視される[[グリフ]]が間に挟まっていたらどう処理されるべきなのか、
[[入れ子]]の [[lookup]] で使われる [CODE[sequenceIndex]] が指すのが[[合字]]化により消失する[[グリフ]]のときどう処理されるべきなのか、
よくわかりません。
[50]
実装によっては
[CODE[GSUB]]
[CODE[lookupType]] [N[1]], [CODE[substFormat]] [N[2]]
しか対応していないこともあるようです。
[57]
[[入れ子]]の [[lookup]] と >>17 の挙動の関係も若干不明瞭です。
[[入れ子]]の [[lookup]] でも適用される旨が仕様書には書かれている
[SRC[>>72]]
のですが、どういうイメージなのでしょう。
[74]
[[入れ子]]を二重以上深くできるのか不明です。仕様書では特に禁止はしていませんが。
[154]
[[JstfMax lookup]] は [CODE[GPOS]] [[lookup]] の [F[[CODE[lookupType]]]]
のうち contextual positioning lookups 以外を使えます。 [SRC[>>103]]
つまり[[入れ子]]に [[lookup]] するものは認められていないようです。
(指定された場合にどう処理するべきなのかは不明。)
* 文脈
[6]
[CODE[GSUB]],
[CODE[GPOS]]
とも必須の[[表]]ではなく、
不要な[[フォント]]には入っていません。
どちらかだけの[[フォント]]もあります。
[7]
といっても使わないで済むのは[[欧米]]や[[東アジア]]の昔ながらの簡易的な表示に使う[[フォント]]くらいのものです。
それ以外の地域で使われる[[文字]]の多くは
[CODE[GSUB]] や [CODE[GPOS]]
の機能が必要です。
[[欧米]]や[[東アジア]]の[[文字]]も、[[カーニング]]や[[縦書き]]や[[合字]]など、
高品質
[WEAK[(現在の計算機環境では標準的に実現されているレベルも含む。)]]
な[[文字のレンダリング]]にはそうした機能が必要となります。
* [CODE[GSUB]] 代替グリフの選択
[90]
[CODE[GSUB]] の [[lookup]] (群) を適応する処理は、
原則的に入力が1つの[[グリフ]]列、
出力も1つの[[グリフ]]列です。
[91]
ただし一部の [F[[CODE[lookupType]]]] (を使う一部の[[機能][フォント機能]])
は、 [CODE[GSUB]] [[lookup]] の適用結果に複数の候補を示すことが出来ます。
[EG[
[93] 例えば[[機能][フォント機能]] [CODE[salt]] は異なるデザインの多数の[[グリフ]]を提示できます。
]EG]
[92]
複数の結果になるのが最後の [[lookup]] なら複数通りの最終出力の可能性があり得ますし、
最後でない [[lookup]] ならそれ以降の [[lookup]] で最終出力の違いが更に広がっていく可能性があります。
1つの[[グリフ]]列中にそのような箇所が複数あれば、
最終出力はそれぞれの選択のすべての組合せ分あり得ることになります。
[94]
[CITE[[[OpenType]]]] 仕様書の[[機能タグ]]登録簿の記述によれば、
そうした[[機能][フォント機能]]は
[[DTP]] ソフトウェアの編集画面などに[[グリフ]]ごとに他の選択肢を表示して、
[[利用者]]に適切なものを選ばせることが想定されているようです。
[95]
1度限りの[[印刷]]なら選んで終わりで済みますが、
[[情報交換]]や長期保存のためには選択結果を恒久的に固定する方法が必要となります。
- [96]
1つは[[グリフID]]など[[グリフ]]を直接特定する方法です。
[SEE[ [[グリフ]] ]]
-- [101] この場合 [CODE[GSUB]] は編集中の[[グリフ]]検索の手段として用いただけで、
以後の参照には関係しないことになります。
- [97]
もう1つは得られた複数の候補の中で第何番目かを指定する方法です。
-- [98]
[[CSS Fonts]] ではこの方法が使われています。
[99]
どちらも[[フォント]]の改訂などで構造が変わってしまうと指していた[[グリフ]]が変わってしまうリスクはあります。
もっとも[[フォント]]の改訂はどの[[グリフ]]も前のものとの「同一性」が保たれる保証はないので、
あまり気にしても仕方がないかもしれません。互換性を気にする[[フォント]]開発者なら気を使ってくれるはずです。
それが期待できないなら[[フォント]]を[[埋め込む]]など、
利用[[フォント]]含め転送・保存するしかありません。
;; [100]
異なる[[フォント]]で[[グリフID]]や候補リスト中の位置が共通化されることはほぼ期待できません。
同じ[[フォント]]提供者による別の[[フォント]]なら、多少期待してもいいかもしれない、
という程度です。
[[グリフ]]特定に [[CID]] が使える (そして[[標準化]]された [[CID]] が振られている)
なら別ですが...
[155]
[CITE@ja[IllustratorとInDesignでaaltのルールが異なる件 - 帰ってきた💫Unicode刑事〔デカ〕リターンズ]], [TIME[2022-10-10T08:01:48.000Z]] <https://moji-memo.hatenablog.jp/entry/20070720/1184917140>
>Illustratorの「aalt 0」って、InDesignで言うところの「aalt 1」(CID順で1番目の異体字)のことだと思うのだが、なぜ別のルールを採用しているのだろう。
* [CODE[JSTF]] の調整
[106]
[[justification]] は期待される[[行]]長と実際の[[行]]の内容の長さの関係を調整する処理です。
[[グリフ]]間の[[スペース]]量を加減したり、[[グリフ]]を[[合字グリフ]]に置き換えたりします。
[107]
[CODE[JSTF]]
にはその[[フォント]]に適した調整方法と調整量の提案を何段階かに分けて記述できます
[SRC[>>103]]。
[[文字のレンダリング]]の際にはこれを参照してその[[フォント]]に適した
[[justification]] を実装できます。
[CITE[[[OpenType]]]] は具体的な [[justification]] の手法までは[[規定]]していません。
[[行]]長をもっと減らしたいとき、増やしたいときにどの[[グリフ]]をどうすればいいかを取得できますが、
もっと増やしたい、減らしたいという判断は別途行わないといけません。
[108]
[CODE[JSTF]] には、 [[用字系]]と[[言語系]]に対して、
適用可能な提案のリストが含まれます。
リスト中の各提案は、 priority level (影響の小さい順、「悪くない」順)
に並べて格納します。
適用時には、初めの提案から順に必要な提案まで適用していきます。
[SRC[>>103]]
[126]
各提案には次のデータを含められます。
[SRC[>>103]]
- [127] line shrinkage 用の [CODE[GSUB]] で有効にする [[lookup]] 群
- [128] line shrinkage 用の [CODE[GSUB]] で無効にする [[lookup]] 群
- [129] line shrinkage 用の [CODE[GPOS]] で有効にする [[lookup]] 群
- [130] line shrinkage 用の [CODE[GPOS]] で無効にする [[lookup]] 群
- [141] line shrinkage 用の [[JstfMax lookup]]
- [131] line extension 用の [CODE[GSUB]] で有効にする [[lookup]] 群
- [132] line extension 用の [CODE[GSUB]] で無効にする [[lookup]] 群
- [133] line extension 用の [CODE[GPOS]] で有効にする [[lookup]] 群
- [134] line extension 用の [CODE[GPOS]] で無効にする [[lookup]] 群
- [142] line extension 用の [[JstfMax lookup]]
[135] [CODE[GSUB]] や [CODE[GPOS]] の [[lookup]] は、
それぞれの[[表][OpenType表]] の [F[[CODE[LookupList]]]]
における[[index]]により指定します。
[SRC[>>103]]
[143]
[[JstfMax lookup]] ([[justify lookup]]) は
[CODE[JSTF]] [[表][OpenType表]]に直接記述します。
[SRC[>>103]]
[111]
提案を適用した調整は、次のようにします。
[SRC[>>103]]
[FIG(steps)[
= [139] [VAR[フォント]]を入力の[[フォント]]とします。
= [112] [VAR[原グリフ列]]を入力の[[グリフ]]列とします。
= [113] [VAR[機能群]]を入力の[[機能]]群とします。
= [137] [VAR[用字系]]を入力の[[用字系]]とします。
= [138] [VAR[言語系]]を入力の[[言語系]]とします。
= [136] [VAR[要望]]を入力の [I[line shrinkage]] または [I[line extension]]
とします。
= [116] [VAR[提案群]]を[VAR[フォント]]の [CODE[JSTF]]
[[表][OpenType表]]において[VAR[用字系]]と[VAR[言語系]]から決まる提案群とします。
= [114] [VAR[提案]]を、空の提案に設定します。
= [115] 繰り返し、
== [123] [VAR[lookup群]]を、
[VAR[フォント]]から[VAR[機能群]]の [[lookup]] を集めて整列した結果に設定します。
([[variable font]] の変更を踏まえて実際に適用される [[lookup]] を選びます。)
== [124] [VAR[lookup群]]を[VAR[提案]]と[VAR[要望]]に基づき編集します。
== [117] [VAR[グリフ列]]を、[VAR[原グリフ列]]に[VAR[lookup群]]を適用した結果に設定します。
== [118] [VAR[グリフ列]]の長さが適当と判断される場合、
=== [119] [VAR[グリフ列]]を返してここで停止します。
== [121] [VAR[提案群]]の次の提案がもうない場合、
=== [122] [VAR[グリフ列]]を返してここで停止します。
== [120] [VAR[提案]]を、[VAR[提案群]]の次の提案に設定します。
]FIG]
[125]
実際には1つの[[行]]は[[フォント]]や[[書字方向]]が違う複数の[[連なり]]で構成されているかもしれませんし、
[[機能][フォント機能]]はすべて同時に適用するのではなく [[shaping]]
過程で複数回に分けて適用されたり、[[グリフ]]列の一部分のみに適用されたりするのでしょうから、
ここに示した[[手順群]]がそのまま実行できるとは限りません。
[[追い込み]]や[[追い出し]]のため[[連なり]]を再構成する場合もあるかもしれません。
実際の[[手順群]]の構成は [[shaping]] の設計や [[justification]]
周りのアルゴリズムに依存します。
しかし [CODE[JSTF]] の指定の適用に関わる部分だけを眺めれば、
およそこのような[[手順群]]に要約できるものと考えられます。
[153] [[JstfMax lookup]] で設定された値の利用については[[グリフ位置決定]]を参照。
-*-*-
[109]
[CODE[JSTF]] には[[用字系]]ごとに[RUBYB[拡張子グリフ][extender glyph]]のリストも指定できます。
[[justification]] の処理では各提案の他にこの[[グリフ]]も使えます。
[SRC[>>103]]
[EG[
[110] 例えば[[アラビア文字]]の [[kashida]] をリストに含められます。
[SRC[>>103]]
]EG]
[140]
[CITE[OpenType]] 仕様としてはリストを指定できるだけで、その使い方は決められていません。
* 関連
[75]
実装の効率化のため、
[CODE[GPOS]] による[[添付点]]の情報を [CODE[GDEF]] に要約して記述することが出来ます。
[156]
似たもので組み合わせを指定するだけの [CODE[MERG]] があります。
* 実例
[10] 各 [[feature]] の利用例は [[font feature]] 参照。
[9]
[CITE[[[Nishiki-teki]]]]
は
[CODE[GSUB]],
[CODE[GPOS]]
ともに
[[script]]
が多数あって、
[CODE[langSysRecords]]
をも複数使っています。
また
[CODE[GSUB]],
[CODE[GPOS]]
ともに同じ [[feature]] tag の別の feature list item があります。
- [39] [CITE@ja['''['''こかげ''']''' フォント : Nu みちしるべ]], [TIME[2020-11-05T13:34:49.000Z]], [TIME[2022-08-18T05:18:48.827Z]] <http://kokagem.sakura.ne.jp/font/michishirube/>
--[40] [CITE@ja[「Nu みちしるべ」フォントの中身を見る - omuronの備忘録]], [TIME[2022-08-18T05:19:07.000Z]] <https://omuron.hateblo.jp/entry/2020/11/07/142500>
-[42] [CITE@en[GitHub - ayaka14732/FanWunMing: A Simplified-Chinese-to-Traditional-Chinese font based on GenYoMin, which can handle the one-to-many problem | 繁媛明朝是基於源樣明體開發的簡轉繁字型,能處理一簡對多繁]], [TIME[2022-08-18T05:28:22.000Z]] <https://github.com/ayaka14732/FanWunMing>
--[43] [CITE@zh-HK[正確實現簡轉繁字型]], [[三日月綾香]], [TIME[2022-07-05T04:28:59.000Z]], [TIME[2022-08-18T05:29:34.570Z]] <https://ayaka.shn.hk/s2tfont/hant/>
[45] >>42
[CODE[GSUB]]
1, 2; 3, 1
[CODE[GPOS]]
1, 1; 1, 2; 9, 1 (2, 1)
[44]
[CITE@en[โครงการอักษรอีสาน]], [TIME[2022-03-22T07:25:24.000Z]], [TIME[2022-08-18T05:37:35.328Z]] <https://linux.thai.net/~thep/esaan-scripts/>
[CITE[Khottabun]]
[CODE[GSUB]]
2, 1; 4, 1; 5, 2; 6, 1; 6, 2
([[入れ子]]の lookup が 2, 1; 4, 1)
[CODE[GPOS]]
4, 1; 6, 1
[41] [CITE@ja[Ken Lunde 小林剣さんはTwitterを使っています: 「Rendering 김일성, 김정일 & 김정은 via the #OpenType 'ccmp' GSUB feature using chaining contextual substitutions. 🇰🇵 🤔 #KPS9566 #UTC154 @DPRK_News https://t.co/Fi41NOsWsQ」 / Twitter]], 午前11:42 · 2018年1月7日 [TZ[+09:00]], [TIME[2022-08-18T05:03:26.000Z]] <https://twitter.com/ken_lunde/status/949833681354375168>
[157] [CITE@zh-HK[正確實現簡轉繁字型]], [[三日月綾香]], [TIME[2023-04-11T04:19:14.000Z]], [TIME[2023-07-03T14:02:11.747Z]] <https://ayaka.shn.hk/s2tfont/hant/>
[158] >>157 [[簡体字]]から[[繁体字]]への変換に [CODE[GSUB]] + [CODE[trad]]
を使う。
* 歴史
[11]
[CITE@en[opentype-layout/proposals at master · OpenType/opentype-layout · GitHub]], [TIME[2022-08-17T07:14:06.000Z]] <https://github.com/OpenType/opentype-layout/tree/master/proposals>
* メモ
[38]
[CITE[Spec for Thai OpenType Creation]], [TIME[2022-03-22T07:23:44.000Z]], [TIME[2022-08-18T02:34:48.288Z]] <https://linux.thai.net/~thep/th-otf/>
-
[2]
[CITE[Manipulating OpenType Lookups — FontForge 20220308 documentation]], [TIME[2022-07-16T19:58:44.000Z]], [TIME[2022-08-13T05:26:05.464Z]] <https://fontforge.org/docs/ui/dialogs/lookups.html>
[3] [CITE@ja[GSUB テーブル (1) - ScriptList]], [TIME[2022-08-13T05:26:21.000Z]] <https://aznote.jakou.com/prog/opentype/17_gsub1.html>