1 %#! time luatex jfmglue
2 \input s1sty.tex % style file
5 \ifnum\ncount=0 \ncount=1\else\longrightarrow\fi
6 \setbox0=\hbox{\kern.5em$\mathstrut#1$\kern.5em}\dp0=0pt
8 $\vcenter{\hsize=\wd0\hrule\kern.5ex\copy0\kern.5ex\hrule}$%
12 \def\np{{\rm penalty}\ }
14 \jfont\tenmini={file:ipam.ttf:slant=0.5;jfm=ujis} at 13\jQ
16 \centerline{\big Lua\TeX-ja 和文処理グルーについて}\bigskip
17 \centerline{\large\the\year/\the\month/\the\day}\medskip
19 本文書では,Lua\TeX-jaが(現時点において)和文処理に関わるglue/kernを
20 どのように挿入するかの内部処理について説明する.
24 説明に入る前に,段落やhboxの中身は,\TeX の内部ではnode達による
25 リストとして表現されていることに注意する.nodeの種類については,
26 \hbox{\it The\ Lua\TeX\ Reference\/}の第8章を参照して欲しい.代表的なものを挙げると,
28 \item {\it glyph\_node}: 文字(合字も含む)を表現する.和文処理グルーを挿入する際には,
29 既に各{\it glyph\_node}が欧文文字のものか和文文字のものか区別がついている.
30 \item {\it glue\_node}: glueを表す.
31 \item {\it kern\_node}: kernを表す.各|kern_node|には|subtype|という値があり,
34 \itemitem 1: 明示的な|\kern|か,イタリック補正 (|\/|) によるもの
35 \itemitem 2: 非数式アクセント用文字の左右位置調整のためのもの
36 \item {\it penalty\_node}: penaltyを表す.
37 \item {\it hlist\_node}: hbox(水平ボックス)を表す.
40 以後,次のように,nodeがどのように連続しているかを表すことにする.
42 \node{a}\node{b}_{\rm I}\node{c}
44 右下についている添字は,Lua\TeX-ja においてそのnodeの役割を区別するためにつけられた
48 T: \[x]kanjiskipに置換されうる\kern
57 \beginsection JFM由来グルーの挿入 ({\tt luatexja-jfmglue.lua})
59 JFM由来グルーの処理は,「連続する2つのnodeの間に何を入れるか」という単位で行われる.
61 \item node生成を伴わないもの(グループ境界,|\relax|等)は全て無視される.
62 \item 一方,node生成を伴うものは全て「透過しない」.
63 例えば,次のソースにおいて,閉じ括弧と開き括弧の間に入る物は,
68 \item JFM由来グルーの挿入禁止を行う|\inhibitglue|は,内部では専用のnodeを作ること
69 によって実装している.この|\inhibitglue|用nodeは透過する.
71 以下,$q$, $p$を連続するnodeとする.
74 \beginparagraph 2つの和文文字の間
76 この場合,グルー挿入に関係する量は次の通りである.これら3つの量の値によって,
77 $q$と$p$の間に何が挿入されるかが決定される.これらの記号は他の場合にも用いる.
78 \item $g$: JFMで指定された,$q$と$p$の間に入るglue/kern.
79 JFMで規定されていないときは$\emptyset$と書こう.
80 両ノードで使われているJFMが異なる時の$g$の決定方法は,後に記述する.
81 \item $w$: JFMで指定された,「$q$の直後で改行が行われた場合,
84 $g-w$で,$g$の自然長を$w$だけ減算したglue/kernを表すことにする.
86 \item $P$: $q$に対する行末禁則用ペナルティ (post-break penalty) と,
87 $p$に対する行頭禁則用ペナルティ (pre-break penalty) との和.どちらも
92 \item JFM由来で入るものがkernの場合,この場所では行分割は許さない.
93 \item そうでない場合,(penaltyの値$P$があるが)この場所での行分割は可能である.
97 \enum $w\neq 0$, $g=\emptyset$のとき
102 \node{\nk{-w}}_{\rm T}
106 \enum $w\neq 0$, $g\neq\emptyset$のとき:
115 \enum $w=0$, $g$: kernのとき
122 \enum $w=0$, $g$: glueのとき
130 \enum $w=0$, $g=\emptyset$, $P\neq 0$のとき
137 \enum $w=0$, $g=\emptyset$, $P=0$のとき
144 なお,両ノードで使われているJFMが異なる時の$g$の決定方法であるが,
145 \enum $g_{\rm L}$を,$q$に使用されているJFMにおける,「$q$と文字|'diffmet'|」の間に
147 \enum $g_{\rm R}$を,$p$に使用されているJFMにおける,「文字|'diffmet'|と$p$」の間に
149 \enum 両方から,実際に入る$g$の値を計算する.
150 \itemitem $g_L$, $g_R$の少なくとも片方が$\emptyset$のときは,$\emptyset$でない方を
152 \itemitem 両方とも$\emptyset$でない場合は,|differentjfm|の値にそって$g$の値を計算する.
155 \beginparagraph 和文文字と(和文文字,kern以外のnode)の間
157 「和文文字の間」の場合に対して,以下が異なる:
158 \item $g$は,$q$に使用されているJFMにおける,「$q$と文字|'jcharbdd'|」の間に
160 \item $p$が{\bf penaltyでない場合}は,いつもこの位置で行分割できるようにするため,
161 case~6 ($w$, $P=0$, $g=\emptyset$) の場合にも,$q$と$p$の間には
162 0という値のpenaltyが入る.即ち,次のようになる.
170 \beginparagraph (和文文字,kern以外のnode)と和文文字の間
172 この場合も,基本的には「和文文字の間」と似ているが,以下が異なる:
173 \item $g$は,$p$のJFMにおける,「文字|'jcharbdd'|と$p$」の間に
176 \item いつもこの位置で行分割できるようにするため,
177 case~6 ($w$, $P=0$, $g=\emptyset$) の場合にも,$q$と$p$の間には
197 \enum $g=\emptyset$のとき
205 \beginparagraph 和文文字とkernの間,kernと和文文字の間
207 和文文字の後にkernが続いた場合,あるいはkernの後に和文文字が続いた場合,
208 この間で行分割はできないものとしている.そのため,
220 \node{\np 10000}_{\rm K}
225 \enum $g=\emptyset$のとき
234 $q$のJFMにおける,「$q$と|'jcharbdd'|」の間に
237 $p$のJFMにおける,「|'jcharbdd'|と$p$」の間に
241 \beginparagraph 要検討の箇所
244 \item 単語内ではフォントは変わらない.
245 \item 単語内では,明示的に/ハイフネーションにより挿入されたdiscretionary break以外では
248 という事情があるため,TFM由来のkernや合字処理は(nodeを生成しないもの以外は)
249 何も透過しないという状態になっているものと思われます.
251 そのため,JFMグルー等の仕様を考える場合,欧文でいう「単語」に対応するようなものは
252 何か,というのを考える必要があります.現実装では,素直に欧文の合字処理と同様のものであると考え,
253 透過するnodeはない,という仕様にしています.
254 しかし,|\[x]kanjiskip|の処理と共通にしてしまうというのも
258 \item {\bf イタリック補正のkernの周囲}
260 例えば,|jfm-ujis.lua|では,|'jcharbdd'|は文字クラス
261 0であるため,今の実装では,\hfil\break
262 「|)\/(|」という入力からは,次のnodeの並びを得る:
263 \setbox1=\hbox{|\/|}%
266 \node{\np 10000}_{\rm K}
267 \node{\ng 0.5\z_{-0.5}}_{\rm J}
269 \node{\ng 0.5\z_{-0.5}}_{\rm J}
272 一方,イタリック補正をJFM由来グルーが透過するとしたならば,当然
276 \node{\ng 0.5\z_{-0.5}}
280 「{\tenmini 斜め)}\hbox{}(」「{\tenmini 斜め)}(」).どちらにするか?
284 \item {\bf penaltyの周囲}
286 これも,例えば次の設定の下では,「|)\penalty1701(|」からは以下を得る:
287 \itemitem 「)」と行末の間に$-0.5\z$だけkernを入れる.
288 \itemitem 「)」「(」の行頭/行末禁則用penaltyの値はどれも1000.
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
301 例えばpenaltyを合算することとした場合,上の入力例では本来「)」「(」の間に
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
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
318 のどちらか(上はpenaltyを透過する場合,下は透過しない場合)にするのが
322 \item {\bf discretionary breakの取り扱い}
324 discretionary break ({\it disc\_node})は,行分割時の行末の内容<pre>,
325 行頭の内容<post>,それに行分割しないときの内容<no_break>の3つをリストの形で
326 持っている.|linebreak.w|を見る限り,Lua\TeX でも<pre>, <post>, <no_break>の
327 中身にはglueやpenaltyを許容していないようだ.
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>の中身全体を
338 \itemitem 「glueを挿入」を全部「自然長だけを取り出したkernを挿入」に置き換え,
343 \beginsection {\tt \char"5C[x]kanjiskip}の挿入%"
345 現実装の|\[x]kanjiskip|の挿入の方針として,
346 \item JFMグルーが挿入されていないところに「標準の空き量」として挿入する.
347 \item 実際の段落/hboxの内容に即して,組版イメージの見た目に関係のないところは透過する.
350 |\[x]kanjiskip|挿入処理では,次の3つのnodeを用いている.
352 \node{\it nr}\longrightarrow\cdots
353 \node{\it nq}\longrightarrow\cdots
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挿入処理を行っている.
363 ループの中で,以下の場合には$\it nr$は変化せず,${\it nq}\leftarrow {\it np}$となる.
364 つまり,これらのnodeに対して|\[x]kanjiskip|は透過する:
365 \item $\it np$がpenaltyの場合
366 \item $\it np$がkernであって,予備知識の項目で述べられた値が
368 \hbox{I (イタリック補正),E(行末との間),T(一時的)}
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 これらは水平リストからは消え去る運命にある.