OSDN Git Service

Added the description of main process (doc/jfmglue.tex)
[luatex-ja/luatexja.git] / doc / jfmglue.tex
1 %#! time luatex jfmglue
2 \input s1sty.tex % style file
3 \newcount\ncount
4 \def\node#1{
5   \ifnum\ncount=0 \ncount=1\else\longrightarrow\fi
6   \setbox0=\hbox{\kern.5em$\mathstrut#1$\kern.5em}\dp0=0pt
7   \hbox{\vrule
8     $\vcenter{\hsize=\wd0\hrule\kern.5ex\copy0\kern.5ex\hrule}$%
9     \vrule\kern.1em}}
10 \def\nk{{\rm kern}\ }
11 \def\ng{{\rm glue}\ }
12 \def\np{{\rm penalty}\ }
13 \def\z{\,{\rm zw}}
14 \jfont\tenmini={file:ipam.ttf:slant=0.5;jfm=ujis} at 13\jQ
15
16 \centerline{\big Lua\TeX-ja 和文処理グルーについて}\bigskip
17 \centerline{\large\the\year/\the\month/\the\day}\medskip
18
19 本文書では,Lua\TeX-jaが(現時点において)和文処理に関わるglue/kernを
20 どのように挿入するかの内部処理について説明する.
21
22 \beginsection 予備知識
23
24 説明に入る前に,段落やhboxの中身は,\TeX の内部ではnode達による
25 リストとして表現されていることに注意する.nodeの種類については,
26 \hbox{\it The\ Lua\TeX\ Reference\/}の第8章を参照して欲しい.代表的なものを挙げると,
27
28 \item {\it glyph\_node}: 文字(合字も含む)を表現する.和文処理グルーを挿入する際には,
29 既に各{\it glyph\_node}が欧文文字のものか和文文字のものか区別がついている.
30 \item {\it glue\_node}: glueを表す.
31 \item {\it kern\_node}: kernを表す.各|kern_node|には|subtype|という値があり,
32 次の3種類を区別できるようになっている.
33 \itemitem 0: 欧文用TFM由来
34 \itemitem 1: 明示的な|\kern|か,イタリック補正 (|\/|) によるもの
35 \itemitem 2: 非数式アクセント用文字の左右位置調整のためのもの
36 \item {\it penalty\_node}: penaltyを表す.
37 \item {\it hlist\_node}: hbox(水平ボックス)を表す.
38 \enditem
39
40 以後,次のように,nodeがどのように連続しているかを表すことにする.
41 $$
42 \node{a}\node{b}_{\rm I}\node{c}
43 $$
44 右下についている添字は,Lua\TeX-ja においてそのnodeの役割を区別するためにつけられた
45 値であり,次のようになっている.
46 \begintt
47 I: イタリック補正由来の\kern
48 T: \[x]kanjiskipに置換されうる\kern
49 J: JFM由来のglue/kern
50 K: 禁則処理用penalty
51 E: 
52 KS: \kanjiskip
53 XS: \xkanjiskip
54 \endtt
55
56
57 \beginsection JFM由来グルーの挿入 ({\tt luatexja-jfmglue.lua})
58
59 JFM由来グルーの処理は,「連続する2つのnodeの間に何を入れるか」という単位で行われる.
60 そのため,
61 \item node生成を伴わないもの(グループ境界,|\relax|等)は全て無視される.
62 \item 一方,node生成を伴うものは全て「透過しない」.
63 例えば,次のソースにおいて,閉じ括弧と開き括弧の間に入る物は,
64 左と右とで異なる:
65 \begintt
66 )(  )\hbox{}(
67 \endtt
68 \item JFM由来グルーの挿入禁止を行う|\inhibitglue|は,内部では専用のnodeを作ること
69 によって実装している.この|\inhibitglue|用nodeは透過する.
70 \enditem
71 以下,$q$, $p$を連続するnodeとする.
72
73
74 \beginparagraph 2つの和文文字の間
75
76 この場合,グルー挿入に関係する量は次の通りである.これら3つの量の値によって,
77 $q$と$p$の間に何が挿入されるかが決定される.これらの記号は他の場合にも用いる.
78 \item $g$: JFMで指定された,$q$と$p$の間に入るglue/kern.
79 JFMで規定されていないときは$\emptyset$と書こう.
80 両ノードで使われているJFMが異なる時の$g$の決定方法は,後に記述する.
81 \item $w$: JFMで指定された,「$q$の直後で改行が行われた場合,
82 $q$と行末の間に入るカーン量」の値.
83
84 $g-w$で,$g$の自然長を$w$だけ減算したglue/kernを表すことにする.
85
86 \item $P$: $q$に対する行末禁則用ペナルティ (post-break penalty) と,
87 $p$に対する行頭禁則用ペナルティ (pre-break penalty) との和.どちらも
88 設定されていないときは0となる.
89 \enditem
90
91 設計方針としては,
92 \item JFM由来で入るものがkernの場合,この場所では行分割は許さない.
93 \item そうでない場合,(penaltyの値$P$があるが)この場所での行分割は可能である.
94 \enditem
95 である.さて,次が実際の場合わけである:
96
97 \enum $w\neq 0$, $g=\emptyset$のとき
98 $$\ncount=0
99 \node{q}
100 \node{\nk w}_{\rm E}
101 \node{\np P}_{\rm K}
102 \node{\nk{-w}}_{\rm T}
103 \node{p}
104 $$
105
106 \enum $w\neq 0$, $g\neq\emptyset$のとき:
107 $$\ncount=0
108 \node{q}
109 \node{\nk w}_{\rm E}
110 \node{\np P}_{\rm K}
111 \node{g-w}_{\rm J}
112 \node{p}
113 $$
114
115 \enum $w=0$, $g$: kernのとき
116 $$\ncount=0
117 \node{q}
118 \node{g}_{\rm J}
119 \node{p}
120 $$
121
122 \enum $w=0$, $g$: glueのとき
123 $$\ncount=0
124 \node{q}
125 \node{\np P}_{\rm K}
126 \node{g}_{\rm J}
127 \node{p}
128 $$
129
130 \enum $w=0$, $g=\emptyset$, $P\neq 0$のとき
131 $$\ncount=0
132 \node{q}
133 \node{\np P}_{\rm K}
134 \node{p}
135 $$
136
137 \enum $w=0$, $g=\emptyset$, $P=0$のとき
138 $$\ncount=0
139 \node{q}
140 \node{p}
141 $$
142 \enditem
143
144 なお,両ノードで使われているJFMが異なる時の$g$の決定方法であるが,
145 \enum $g_{\rm L}$を,$q$に使用されているJFMにおける,「$q$と文字|'diffmet'|」の間に
146 入るglue/kernの値とする.
147 \enum $g_{\rm R}$を,$p$に使用されているJFMにおける,「文字|'diffmet'|と$p$」の間に
148 入るglue/kernの値とする.
149 \enum 両方から,実際に入る$g$の値を計算する.
150 \itemitem $g_L$, $g_R$の少なくとも片方が$\emptyset$のときは,$\emptyset$でない方を
151 そのまま採用する.
152 \itemitem 両方とも$\emptyset$でない場合は,|differentjfm|の値にそって$g$の値を計算する.
153 \enditem
154
155 \beginparagraph 和文文字と(和文文字,kern以外のnode)の間
156
157 「和文文字の間」の場合に対して,以下が異なる:
158 \item $g$は,$q$に使用されているJFMにおける,「$q$と文字|'jcharbdd'|」の間に
159 入るglue/kernの値である.
160 \item $p$が{\bf penaltyでない場合}は,いつもこの位置で行分割できるようにするため,
161 case~6 ($w$, $P=0$, $g=\emptyset$) の場合にも,$q$と$p$の間には
162 0という値のpenaltyが入る.即ち,次のようになる.
163 $$\ncount=0
164 \node{q}
165 \node{\np 0}_{\rm K}
166 \node{p}
167 $$
168 \enditem
169
170 \beginparagraph (和文文字,kern以外のnode)と和文文字の間
171
172 この場合も,基本的には「和文文字の間」と似ているが,以下が異なる:
173 \item $g$は,$p$のJFMにおける,「文字|'jcharbdd'|と$p$」の間に
174 入るglue/kernの値である.
175 \item 常に$w=0$である.
176 \item いつもこの位置で行分割できるようにするため,
177 case~6 ($w$, $P=0$, $g=\emptyset$) の場合にも,$q$と$p$の間には
178 0という値のpenaltyが入る.
179 \enditem
180
181 即ち,次の3通りになる.
182 \enum $g$: kernのとき
183 $$\ncount=0
184 \node{q}
185 \node{g}_{\rm J}
186 \node{p}
187 $$
188
189 \enum $g$: glueのとき
190 $$\ncount=0
191 \node{q}
192 \node{\np P}_{\rm K}
193 \node{g}_{\rm J}
194 \node{p}
195 $$
196
197 \enum $g=\emptyset$のとき
198 $$\ncount=0
199 \node{q}
200 \node{\np P}_{\rm K}
201 \node{p}
202 $$
203 \enditem
204
205 \beginparagraph 和文文字とkernの間,kernと和文文字の間
206
207 和文文字の後にkernが続いた場合,あるいはkernの後に和文文字が続いた場合,
208 この間で行分割はできないものとしている.そのため,
209 以下の3ケースに限られる:
210 \enum $g$: kernのとき
211 $$\ncount=0
212 \node{q}
213 \node{g}_{\rm J}
214 \node{p}
215 $$
216
217 \enum $g$: glueのとき
218 $$\ncount=0
219 \node{q}
220 \node{\np 10000}_{\rm K}
221 \node{g}_{\rm J}
222 \node{p}
223 $$
224
225 \enum $g=\emptyset$のとき
226 $$\ncount=0
227 \node{q}
228 \node{p}
229 $$
230 \enditem
231
232 なお,ここでの$g$は,
233 \item kernが前だった場合は,
234 $q$のJFMにおける,「$q$と|'jcharbdd'|」の間に
235 入るglue/kernの値.
236 \item kernが後だった場合は,
237 $p$のJFMにおける,「|'jcharbdd'|と$p$」の間に
238 入るglue/kernの値.
239 \enditem
240
241 \beginparagraph 要検討の箇所
242
243 私が推測するに,欧文では,
244 \item 単語内ではフォントは変わらない.
245 \item 単語内では,明示的に/ハイフネーションにより挿入されたdiscretionary break以外では
246 行分割がおきない.
247 \enditem
248 という事情があるため,TFM由来のkernや合字処理は(nodeを生成しないもの以外は)
249 何も透過しないという状態になっているものと思われます.
250
251 そのため,JFMグルー等の仕様を考える場合,欧文でいう「単語」に対応するようなものは
252 何か,というのを考える必要があります.現実装では,素直に欧文の合字処理と同様のものであると考え,
253 透過するnodeはない,という仕様にしています.
254 しかし,|\[x]kanjiskip|の処理と共通にしてしまうというのも
255 考え方によってはありかもしれません.
256
257 \bigskip
258 \item {\bf イタリック補正のkernの周囲}
259
260 例えば,|jfm-ujis.lua|では,|'jcharbdd'|は文字クラス
261 0であるため,今の実装では,\hfil\break
262 「|)\/(|」という入力からは,次のnodeの並びを得る:
263 \setbox1=\hbox{|\/|}%
264 $$
265 \node{\hbox{)}}
266 \node{\np 10000}_{\rm K}
267 \node{\ng 0.5\z_{-0.5}}_{\rm J}
268 \node{\nk \copy1}
269 \node{\ng 0.5\z_{-0.5}}_{\rm J}
270 \node{\hbox{(}}
271 $$
272 一方,イタリック補正をJFM由来グルーが透過するとしたならば,当然
273 $$
274 \node{\hbox{)}}
275 \node{\nk \copy1}
276 \node{\ng 0.5\z_{-0.5}}
277 \node{\hbox{(}}
278 $$
279 となる(実際の組版イメージでは,
280 「{\tenmini 斜め)}\hbox{}(」「{\tenmini 斜め)}(」).どちらにするか?
281
282
283
284 \item {\bf penaltyの周囲}
285
286 これも,例えば次の設定の下では,「|)\penalty1701(|」からは以下を得る:
287 \itemitem 「)」と行末の間に$-0.5\z$だけkernを入れる.
288 \itemitem 「)」「(」の行頭/行末禁則用penaltyの値はどれも1000.
289 $$
290 \halign{$#$\hfil&$#$\hfil&$#$\hfil&$#$\hfil&$#$\hfil\cr
291 \node{\hbox{)}}&\ncount=1
292 \node{\nk {-0.5}\z}_{\rm E}&\ncount=1
293 \node{\np 1000}_{\rm K}&\ncount=1
294 \node{\ng 1\z_{-0.5}}_{\rm J}\cr
295 &\ncount=1\node{\np 1701}&\ncount=1
296 \node{\np 1000}_{\rm K}&\ncount=1
297 \node{\ng 0.5\z_{-0.5}}_{\rm J}&\ncount=1
298 \node{\hbox{(}}\cr}
299 $$
300 \leftskip2\zw
301 例えばpenaltyを合算することとした場合,上の入力例では本来「)」「(」の間に
302 1701のpenaltyがあるのだから,
303 $$
304 \halign{$#$\hfil&$#$\hfil&$#$\hfil&$#$\hfil&$#$\hfil&$#$\hfil\cr
305 \node{\hbox{)}}&\ncount=1
306 \node{\nk {-0.5}\z}_{\rm E}&\ncount=1
307 \node{\np 3701}_{\rm K}&\ncount=1
308 \node{\ng 0.5\z_{-0.5}}_{\rm J}&\ncount=1
309 \node{\hbox{(}}\cr
310 \node{\hbox{)}}&\ncount=1
311 \node{\nk {-0.5}\z}_{\rm E}&\ncount=1
312 \node{\np 3701}_{\rm K}&\ncount=1
313 \node{\ng 1\z_{-0.5}}_{\rm J}&\ncount=1
314 \node{\ng 0.5\z_{-0.5}}_{\rm J}&\ncount=1
315 \node{\hbox{(}}\cr
316 }
317 $$
318 のどちらか(上はpenaltyを透過する場合,下は透過しない場合)にするのが
319 良いと思われます.
320
321
322 \item {\bf discretionary breakの取り扱い}
323
324 discretionary break ({\it disc\_node})は,行分割時の行末の内容<pre>,
325 行頭の内容<post>,それに行分割しないときの内容<no_break>の3つをリストの形で
326 持っている.|linebreak.w|を見る限り,Lua\TeX でも<pre>, <post>, <no_break>の
327 中身にはglueやpenaltyを許容していないようだ.
328
329 現行の実装では,<pre>, <post>, <no_break>のどれも,和文フォントへの置換の
330 段階からして行われていない(だから中身は全部欧文扱いとなる).
331 {\small 単純にサボっていました|^^;|}
332 <pre>, <post>, <no_break>の中身にglueやpenaltyが許容されないことから,
333 これらに対する和文用処理の方法として,次の2種類が挙げられる.
334 私は前者で良いのではないかと思っているのだが…….
335 \itemitem (現行のまま)discretionary breakの中身に和文文字はないものと想定する.
336 例えば<pre>の中身に和文文字を入れたい場合は,<pre>の中身全体を
337 必ずhboxで括ることとする.
338 \itemitem 「glueを挿入」を全部「自然長だけを取り出したkernを挿入」に置き換え,
339 普段の和文処理グルー挿入処理を流用する.
340
341 \enditem
342
343 \beginsection {\tt \char"5C[x]kanjiskip}の挿入%"
344
345 現実装の|\[x]kanjiskip|の挿入の方針として,
346 \item JFMグルーが挿入されていないところに「標準の空き量」として挿入する.
347 \item 実際の段落/hboxの内容に即して,組版イメージの見た目に関係のないところは透過する.
348 \enditem
349
350 |\[x]kanjiskip|挿入処理では,次の3つのnodeを用いている.
351 $$\ncount=0
352 \node{\it nr}\longrightarrow\cdots
353 \node{\it nq}\longrightarrow\cdots
354 \node{\it np}
355 $$
356 \item $\it nr$と$\it np$の間に|\[x]kanjiskip|を挿入しようとする.
357 \item 実際にnodeの形で挿入しようとする場所は$\it nq$の直後である.
358 \item $\it nr$, $\it nq$は異なるnodeとは限らない.
359 \item $\it np$はリストの先頭から末尾までループで渡る.その過程で
360 $\it nr$, $\it nq$を適宜更新し,実際のnode挿入処理を行っている.
361 \enditem
362
363 ループの中で,以下の場合には$\it nr$は変化せず,${\it nq}\leftarrow {\it np}$となる.
364 つまり,これらのnodeに対して|\[x]kanjiskip|は透過する:
365 \item $\it np$がpenaltyの場合
366 \item $\it np$がkernであって,予備知識の項目で述べられた値が
367 $$
368 \hbox{I (イタリック補正),E(行末との間),T(一時的)}
369 $$
370 であるもの.後者2つはJFMグルーの挿入で入るものなので,
371 ユーザは「イタリック補正は透過」と考えればよい.
372 \item $\it np$がアクセント由来のもの.この場合は,$\it nq$は変化せず,
373 ${\it np}\leftarrow {\it next}({\it next}({\it np}))$となる.
374 \item $\it np$がinsertion, mark, |\vadjust|, whatsitのnodeである場合.
375 これらは水平リストからは消え去る運命にある.
376 \enditem
377
378 \end