OSDN Git Service

Merge branch 'kitagawa_test' into master
authorHironori Kitagawa <h_kitagawa2001@yahoo.co.jp>
Thu, 18 Aug 2011 06:40:24 +0000 (15:40 +0900)
committerHironori Kitagawa <h_kitagawa2001@yahoo.co.jp>
Thu, 18 Aug 2011 06:40:24 +0000 (15:40 +0900)
39 files changed:
doc/jfmglue.pdf
doc/jfmglue.tex
doc/sample1.pdf
doc/sample1.tex
src/jfm-mono.lua
src/jfm-ujis.lua
src/lltjdefs.sty [new file with mode: 0644]
src/lltjfont.sty [new file with mode: 0644]
src/luatexja-base.sty
src/luatexja-core.lua
src/luatexja-core.sty
src/luatexja-jfmglue.lua [deleted file]
src/luatexja-kinsoku.tex
src/luatexja-latex.sty [new file with mode: 0644]
src/luatexja-plain.sty
src/luatexja-xkanji.lua [deleted file]
src/luatexja/charrange.lua
src/luatexja/compat.lua
src/luatexja/inputbuf.lua
src/luatexja/jfmglue.lua [new file with mode: 0644]
src/luatexja/jfont.lua [moved from src/luatexja-jfont.lua with 76% similarity]
src/luatexja/pretreat.lua [new file with mode: 0644]
src/luatexja/rmlgbm.lua [moved from src/luatexja-rmlgbm.lua with 90% similarity]
src/luatexja/setwidth.lua [new file with mode: 0644]
src/luatexja/stack.lua
test/jfm-bad.lua
test/jfm-hang.lua
test/jfm-test.lua
test/test01-noembed.pdf
test/test01.pdf
test/test01.tex
test/test02-latex.pdf
test/test02-latex.tex
test/test04-jfm.pdf
test/test04-jfm.tex
test/test05-speed.pdf [deleted file]
test/test05-speed.tex
test/test06-offset.pdf [new file with mode: 0644]
test/test06-offset.tex [new file with mode: 0644]

index 59a3d9d..20fb35c 100644 (file)
Binary files a/doc/jfmglue.pdf and b/doc/jfmglue.pdf differ
index dc43420..d44ee51 100644 (file)
@@ -6,7 +6,7 @@
   \setbox0=\hbox{\kern.5em$\mathstrut#1$\kern.5em}\dp0=0pt
   \hbox{\vrule
     $\vcenter{\hsize=\wd0\hrule\kern.5ex\copy0\kern.5ex\hrule}$%
-    \vrule\kern.1em}}
+    \vrule\kern.1em}{}}
 \def\nk{{\rm kern}\ }
 \def\ng{{\rm glue}\ }
 \def\np{{\rm penalty}\ }
 本文書では,Lua\TeX-jaが(現時点において)和文処理に関わるglue/kernを
 どのように挿入するかの内部処理について説明する.
 
+\bigskip
+{\large\bf\noindent これは仕様・内部処理の提案の1つにしかすぎません.最終的にこのようになる
+保証はどこにもありませんし,現時点でのLuaコードが本文書に従っている保証もありません.
+バグが混入している可能性も大きいです.}
+
 \beginsection 予備知識
 
 説明に入る前に,段落やhboxの中身は,\TeX の内部ではnode達による
 
 \item 次のように,nodeがどのように連続しているかを表すことにする.
 $$
-\node{a}\node{b}_{\rm I}\node{c}
+\node{a}\node{b}_{1}\node{c}
 $$
-å\8f³ä¸\8bã\81«ã\81¤ã\81\84ã\81¦ã\81\84ã\82\8bæ·»å­\97ã\81¯ï¼\8cLua\TeX-jaã\81«ã\81\8aã\81\84ã\81¦ã\81\9dã\81®nodeã\81®å½¹å\89²ã\82\92å\8cºå\88¥ã\81\99ã\82\8bã\81\9fã\82\81ã\81«ã\81¤ã\81\91ã\82\89ã\82\8cã\81\9f
-値(jtypeと呼ぼう)であり,次のようになっている.
+ä¸\8bæ·»å­\97ã\81¯ï¼\8cLua\TeX-jaã\81«ã\81\8aã\81\84ã\81¦ã\81\9dã\81®nodeã\81®å½¹å\89²ã\82\92å\8cºå\88¥ã\81\99ã\82\8bã\81\9fã\82\81ã\81«ã\81¤ã\81\91ã\82\89ã\82\8cã\81\9f
+値(icflagと呼ぼう)であり,次のようになっている.
 $$
 \vbox{\halign{#:\ \hfil&#\hfil\quad&#:\ \hfil&#\hfil\cr
-I&イタリック補正由来のkern&
-T&|\[x]kanjiskip|に置換されうるkern\cr
-J&JFM由来のglue/kern&
-K&禁則処理用penalty\cr
-E&「行末」との間に入るkern&
-KS&|\kanjiskip|用glue\cr
-XS&|\xkanjiskip|用glue\cr
+1&イタリック補正由来のkern &
+2&幅補正のため,hboxにカプセル化された和文文字\cr
+3&禁則処理用penalty&
+4&JFM由来のglue/kern\cr
+5&「行末」との間に入るkern&
+6&|\kanjiskip|用glue\cr
+7&|\xkanjiskip|用glue&
+8&既に処理対象となったnode\cr
+15&リスト先頭/末尾に入るglue/kern/penalty\span\omit\span\cr
 }}
 $$
+和文処理グルーの挿入処理に一度通されたnodeは,みなicflagが3以上となることに注意.
+
+なお,上添字はnodeのsubtypeを表す.
 \item {\sf jaxspmode}のようなサンセリフ体で,|\ltjsetparameter|で設定可能なパラメタ値を表す.
-\item タイプライタ体の|\kanjiskip|, |\xkanjiskip|は,それぞれ「和文間空白」「和欧文間空白」の意味で
-抽象的に用いている.
+\item タイプライタ体の|\kanjiskip|, |\xkanjiskip|は,
+それぞれ「和文間空白」「和欧文間空白」の意味で抽象的に用いている.
 \item nil値は$\emptyset$と書く.
 \enditem
 
-\beginsection JFM由来グルーの挿入 ({\tt luatexja-jfmglue.lua})
+\beginsection 方針など
+
+本バージョンにおいては,JFM由来グルーと|\[x]kanjiskip|の挿入は同じ段階で行われる.
+大雑把に言うと,
+$$
+\vbox{\hsize=0.85\hsize\bf 和文処理グルーの挿入処理では,以下は存在しないものとして扱われる:
+\item 「文字に付属する」アクセントやイタリック補正.
+\item 行中数式の内部.
+\item 実際の組版中には現れないinsertion, vadjust, mark, whatsit node達.
+\enditem}
+$$
+
+\beginparagraph 和文文字の「自然長」(JFMにおける{\tt width}の指定値)について
+
+p\TeX においては,和文文字の行頭と行末に自動的にglueやkernをおくことはできなかったことから,
+JFMにおける文字幅の意味は,
+$$
+\hbox{\vbox{\hsize=0.8\hsize \noindent
+「その文字が行頭におかれるときの,版面左端の位置」を左端,\hfill\break
+「その文字が行末におかれるときの,版面右端の位置」を右端としたときの幅}}
+$$
+というように,明確な意味があるものであった.例えば,乙部さんによるぶら下げ組パッケージ ({\tt burasage.lzh})
+においては,句読点類(「|,、.。|」の4文字)の文字幅は0.0となっている.
+
+一方,Lua\TeX-ja においては,和文文字が行末にきた場合,その文字と行末の間にkernを挿入することができる:
+例えば,前に挙げた4文字についてぶら下げ組をしたいのであれば,
 
-JFM由来グルーの処理は,「連続する2つのnodeの間に何を入れるか」という単位で行われる.
-そのため,
-\item node生成を伴わないもの(グループ境界,|\relax|等)は全て無視される.
-\item 一方,node生成を伴うものは全て「透過しない」.
-例えば,次のソースにおいて,閉じ括弧と開き括弧の間に入る物は,
-左と右とで異なる:
 \begintt
-)(  )\hbox{}(
+   [1701] = {
+      chars = { 'lineend' }
+   },
+   [42] = {
+      chars = { ',', '、', '.', '。' },
+      align = 'left', left = 0.0, down = 0.0,
+      width = 0.5, height = 0.88, depth = 0.12, italic=0.0,
+      kern = { [1701] = -0.5, ...}
+   }, ...
 \endtt
-\item 「現在位置でのJFM由来グルーの挿入抑制」を行う|\inhibitglue|は,内部では専用のwhatsit node 
-($\hbox{\tt subtype}=44$, \setbox0=\hbox{|user_id|}$\copy0=30111$)を作ること
-によって実装している.これらのnodeは,「現在位置で挿入しない」というフラグを立てるためだけ
-に存在するものであって,挿入処理中に全て削除される.
-\enditem
-以下,$q$, $p$を連続するnodeとする.
+のように,「文字|'lineend'|との間に負のkernをおく」ように指定すればよい.
+そのため,p\TeX と比較すると,JFMにおける|width|の指定値に絶対的な意味はあまりないことになる.
+{\small 行頭にもkern をおけるようにするかどうかは検討中である.}
 
-\beginparagraph 2つの和文文字の間
 
-この場合,グルー挿入に関係する量は次の通りである.これら3つの量の値によって,
-$q$と$p$の間に何が挿入されるかが決定される.これらの記号は他の場合にも用いる.
-\item $g$: JFMで指定された,$q$と$p$の間に入るglue/kern.
-JFMで規定されていないときは$\emptyset$と書こう.
-両ノードで使われているJFMが異なる時の$g$の決定方法は,後に記述する.
-\item $w$: JFMで指定された,「$q$の直後で改行が行われた場合,
-$q$と行末の間に入るカーン量」の値.
+\beginparagraph グルーの挿入単位「塊」
 
-また,$g-w$で,$g$の自然長を$w$だけ減算したglue/kernを表すことにする($g$がglueならばこのnodeはglue,$g$がkernならばkern).
+和文処理グルーの挿入処理は,
+ごく大雑把にいうと,「連続する2つのnodeの間に何を挿入するか」の繰り返しである.
+実際の挿入処理は,「隣り合った2つの『塊』\IT{Nq}, \IT{Np}の間に何を入れるか」を
+単位として行われる.
 
-\item $P$: $q$に対する行末禁則用ペナルティ (post-break penalty) と,
-$p$に対する行頭禁則用ペナルティ (pre-break penalty) との和.どちらも
-設定されていないときは0となる.
-\enditem
-なお,間に|\inhibitglue|による指定があった場合,$g=\emptyset$, $w=0$として処理される.
+\medskip\noindent{\bf 定義}\quad
+「{\bf 塊}」(\IT{Nn}などで表す)とは,次の4つのいずれかの条件を満たすnode(達のリスト)
+のことである:
+\enum icflagが3以上15未満であるnode達の連続からなるリスト.
 
-設計方針としては,
-\item JFM由来で入るものがkernの場合,この場所では行分割は許さない.
-\item そうでない場合,(penaltyの値$P$があるが)この場所での行分割は可能である.
-\enditem
-である.さて,次が実際の場合わけである:
-
-\enum $w\neq 0$, $g=\emptyset$のとき
-$$\ncount=0
-\node{q}
-\node{\nk w}_{\rm E}
-\node{\np P}_{\rm K}
-\node{\nk{-w}}_{\rm T}
-\node{p}
-$$
-この$\node{\nk{-w}}_{\rm T}$は,
-「$q$と$p$の間で行分割されないときは間に何のglue/kernもないように見える」ために
-挿入されたものである.次のステップで|\[x]kanjiskip|の挿入が行われる時に,このnodeは
-|\[x]kanjiskip|用のglueに置換される.
-
-\enum $w\neq 0$, $g\neq\emptyset$のとき:
-$$\ncount=0
-\node{q}
-\node{\nk w}_{\rm E}
-\node{\np P}_{\rm K}
-\node{g-w}_{\rm J}
-\node{p}
-$$
+このようなnode達は,既に組み上がったhboxを|\unpackage|により解体したときに発生する.
+一度和文処理グルーの挿入処理が行われているため,二重の処理を防ぐためにこうして1つの塊を構成させている.
 
-\enum $w=0$, $g$: kernのとき
-$$\ncount=0
-\node{q}
-\node{g}_{\rm J}
-\node{p}
+なお,icflagが15であるnodeは,処理中に発見されしだい削除される
+(hboxの先頭や末尾に挿入されたglue/kern/penaltyであるので,
+本来の「段落/hboxの中身に適宜グルーを挿入する」という目的を考えると存在すべきでない).
+\enum 数式開始を表す\IT{math\_node}から始まる文中数式を表すnodeのリスト:
 $$
-
-\enum $w=0$, $g$: glueのとき
-$$\ncount=0
-\node{q}
-\node{\np P}_{\rm K}
-\node{g}_{\rm J}
-\node{p}
+ \node{\hbox{数式境界(開始)}}
+ \longrightarrow\hbox{(この間,行中数式が続く)}
+ \node{\hbox{数式境界(終了)}}
 $$
-
-\enum $w=0$, $g=\emptyset$, $P\neq 0$のとき
-$$\ncount=0
-\node{q}
-\node{\np P}_{\rm K}
-\node{p}
+\enum \IT{glyph\_node}~$p$と,それと切り離すことが望ましくないと考えられるnode達:
 $$
-
-\enum $w=0$, $g=\emptyset$, $P=0$のとき
-$$\ncount=0
-\node{q}
-\node{p}
+ \Bigl[\node{\nk\hskip-.5em}^2
+ \node{\hbox{アクセント文字}}
+ \node{\nk\hskip-.5em}^2\Bigr]
+ \node{p}
+ \Bigl[\node{\nk\hskip-.5em}_1\Bigr]
 $$
-\enditem
+但し,これには$p$が${\rm icflag}=2$のhboxである場合も含む.%
+{\small ←この場合の処理は実はおこらない?}
+\enum {\bf 以下のどれにもあてはまらない}node~$p$:
+\itemitem 組版結果からは消えてしまう,\IT{ins\_node}, 
+\IT{mark\_node}, \IT{adjust\_node}, \IT{whatsit\_node}.
+\itemitem penalty(←但し,挿入処理の過程で値が変更されることはある)
 
-なお,両ノードで使われているJFMが異なる時の$g$の決定方法であるが,
-\enum $g_{\rm L}$を,$q$に使用されているJFMにおける,「$q$と文字|'diffmet'|」の間に
-入るglue/kernの値とする.
-\enum $g_{\rm R}$を,$p$に使用されているJFMにおける,「文字|'diffmet'|と$p$」の間に
-入るglue/kernの値とする.
-\enum 両方から,実際に入る$g$の値を計算する.
-\itemitem $g_L$, $g_R$の少なくとも片方が$\emptyset$のときは,$\emptyset$でない方を
-そのまま採用する.
-\itemitem 両方とも$\emptyset$でない場合は,|differentjfm|の値にそって$g$の値を計算する.
 \enditem
 
-\beginparagraph 和文文字と(和文文字,kern以外のnode)の間
-
-「和文文字の間」の場合に対して,以下が異なる:
-\item $g$は,$q$に使用されているJFMにおける,「$q$と文字|'jcharbdd'|」の間に
-入るglue/kernの値である.
-\item $p$が{\bf penaltyでない場合}は,いつもこの位置で行分割できるようにするため,
-case~6 ($w$, $P=0$, $g=\emptyset$) の場合にも,$q$と$p$の間には
-0という値のpenaltyが入る.即ち,次のようになる.
-$$\ncount=0
-\node{q}
-\node{\np 0}_{\rm K}
-\node{p}
-$$
-\enditem
+\medskip\noindent{\bf 記号}\quad
+\IT{Bp}で,塊\IT{Nq}と塊\IT{Np}の間にある\IT{penalty\_node}達の配列を表す.
 
-\beginparagraph (和文文字,kern以外のnode)と和文文字の間
 
-この場合も,基本的には「和文文字の間」と似ているが,以下が異なる:
-\item $g$は,$p$のJFMにおける,「文字|'jcharbdd'|と$p$」の間に
-入るglue/kernの値である.
-\item 常に$w=0$である.
-\item いつもこの位置で行分割できるようにするため,
-case~6 ($w$, $P=0$, $g=\emptyset$) の場合にも,$q$と$p$の間には
-0という値のpenaltyが入る.
-\enditem
+\beginsection 挿入処理の大枠
 
-即ち,次の3通りになる.
-\enum $g$: kernのとき
-$$\ncount=0
-\node{q}
-\node{g}_{\rm J}
-\node{p}
-$$
+\beginparagraph 「塊」の保持するデータ
 
-\enum $g$: glueのとき
-$$\ncount=0
-\node{q}
-\node{\np P}_{\rm K}
-\node{g}_{\rm J}
-\node{p}
-$$
+「塊」\IT{Np}は,内部では少なくとも次の要素を持ったテーブルとして表される:
 
-\enum $g=\emptyset$のとき
-$$\ncount=0
-\node{q}
-\node{\np P}_{\rm K}
-\node{p}
-$$
+\item \IT{.first}: \IT{Np}の先頭のnode.
+\item \IT{.nuc}: \IT{Np}の「核」となるnode.
+\itemitem 1., 2.によるものである場合,$\mibox{Np.nuc}=\mibox{Np.first}$.
+\item \IT{.last}: \IT{Np}の最後のnode.
+\item \IT{.id}: \IT{Np}の種類を表す値.
+\itemitem 1.によるものである場合,\IT{id\_pbox}(Pseudo BOXのつもり).
+\itemitem 3.によるものであり,$p$が和文文字だった場合,\IT{id\_jglyph}.
+\itemitem 4.によるものであり,$p$が垂直変位がnon-zeroなhbox,
+あるいはvbox, ruleだった場合,\IT{id\_box\_like}.
+\itemitem それ以外の場合,node~$p$の種別を表す数値$p.\mibox{id}$そのもの.
+(数値そのものだと使い勝手が悪いので,\IT{id\_glyph}, \IT{id\_glue}, \IT{id\_kern}などと
+別名を定義している)
 \enditem
 
-\beginparagraph 和文文字とkernの間,kernと和文文字の間
-
-和文文字の後にkernが続いた場合,あるいはkernの後に和文文字が続いた場合,
-この間で行分割はできないものとしている.そのため,
-以下の3ケースに限られる:
-\enum $g$: kernのとき
-$$\ncount=0
-\node{q}
-\node{g}_{\rm J}
-\node{p}
-$$
-
-\enum $g$: glueのとき
-$$\ncount=0
-\node{q}
-\node{\np 10000}_{\rm K}
-\node{g}_{\rm J}
-\node{p}
-$$
-
-\enum $g=\emptyset$のとき
-$$\ncount=0
-\node{q}
-\node{p}
-$$
+\medskip\noindent{\bf 定義}\quad
+「\IT{Np}の中身の先頭」を意味する$\mibox{head}(\mibox{Np})$は,以下で定義される:
+
+\noindent{\small (説明の都合上作った記法で,Luaソース中にはこのような書き方はない)}
+
+\item \IT{Np.id}が\IT{id\_hlist}の場合:後に述べる{\tt check\_box}関数を用いて,
+hbox~\IT{Np.nuc}中の「最初のnode」「最後のnode」を求める.
+\item \IT{Np.id}が\IT{id\_pbox}の場合:\IT{id\_hlist}の場合とほぼ同様.
+\item $\mibox{Np}.\mibox{id}=\mibox{id\_glyph}$(欧文文字)の場合:
+\itemitem \IT{glyph\_node}~\IT{Np.nuc}が単一の文字を格納している(合字でない)場合は,\IT{Np.nuc}自身.
+\itemitem そうでない場合は,合字の構成要素の先頭→構成要素の先頭→……
+と再帰的に探索し,最後にたどり着いた\IT{glyph\_node}.
+\item $\mibox{Np}.\mibox{id}=\mibox{id\_disc}$ (discretionary break) の場合:
+\IT{disc\_node}は,
+\item $\mibox{Np}.\mibox{id}=\mibox{id\_jglyph}$(和文文字)の場合:\IT{Np.nuc}自身.
+\item $\mibox{Np}.\mibox{id}=\mibox{id\_math}$(数式境界)の場合:
+「文字コード$-1$の欧文文字」を仮想的に考え,それを$\mibox{head}(\mibox{Np})$とする.
+\item それ以外の場合:未定義.敢えて書けば$\mibox{head}(\mibox{Np}):=\emptyset$.
 \enditem
 
-なお,ここでの$g$は,
-\item $q$がkernだった場合は,
-$p$のJFMにおける,「|'jcharbdd'|と$p$」の間に
-入るglue/kernの値.
-\item $p$がkernだった場合は,
-$q$のJFMにおける,「$q$と|'jcharbdd'|」の間に
-入るglue/kernの値.
+\noindent 同様にして,「\IT{Np}の中身の先頭」を意味する$\mibox{last}(\mibox{Np})$も定義され,
+「\IT{Np}は,先頭が$\mibox{head}(\mibox{Np})$,
+末尾が$\mibox{tail}(\mibox{Np})$であるような単語」のように
+考えることができる.
+
+\medskip\noindent{\bf 定義}\quad
+「\IT{glyph\_node}~$h$の情報を算出する」とは,
+$h\neq\emptyset$の時に,テーブル\IT{Np}に
+以下のような要素を追加することである:
+
+\item \IT{.pre}: $h$の文字コードに対する{\sf prebreakpenalty}パラメタの値
+\item \IT{.post}: $h$の文字コードに対する{\sf postbreakpenalty}パラメタの値
+\item \IT{.xspc\_before}, \IT{.xspc\_after}: $h$の前後に|\xkanjiskip|が挿入可能であるかの
+指定値(パラメタ{\sf jaxspmode}, {\sf alxspmode}由来)
+\item \IT{.auto\_xspc}: $h$での{\sf autoxspacing}パラメタの値
 \enditem
 
-\beginparagraph 要検討の箇所
+$h$が和文文字を格納している場合は,さらに次の要素の追加作業も含む:
 
-私が推測するに,欧文では,
-\item 単語内ではフォントは変わらない;
-\item 単語内では,明示的に/ハイフネーションにより挿入されたdiscretionary break以外では
-行分割がおきない;
+\item \IT{.size}: $h$で使われている和文フォントのフォントサイズ.
+\item \IT{.met}, \IT{.var}: 使われているJFMの情報.
+\item \IT{.auto\_kspc}: {\sf autospacing}パラメタの値.
 \enditem
-という事情があるため,TFM由来のkernや合字処理は(nodeを生成しないもの以外は)
-何も透過しないという状態になっているものと思われます.
 
-そのため,JFMグルー等の仕様を考える場合,欧文でいう「単語」に対応するようなものは
-何か,というのを考える必要があります.現実装では,素直に欧文の合字処理と同様のものであると考え,
-透過するnodeはない,という仕様にしています.
-しかし,|\[x]kanjiskip|の処理と共通にしてしまうというのも
-考え方によってはありかもしれません.
+\beginparagraph 全体図
 
-\bigskip
-\item {\bf イタリック補正のkernの周囲}
+\enum 変数類の初期化
+\itemitem 処理対象が段落の中身(後で行分割される)の場合:$\mibox{mode}\leftarrow\top$
+\itemT \IT{lp}(node走査用カーソル)の初期位置は,
+リスト先頭部にある|\parindent|由来のhboxや
+local paragraph($\Omega$由来)等の情報を格納するwhatsit nodeたちが終わった所
+(つまり,段落本来の先頭部分)となる.
+\itemT \IT{last}(リスト末尾のnode)も,リストの最後部に挿入される|\parfillskip|由来のglue%
+を指す.
+\itemitem 
+処理対象がhboxの中身の場合:$\mibox{mode}\leftarrow\bot$
+\itemT \IT{lp}はリスト先頭.
+\itemT 番人として,リスト末尾にkernを挿入.\IT{last}はこのkernとなる.
 
-例えば,|jfm-ujis.lua|では,|'jcharbdd'|は文字クラス
-0であるため,今の実装では,\hfil\break
-「|)\/(|」という入力からは,次のnodeの並びを得る:
-\setbox1=\hbox{|\/|}%
-$$
-\vbox{\halign{$#$\hfil&$#$\hfil&$#$\hfil&$#$\hfil&$#$\hfil\cr
-\node{\hbox{)}}&\ncount=1
-\node{\np 10000}_{\rm K}&\ncount=1
-\node{\ng 0.5\z_{-0.5}}_{\rm J}\cr&\ncount=1
-\node{\nk \copy1}&\ncount=1
-\node{\np 10000}_{\rm K}&\ncount=1
-\node{\ng 0.5\z_{-0.5}}_{\rm J}&\ncount=1
-\node{\hbox{(}}\cr
-}}
-$$
-一方,イタリック補正をJFM由来グルーが透過するとしたならば,当然
-$$
-\node{\hbox{)}}
-\node{\nk \copy1}
-\node{\ng 0.5\z_{-0.5}}
-\node{\hbox{(}}
-$$
-となる(実際の組版イメージでは,
-「{\tenmini 斜め)}\hbox{}(」「{\tenmini 斜め)}(」).どちらにするか?
+\enum 先頭が\IT{lp}以降にある塊で,一番早いものを\IT{Np}にセットする.
+\itemitem 作業の途中で$\mibox{lp}=\mibox{last}$となったら,処理対象のリストに塊はないので,8.へ.
+\itemitem そうでなければ,$\mibox{head}(\mibox{Np})$の情報を算出しておく.
+\itemitem 本段階終了後,\IT{lp}は\IT{Np.last}の次のnodeとなる.
 
 
+\enum ({\tt handle\_list\_head}) 
+リストに最初に出てくる塊\IT{Np}が求まったので,リスト「先頭」とこの塊との間に和文処理グルーを挿入.
 
-\item {\bf penaltyの周囲}
+\enum 今の塊\IT{Np}と,その次の塊の間に入る和文処理グルーを求めるため,
+一旦$\mibox{Nq}\leftarrow \mibox{Np}$として待避させ,次の塊\IT{Np}を探索する.
+\itemitem 作業の途中で$\mibox{lp}=\mibox{last}$となったら,\IT{Nq}がリスト中最後の塊であるので,
+7.へ.
+\itemitem そうでなければ,$\mibox{head}(\mibox{Np})$の情報を算出しておく.
+\itemitem 本段階終了後,\IT{lp}は\IT{Np.last}の次のnodeとなる.
 
-これも,例えば次の設定の下では,「|)\penalty1701(|」からは以下を得る:
-\itemitem 「)」と行末の間に$-0.5\z$だけkernを入れる.
-\itemitem 「)」「(」の行頭/行末禁則用penaltyの値はどれも1000.
-$$
-\vbox{\halign{$#$\hfil&$#$\hfil&$#$\hfil&$#$\hfil&$#$\hfil\cr
-\node{\hbox{)}}&\ncount=1
-\node{\nk {-0.5}\z}_{\rm E}&\ncount=1
-\node{\np 1000}_{\rm K}&\ncount=1
-\node{\ng 1\z_{-0.5}}_{\rm J}\cr
-&\ncount=1\node{\np 1701}&\ncount=1
-\node{\np 1000}_{\rm K}&\ncount=1
-\node{\ng 0.5\z_{-0.5}}_{\rm J}&\ncount=1
-\node{\hbox{(}}\cr}}
-$$
-\leftskip2\zw
-例えばpenaltyを合算することとした場合,上の入力例では本来「)」「(」の間に
-1701のpenaltyがあるのだから,
-$$
-\vbox{\halign{$#$\hfil&$#$\hfil&$#$\hfil&$#$\hfil&$#$\hfil&$#$\hfil\cr
-\node{\hbox{)}}&\ncount=1
-\node{\nk {-0.5}\z}_{\rm E}&\ncount=1
-\node{\np 3701}_{\rm K}&\ncount=1
-\node{\ng 0.5\z_{-0.5}}_{\rm J}&\ncount=1
-\node{\hbox{(}}\cr
-\node{\hbox{)}}&\ncount=1
-\node{\nk {-0.5}\z}_{\rm E}&\ncount=1
-\node{\np 3701}_{\rm K}&\ncount=1
-\node{\ng 1\z_{-0.5}}_{\rm J}&\ncount=1
-\node{\ng 0.5\z_{-0.5}}_{\rm J}&\ncount=1
-\node{\hbox{(}}\cr
-}}
-$$
-のどちらか(上はpenaltyを透過する場合,下は透過しない場合)にするのが
-良いと思われます.
+\enum \IT{Nq}と\IT{Np}の間に和文処理グルーを挿入する.\IT{Np.id}による場合分けを行う.
+「main loop その\nobreak1,~2」を参照のこと.
 
+\enum \IT{Np}が単一の文字ではない{\small (合字など)}可能性がある以下の場合において,
+$\mibox{tail}(\mibox{Np})$の情報を算出する.終わったら,再びループに入るため,4.へ.
 
-\item {\bf discretionary breakの取り扱い}
 
-discretionary break (\IT{disc\_node})は,行分割時の行末の内容<pre>,
-行頭の内容<post>,それに行分割しないときの内容<no_break>の3つをリストの形で
-持っている.|linebreak.w|を見る限り,Lua\TeX でも<pre>, <post>, <no_break>の
-中身にはglueやpenaltyを許容していないようだ.
+\itemitem \IT{id\_glyph}(欧文文字)のとき
+\itemitem \IT{id\_disc} (discretionary break) のとき
+\itemitem \IT{id\_hlist}のとき
+\itemitem \IT{id\_pbox}のとき
 
-現行の実装では,<pre>, <post>, <no_break>のどれも,和文フォントへの置換の
-段階からして行われていない(だから中身は全部欧文扱いとなる).
-{\small 単純にサボっていました|^^;|}
-<pre>, <post>, <no_break>の中身にglueやpenaltyが許容されないことから,
-これらに対する和文用処理の方法として,次の2種類が挙げられる.
-私は前者で良いのではないかと思っているのだが…….
-\itemitem (現行のまま)discretionary breakの中身に和文文字はないものと想定する.
-例えば<pre>の中身に和文文字を入れたい場合は,<pre>の中身全体を
-必ずhboxで括ることとする.
-\itemitem 「glueを挿入」を全部「自然長だけを取り出したkernを挿入」に置き換え,
-普段の和文処理グルー挿入処理を流用する.
+\enum ({\tt handle\_list\_tail}) 
+リストの最後にある塊\IT{Nq}が求まったので,この塊とリスト「末尾」の間に和文処理グルーを挿入.
 
-
-\item {\bf 数式の取り扱い}
-
-まだ数式中に和文文字が(hboxでカプセル化されることなく)出現することは想定していない.
-実用的にはそれでも十分だと思うが,もしp\TeX のように単に
-\begintt
-$aあa$
-\endtt
-などと書いても和文文字が
-出力されるようにするとなれば,「数式リストから変換されてできた水平リストでは,
-和文処理グルーの挿入処理を無効とする」ようにしないといけないだろう.
+\enum $\mibox{mode}=\bot$の場合,番人となるkernを1.において挿入したので,その番人を削除する.
 
 \enditem
 
-\beginsection {\tt \char"5C[x]kanjiskip}の挿入%"
-
-現実装の|\[x]kanjiskip|の挿入の方針として,
-\item JFMグルーが挿入されていないところに「標準の空き量」として挿入する.
-\item 実際の段落/hboxの内容に即して,組版イメージの見た目に関係のないところは透過する.
-\enditem
+\beginsection リスト先頭・末尾の処理と「boxの内容」
 
-\beginparagraph 処理の概要
+\beginparagraph リスト先頭の処理 ({\tt handle\_list\_head})
 
-|\[x]kanjiskip|挿入処理では,次の3つのnodeを用いている.
-$$\ncount=0
-\node{\IT{nr}}\longrightarrow\cdots
-\node{\IT{nq}}\longrightarrow\cdots
-\node{\IT{np}}
-$$
-\item \IT{nr}と\IT{np}の間に|\[x]kanjiskip|を挿入しようとする.
-\item 実際にnodeの形で挿入しようとする場所は$\it nq$の直後である.
-\item \IT{nr}, \IT{nq}は異なるnodeとは限らない.
-\item {\bf \IT{np}はリストの先頭から末尾までループで渡る.}その過程で
-\IT{nr}, \IT{nq}を適宜更新し,実際のnode挿入処理を行っている.
-\item 厳密には,コード中では\IT{nr}という変数は使っていない.代わりに使われているのは,
-\itemitem $\mibox{insert\_skip}\in \{\mibox{no\_skip}, 
-  \mibox{after\_schar}, \mibox{after\_wchar}\}$: 
-「node \IT{nr}」の種類を表す:
-\itemT \IT{no\_skip}: 「node \IT{nr}」の後ろ(\IT{nr}と\IT{np}の間)に
-|\[x]kanjiskip|が入ることはない.
-\itemT \IT{after\_schar}: 「node \IT{nr}」を,欧文文字(の入った\IT{glyph\_node})であり,
-かつ{\sf alxspmode}パラメータの指定により「\IT{nr}の後ろに|\xkanjiskip|の挿入を許可する」ようなものとみなす.
-\itemT \IT{after\_wchar}: 「node \IT{nr}」を和文文字(の入った\IT{glyph\_node})とみなす.
-\itemitem \IT{nrc}: 「node \IT{nr}の文字コード」を表す.
-\itemitem \IT{nrf\/}: 「\IT{nr}のフォント」を表す.
-\itemitem $\mibox{nr\_spc}[1]$: 「node \IT{nr}」における
-{\sf autospacing}(|\kanjiskip|の自動挿入を行うか否か)の設定値.
-\itemitem $\mibox{nr\_spc}[2]$: 「node \IT{nr}」における
-{\sf autoxspacing}(|\xkanjiskip|の自動挿入を行うか否か)の設定値.
-
-\medskip\leftskip=2\zw\noindent
-\IT{nrc}, \IT{nrf}の値は,$\mibox{insert\_skip}=\mibox{after\_wchar}$のときのみ用いられる.
-$\mibox{insert\_skip}=\mibox{no\_skip}$のときには,それだけで情報は十分であるから,
-\IT{nr\_spc}, \IT{nq}の値も用いられない.
+次の場合に,
+\IT{Np}で使われているのと同じJFMを使った「文字コードが{\tt 'boxbdd'}の文字」と
+\IT{Np}との間に入るglue/kernを,\IT{Np.first}の直前に挿入する:
+\item $\mibox{Np.id}=\mibox{id\_jglyph}$(和文文字)
+\item $\mibox{Np.id}=\mibox{id\_pbox}$であり,$\mibox{head}(\mibox{Np})$が和文文字であるとき.
 \enditem
-
-ループの中で,以下の場合には\IT{nr}は変化せず,$\IT{nq}\leftarrow \IT{np}$となる.
-つまり,これらのnodeに対して|\[x]kanjiskip|は透過する:
-\item \IT{np}がpenaltyの場合
-\item \IT{np}が$\hbox{\tt subtype}=0$のkern(TFM由来)の場合.
-\item \IT{np}が$\hbox{\tt subtype}=1$のkern(つまり,明示的kernかイタリック補正由来)であって,jtypeが
 $$
-\hbox{I (イタリック補正),E(行末との間),T(一時的)}
+\vcenter{\halign{$\mibox{mode}=#$:\qquad\hfil&$#$\hfil\cr
+\bot&\node{\kern-1em}\,\hbox{(リスト先頭)}\longrightarrow\cdots\node{g}_{15}
+\node{\mibox{Np}}\cr
+\top&\node{\hbox{{\tt\char92 parindent}由来hbox}}\longrightarrow\cdots
+\Bigl[\node{\np 10000}_{15}\Bigr]\node{g}_{15}\node{\mibox{Np}}\cr
+}}
 $$
-であった場合.後者2つはJFMグルーの挿入で入るものなので,
-ユーザは「イタリック補正は透過」と考えればよい.
-
-\item \IT{np}がinsertion, mark, |\vadjust|, whatsitのnodeである場合.
-これらは水平リストからは消え去る運命にある.
-\enditem
+ここで,$g$がglueかつ$\mibox{mode}=\top$かつ$\#\mibox{Bp}=0$のときのみ,|\parindent|由来のhboxの直後で改行されることを防ぐために
+$g$の直前にpenaltyを挿入する.{\small 
+($\#\mibox{Bp}$が1以上の場合は,|\parindent|と\IT{Np}の間にある
+penaltyのため,\IT{Np}の直前での改行が起こり得る状態となっているので,
+特にそれを抑制することもしない)\inhibitglue}.
 
 
-\beginparagraph \IT{np}が文字 (\IT{glyph\_node}) の場合
-
-この場合がやはり一番基本となる.
-\enum $\mibox{insert\_skip}=\mibox{after\_schar}$, \IT{np}: 和文文字の場合
-
-前に書いたように,「node \IT{nr}」は(直後に|\xkanjiskip|の挿入が許可されている)欧文文字と
-みなされている.
-そのため,「node \IT{nr}」と\IT{np}の間に|\xkanjiskip|の入る条件は以下である.
-\itemitem 文字\IT{np}に対する{\sf jaxspmode}パラメータの指定において
-「直前への|\xkanjiskip|の挿入が許可」されている.
-\itemitem 「node \IT{nr}における」{\sf autoxspacing}パラメタの値 ($\mibox{nr\_spc}[2]$) か,
-\IT{np}における{\sf autoxspacing}の値の少なくとも一方が真である.
-
-\medskip\leftskip=2\zw\noindent
-まず,実際に入る|\xkanjiskip|の量$g$を次の方法で決定する:
-\itemitem {\sf xkanjiskip}パラメータの自然長が|\maxdimen|でない場合,
-{\sf xkanjiskip}パラメータの値をそのまま採用する.
-\itemitem {\sf xkanjiskip}パラメータの自然長が|\maxdimen|の場合は,
-\IT{np}で使われているJFMに設定されている|\xkanjiskip|の量を用いる.
-\itemitem 上の2つのどれでもない場合,fallbackとして0を用いる.
-
-{\bf 要検討}:既にJFMグルー挿入処理で和欧文間の行分割は可能としているので
-0を挿入する意味はない?
-
-\medskip\leftskip=2\zw\noindent
-次にこのようにして決定された$g$を実際に挿入する:
-\itemitem ほとんどの場合,$g$の値をもつglueを\IT{nq}の直後に挿入する.
-$$\ncount=0
-\node{\mibox{nr}}\longrightarrow\cdots
-\node{\mibox{nq}}\node{\ng g}_{\rm XS}\longrightarrow\cdots
-\node{\mibox{np}}
-$$
-\itemitem \IT{np}の直前が${\rm jtype}={\rm T}$なnodeの場合,そのnodeに
-$g$の分だけ自然長/伸び/縮み量を加算する.
-$$\ncount=0
-\vbox{\halign{$#$\hfil\cr
-\node{\mibox{nr}}\longrightarrow\cdots
-\node{\mibox{nq}}\longrightarrow\cdots
-\node{\ng h}_{\rm T}
-\node{\mibox{np}}\cr
-\hfil\Downarrow\cr
-\vadjust{\bigskip}
-\node{\mibox{nr}}\longrightarrow\cdots
-\node{\mibox{nq}}\longrightarrow\cdots
-\node{\ng g+h}_{\rm XS}
-\node{\mibox{np}}\cr
-\node{\mibox{nr}}\longrightarrow\cdots
-\node{\mibox{nq}}\longrightarrow\cdots
-\node{\nk k}_{\rm T}
-\node{\mibox{np}}\cr
-\hfil\Downarrow\cr
-\node{\mibox{nr}}\longrightarrow\cdots
-\node{\mibox{nq}}\longrightarrow\cdots
-\node{\ng g+k}_{\rm XS}
-\node{\mibox{np}}\cr
-}}
-$$
+\beginparagraph リスト末尾の処理 ({\tt handle\_list\_tail})
 
-\medskip\leftskip=2\zw\noindent
-最後に,次のループに移るために,次の処理を行う:
-\itemitem 
-$\mibox{nq}\leftarrow \mibox{np}$, 
-$\mibox{nr\_spcの設定}$, 
-$\mibox{nrf}\leftarrow \mibox{np}.\mibox{font}$, 
-$\mibox{nrc}\leftarrow \mibox{np}.\mibox{char}$
-\itemitem $\mibox{np}\leftarrow \mibox{next\/}(\mibox{np})$
-\itemitem $\mibox{insert\_skip}\leftarrow \mibox{after\_wchar}$
-
-\enum $\mibox{insert\_skip}=\mibox{after\_wchar}$, \IT{np}: 欧文文字の場合
-
-前に書いたように,「node \IT{nr}」は和文文字とみなされている.
-そのため,「node \IT{nr}」と\IT{np}の間に|\xkanjiskip|の挿入が起こるための条件は
-次の3条件が満たされていることである:
-\itemitem \IT{nrc}番の和文文字に対する{\sf jaxspmode}パラメータの設定で,
-「直後への|\xkanjiskip|挿入」が許可されている.
-\itemitem \IT{np}の文字{\small(もし\IT{np}が合字であれば,合字の構成要素の最初の文字)}%
-に対する{\sf alxspmode}パラメータの設定で,
-「直前への|\xkanjiskip|挿入」が許可されている.
-\itemitem \IT{nr}における{\sf autoxspacing}パラメタの値 ($\mibox{nr\_spc}[2]$) か,
-「node \IT{nr}」における{\sf autoxspacing}の値の少なくとも一方が真である.
-
-\medskip\leftskip=2\zw\noindent
-この後,実際に|\xkanjiskip|の量を計算し,nodeの形で実際に挿入するところは,
-量の決定のところで\IT{np}の代わりに\IT{nrf}を用いる以外は同じである.
-最後の,次のループに移るための処理では,次が行われる.
-\itemitem 
-$\mibox{nq}\leftarrow \mibox{np}$, 
-$\mibox{nrc}\leftarrow \mibox{np}.\mibox{char}$, 
-$\mibox{nr\_spcの設定}$
-\itemitem $\mibox{np}\leftarrow \mibox{next\/}(\mibox{np})$
-\itemitem \IT{insert\_skip}の設定.
-
-$\mibox{insert\_skip}\leftarrow \mibox{after\_schar}$となるのは,
-\IT{np}の文字{\small(もし\IT{np}が合字であれば,合字の構成要素の末尾の文字)}%
-における{\sf alxspmode}パラメータの設定で,
-「直後への|\xkanjiskip|挿入」が許可されている場合である.
-そうでないときは,$\mibox{insert\_skip}\leftarrow \mibox{no\_skip}$となる.
-
-\enum $\mibox{insert\_skip}=\mibox{after\_wchar}$, \IT{np}: 和文文字の場合
-
-この場合は|\xkanjiskip|の代わりに|\kanjiskip|を挿入することとなる.
-{\sf jaxspmode}, {\sf alxspmode}のように「直前/直後への|\kanjiskip|挿入許可の制御」
-を行うパラメータは存在しない.「{\sf autospacing}で自動挿入が禁止される」とマニュアルでは言っているが,
-それは{\bf 挿入する|\kanjiskip|の量を一時的に0にしているだけで,
-「node \IT{nr}」と\IT{np}の間には
-常に|\kanjiskip|が入ることには変わりはない}ことに注意.
+この場合,\IT{mode}の値により処理が全く異なる.
 
-\medskip
-実際に入る|\kanjiskip|の量$g$は次の方法で決定される:
-\itemitem \IT{nr}における{\sf autospacing}の値 ($\mibox{nr\_spc}[1]$) か,
-\IT{np}における{\sf autospacing}の値が共に偽なら,$g=0$.
-\itemitem {\sf kanjiskip}パラメータの自然長が|\maxdimen|でない場合,
-{\sf kanjiskip}パラメータの値をそのまま採用する.
-\itemitem {\sf xkanjiskip}パラメータの自然長が|\maxdimen|の場合は,
-\IT{np}で使われているJFMに設定されている|\kanjiskip|の量を用いる:
-\itemT 「node \IT{nr}」で使用されているJFMと,\IT{np}で使用されているJFMそれぞれに
-|\kanjiskip|の値が設定されている場合,…….
-
-\itemitem 上の3つのどれでもない場合,fallbackとして0を用いる.
+\noindent{\bf A: \IT{mode}が偽である場合.}
 
+この場合はリストはhboxの中身だから,行分割はおこり得ない.
+リスト先頭の処理と同様に,
+次の場合に
+\IT{Nq}と「文字コードが{\tt 'boxbdd'}の文字」と
+の間に入るglue/kernを,\IT{Nq.last}の直後に挿入する:
+\item $\mibox{Nq.id}=\mibox{id\_jglyph}$(和文文字)
+\item $\mibox{Nq.id}=\mibox{id\_pbox}$であり,$\mibox{tail}(\mibox{Nq})$が和文文字であるとき.
 \enditem
+$$
+\node{\mibox{Nq}}\node{g}_{15}\longrightarrow\cdots\node{\nk\hbox{(番人)}}
+$$
+上の番人は,次のstepで除去されるのだった.
 
 \medskip
-$g$を実際に挿入するところは,今の場合も1.の場合と変わらない.
-次のループに移るために\IT{nq}等の設定処理も,1.と同じである.
+\noindent{\bf B: \IT{mode}が真である場合.}
 
-\beginparagraph \IT{np}がhboxの場合
+この場合,段落の末尾には常に|\penalty 10000|と|\parfillskip|由来のグルーが存在する.
+そのため,上のように「文字コードが{\tt 'boxbdd'}の文字」との空白を考えるのではなく,
+まず,\IT{Nq}が行末にきたときに行末との間に入る空白$w$を代わりに挿入する.
+\item $\mibox{Nq.id}=\mibox{id\_jglyph}$(和文文字)
+\item $\mibox{Nq.id}=\mibox{id\_pbox}$であり,$\mibox{tail}(\mibox{Nq})$が和文文字であるとき.
+\enditem
+$$
+\node{\mibox{Nq}}\node{\nk w}_{15}\node{\np10000}\longrightarrow\cdots
+\node{\ng (\hbox{\tt\char92 parfillskip})}
+$$
+次に,|\jcharwidowpenalty|の挿入処理を行う→省略.
 
-|\[x]kanjiskip|は,垂直変位が0である(即ち,|\raise|, |\lower|により上下に移動されていない)
-hboxの境界を跨ぐ.
+\beginparagraph box内の「最初/最後の文字」の検索 ({\tt check\_box})
 
-\enum hbox内の「最初のnode」\IT{first\_char}と「最後のnode」\IT{last\_char}を探索する.
-この探索は,次を透過する:
-\itemitem 垂直変位が0であるhboxの境界(但し,空hboxは透過しない).
-\itemitem insertion, mark, |\vadjust|, whatsit, penalty用のnode.
-\itemitem 「最初のnode」「最後のnode」それぞれにいえることだが,文字 (\IT{glyph\_node}) でない場合は
-\IT{first\_char},~\IT{last\_char}はそれぞれ$\emptyset$となる.
+「hboxの中の文字と外の文字の間に」|\kanjiskip|, |\xkanjiskip|の挿入を行えるようにするため,
+{\tt check\_box}関数ではhbox内の「最初のnode」「最後のnode」の検索を行う.
 
-\medskip\leftskip=2\zw\noindent
-前者の具体例として,例えば,次の入力を考える.
-\begintt
-あ\hbox{a}い\hbox{\hbox{}b\hbox{}}う\hbox{}cえ\hbox{\hbox{d}}お
-\endtt
-すると,
-$$
-\vbox{\halign{#の間のhbox\hfil\quad $\longrightarrow$\quad
-&$\mibox{first\_char}=\hbox{#}$,\ \hfil
-&$\mibox{last\_char}=\hbox{#}$\hfil\cr
-1.\ 「あ」「い」&「a」&「a」\cr
-2.\ 「い」「う」&$\emptyset$&$\emptyset$\cr
-3.\ 「う」「c」&$\emptyset$&$\emptyset$\cr
-4.\ 「え」「お」&「d」&「d」\cr
-}}
-$$%$
-となる.
-
-\enum \IT{np}の前に|\[x]kanjiskip|を挿入するか否か,あるいは実際に挿入する量の決定は,
-\IT{first\_char}に対しての処理をそのまま適用する.つまり,上の例では
-\itemitem 「あ」と「a」の間に|\xkanjiskip|が挿入されることから,「あ」とhbox 1.の間には|\xkanjiskip|が挿入される.
-\itemitem 「い」とhbox 2.の間には|\xkanjiskip|が挿入されない.
-
-\enum 同様に,\IT{np}の後ろに|\[x]kanjiskip|を挿入するか否かは,
-文字\IT{last\_char}の後ろに対してどうなるかの値を用いる.上の例では,
-\itemitem 「a」と「い」の間に|\xkanjiskip|が挿入されることから,hbox 1.と「い」の間には|\xkanjiskip|が挿入される.
-\itemitem hbox 2.と「う」の間には|\xkanjiskip|が挿入されない.
-\medskip\leftskip=2\zw\noindent
-次のループに進むための設定も,node~\IT{last\_char}における値をもとに行う.
+\item 以下のnodeは検索から除外される:
+\itemitem 組版結果からは消えてしまう,\IT{ins\_node}, 
+\IT{mark\_node}, \IT{adjust\_node}, \IT{whatsit\_node}, penalty.
+\itemitem (box中身の先頭/末尾に入っている)icflagが7のglue/kern/penalty.
+\itemitem アクセント部とイタリック補正.
+\item \IT{hlist\_node}~$q$に出会ったら,$q$の垂直変位量が0である限り,検索は$q$の内部も進む.以下同文.
+\item 検索して得られた「最初のnode」「最後のnode」がそれぞれ\IT{glyph\_node}でなければ,
+実際には$\emptyset$を返す.
 \enditem
 
-以上より,項目1.で与えられた入力では,次の出力が得られる:
-$$
-\hbox{あ\hbox{a}い\hbox{\hbox{}b\hbox{}}う\hbox{}cえ\hbox{\hbox{d}}お}
-$$
-{\bf 要検討:}空のhboxは跨がないようにしているのは,次の2つを使い分けられるようにするため:
-\item JFMグルー挿入の抑止:|\inhibitglue|
-\item 全ての和文処理グルー挿入の抑止:
-|\inhibitglue\hbox{}\inhibitglue|
+\vfill\eject
+\beginsection main loop
+
+\beginparagraph 一覧表
+
+\IT{Nq}, \IT{Np}の種類別に挿入されるglue/kernの種別を表にすると次のようになる.
+
+\def\;{\hskip0.25em}\ltjsetparameter{jacharrange={+1}}
+\def\gkf#1#2#3#4#5{$\vcenter{\small\rm\halign{\hbox to 1em{\hss##\hss}\;\vrule&%
+\hbox to 3em{\hss##\hss}&\vrule\;\hbox to 1em{\hss##\hss}\cr
+#1\mathstrut&\omit\hfil #2\span\omit\cr\noalign{\hrule}#3&#4\strut&#5\cr}}$}
+\setbox1=\hbox{\gkf{E}{M→K}{○}{nor}{○}}
+\setbox2=\hbox to 0.4pt{\vrule height\dimexpr \ht1+0.5em\relax depth \dimexpr \dp1\relax}
+$$\def\:{\hskip0.5em}\lineskiplimit=\maxdimen\lineskip=0pt
+\vcenter{\halign{\hfil#\hfil\hskip1em\copy2%
+\:&\:\hfil#\hfil\:&\:\hfil#\hfil\:&\:\hfil#\hfil\:&\:\hfil#\hfil%
+\:&\:\hfil#\hfil\:&\:\hfil#\hfil\:&\:\hfil#\hfil\:&\:\hfil#\hfil\cr
+\raise0.5em\hbox{$\vcenter{\hbox{\IT{Nq}→}\smallskip\hbox{\IT{Np}↓}}$}%
+&和文1&和文2&欧文&箱&id\_glue&id\_kern\cr
+\noalign{\hrule}
+和文1&
+\gkf{E}{M→K}{○}{nor}{○}&
+\gkf{}{$\rm O_A$→K}{×}{nor}{○}&
+\gkf{}{$\rm O_A$→X}{○}{nor}{○}&
+\gkf{}{$\rm O_A$}{---}{all}{○}&
+\gkf{}{$\rm O_A$}{---}{nor}{○}&
+\gkf{}{$\rm O_A$}{---}{sup}{○}\cr
+和文2&
+\gkf{E}{$\rm O_B$→K}{○}{nor}{×}&
+\gkf{}{K}{×}{sup}{×}&
+\gkf{}{X}{○}{sup}{×}\cr
+欧文&
+\gkf{E}{$\rm O_B$→X}{○}{nor}{○}&
+\gkf{}{X}{○}{sup}{×}\cr
+箱&\gkf{E}{$\rm O_B$}{○}{alw}{---}\cr
+\IT{id\_glue}&\gkf{E}{$\rm O_B$}{○}{nor}{---}\cr
+\IT{id\_kern}&\gkf{E}{$\rm O_B$}{○}{sup}{---}\cr
+}}$$
+
+\item {\bf 項目名}\quad 表1行目の\IT{Nq}の種類について説明する.\IT{Np}についても同様.
+\itemitem 「和文1」:リスト中に直接出現している和文文字.
+\itemT $\mibox{Nq.id}=\mibox{id\_jglyph}$であったとき.
+\itemT $\mibox{Nq.id}=\mibox{id\_pbox}$かつ$\mibox{last}(\mibox{Nq})$が和文文字であったとき.
+\itemitem 「和文2」:リスト内にあるhboxの中身として出現した和文文字.すなわち,
+$\mibox{Nq.id}=\mibox{id\_hlist}$かつ
+$\mibox{last}(\mibox{Nq})$が和文文字であったとき.
+\itemitem 「欧文」:$\mibox{last}(\mibox{Nq})$が欧文文字であったとき.即ち,
+\itemT リスト中に直接出現しているとき($\mibox{Nq.id}=\mibox{id\_jglyph}$ or~%
+$\mibox{Nq.id}=\mibox{id\_pbox}$かつ$\mibox{last}(\mibox{Nq})$が欧文文字).
+\itemT $\mibox{Nq.id}=\mibox{id\_hlist}$かつ
+$\mibox{last}(\mibox{Nq})$が欧文文字であったとき.
+\itemT $\mibox{Nq.id}=\mibox{id\_math}$であったとき.
+\itemitem 「箱」:前後に和文処理グルーが挿入されない用なbox状のnode.
+\itemT $\mibox{Nq.id}=\mibox{id\_list}$かつ
+$\mibox{last}(\mibox{Nq})$が文字でなかった(未定義)だったとき.
+\itemT $\mibox{Nq.id}=\mibox{id\_box\_like}$のとき.
+\itemitem 「\IT{id\_glue}」:そのまま,$\mibox{Nq.id}=\mibox{id\_glue}$であったとき.
+\itemitem 「\IT{id\_kern}」:そのまま,$\mibox{Nq.id}=\mibox{id\_kern}$であったとき.
+
+\item 表中の各セルは,それぞれ次のような内容を表している:
+$$\vcenter{\rm\halign{\hbox to 3em{\hss#\hss}\;\vrule&%
+\hbox to 3.5em{\hss#\hss}&\vrule\;\hbox to 3em{\hss#\hss}\cr
+左空白\mathstrut&\omit\hfil 右空白\span\omit\cr\noalign{\hrule}L&P取扱\strut&R\cr}}$$
+
+\itemitem 「左空白」:\IT{Nq}の直後に挿入される空白の種類.空欄は,何も入らないことを表す.
+\itemitem 「右空白」:\IT{Np}の直前に挿入される空白の種類.
+
+なお,「A→B」は,まずAの種類のglue/kernを調べ,それが未定義ならば,
+Bの種類のglue/kernを採用することを示している.このとき,矢印の右側に入る空白%
+(K, X)はいつでも定義されていることに注意.
+
+\itemitem 「P取扱」:\IT{Nq}と\IT{Np}の間に入る禁則用ペナルティの取扱の方法を表す.
+\IT{Nq}と\IT{Np}の間で常に行分割を許すかに伴い,
+{\bf nor}mal, {\bf alw}ays, {\bf sup}pressの3種類がある.
+\itemitem 「L」「R」:禁則用ペナルティの挿入処理において,
+\IT{Nq.post}~(L)や\IT{Np.pre}~(R)の値を実際に活用するかどうかを示す.値は次の3種類:
+$$
+\hbox{○(利用する),×(利用せず,0として扱う),---(未定義のため0扱い)}$$
 \enditem
 
-なお,\IT{np}の垂直変位が0でない場合は,\IT{np}の前後への|\[x]kanjiskip|の挿入は行われない
-(即ち,$\mibox{insert\_skip}\leftarrow\mibox{no\_skip}$となる).
 
+\beginparagraph 挿入されるglue/kernの種類
 
-\beginparagraph \IT{np}がkernの場合
+前節の表にある空白の種類についての解説を行う.
 
-前に書いたように,|subtype|が0のkern(TFM由来)や,|subtype|が1であってもjtypeがI, E,~Tのkernは
-挿入処理を透過してしまうので,今問題にしているのはそうでない場合である.
+\item E: \IT{Nq}が行末にきたとき,
+\IT{Nq}と行末の間に入る空白 (kern).挿入位置は\IT{Nq.last}の直後.
+\itemitem JFMでは「文字コード|'lineend'|の文字」との間に入るkern量として設定できる.
+\itemitem 右空白がkernであるときは挿入されない.
+\itemitem この種類のkernが挿入される時,右空白は自然長がEの分だけ引かれる.
 
-\item $\hbox{\tt subtype}=1$の場合.
 
-挿入処理で透過されないのは
-jtypeがない(明示的kern)か,jtypeがJ(JFM由来グルー)という2つの場合であるが,
-いずれの場合も,\IT{np}の周囲には|\[x]kanjiskip|の挿入は行われない.そのため,次ループのために
-行われる処理は,$\mibox{insert\_skip}\leftarrow\mibox{no\_skip}$, 
-$\mibox{np}\leftarrow\mibox{next}(\mibox{np})$だけである.
-
-\item $\hbox{\tt subtype}=2$(|\accent|由来)の場合.
-
-\IT{np}はリストの先頭から走査されていることから,\IT{np}に続くnodeの並びは
-$$\ncount=0
-\node{\mibox{np}=\nk\!\!}
-\node{\hbox{アクセント文字}}
-\node{\nk\!\!}
-\node{\hbox{アクセントのつく文字}}
+\item M: \IT{Nq}と\IT{Np}の間に入るJFM由来のglue/kern.
+\itemitem \IT{Nq}, \IT{Np}の間で|\inhibitglue|を発行した場合,挿入は抑止される.
+\itemitem 両方の塊で使われているJFMが(サイズもこめて)等しい場合は,両者で使われている
+JFMの情報をそのまま利用できるので,量の決定は容易い.
+\itemitem そうでなければ,まず
 $$
-となっている.p\TeX-3.2と同様に,Lua\TeX-jaでは|\[x]kanjiskip|挿入処理で
-アクセント文字は無視することにしている.そのため,
-\IT{nq}は変化せず,次回のループで処理対象となる\IT{np}は
-$\mibox{np}\leftarrow 
-\mibox{next\/}(\mibox{next\/}(\mibox{next\/}(\mibox{np})))$となる.
+\vcenter{\halign{\hfil$#:={}$&(\inhibitglue#\inhibitglue)\cr
+gb&\IT{Nq}と「文字コードが|'diffmet'|の文字」との間に入るglue/kern\cr
+ga&「文字コードが|'diffmet'|の文字」と\IT{Np}との間に入るglue/kern\cr
+}}
+$$
+として2つの量を計算.少なくとも片方が未定義の場合は,もう片方の値を用いる.
+そうでなければ,両者の値から自然長,伸び量,縮み量ごとに計算
+(方法として,平均,和,大きい方,小さい方)を行い,それによって得られたglue/kernを採用する.
+\item K: |\kanjiskip|を表すglueを挿入($\emptyset$にはならない).
+\itemitem 両方の塊において「|\kanjiskip|の自動挿入が無効」
+ ($\mibox{Nq.auto\_kspc}\vee \mibox{Np.auto\_kspc}=\bot$) ならば,長さ0のglueを挿入する.
+\itemitem {\sf kanjiskip}パラメタの自然長が$\hbox{\tt\char92maxdimen}=(2^{30}-1)\,{\rm sp}$で
+あれば,
+JFMに指定されている|\kanjiskip|の量を用いる.\IT{Nq}, \IT{Np}で使われているJFMが異なった時の処理は,
+Mの場合と同じである.
+\itemitem 上のどれにも当てはまらなければ,{\sf kanjiskip}パラメタで表される量のglueを挿入する.
+\item X: |\xkanjiskip|を表すglueを挿入($\emptyset$にはならない).
+\itemitem 次のいずれかの場合には,|\xkanjiskip|は長さ0のglueとなる:
+\itemT  両方の塊において,「|\xkanjiskip|の自動挿入が無効」という指定
+($\mibox{Nq}.\mibox{auto\_xspc}\vee \mibox{Np}.\mibox{auto\_xspc}=\bot$)
+がされていた場合.
+\itemT \IT{Nq}内の文字について「直後への|\xkanjiskip|挿入が無効」であった場合,即ち
+$\hbox{\sf alxspmode}\ge 2$(欧文)か$\hbox{\sf jaxspmode}\equiv0\pmod2$(和文).
+\itemT \IT{Np}内の文字について「直前への|\xkanjiskip|挿入が無効」であった場合,即ち
+$\hbox{\sf alxspmode}\equiv0\pmod2$(欧文)か$\hbox{\sf jaxspmode}\ge2$(和文).
+\itemitem {\sf xkanjiskip}パラメタの自然長が|\maxdimen|であれば,
+$\mibox{last}(\mibox{Nq})$, $\mibox{head}(\mibox{Np})$の片方が和文文字であるので,
+そこで使われているJFMで指定されている|\xkanjiskip|の量を用いる
+(JFMで指定されていなければ長さ0のglueと見なされる).
+\itemitem 上のどれにも当てはまらなければ,{\sf xkanjiskip}パラメタで表される量のglueを挿入する.
+\item $\rm O_B$: \IT{Nq}と「文字コードが|'jcharbdd'|の文字」との間に入るglue.
+Mのバリエーションと考えればよく,同じように|\inhibitglue|の指定で抑止される.
+\item $\rm O_A$: 「文字コードが|'jcharbdd'|の文字」と\IT{Np}との間に入るglue.
+Mのバリエーションと考えればよく,同じように|\inhibitglue|の指定で抑止される.
 \enditem
 
-\beginparagraph \IT{np}が数式境界 (\IT{math\_node})の場合
-
-数式境界は,便宜的に「文字コードが$-1$である文字」とみなして内部で処理している.
 
-\beginparagraph その他の場合
+\beginparagraph penaltyまわりの処理
 
-以上に出てきていないnode(vbox, rule, discretionary break, glue, margin\_kern)の
-周囲には|\[x]kanjiskip|の挿入は行われない.
-
-\beginsection JFM由来グルーとの関係の例
+隣り合った塊\IT{Nq}, \IT{Np}の間には,集合\IT{Bp}で表される0個以上のpenaltyがあるのだった:
+$$
+\node{\mibox{Nq}}
+\Bigl[\node{\hbox{E}}_4\Bigr]
+\longrightarrow\cdots 
+\hbox{(penaltyある可能性あり)}\cdots
+\Bigl[\node{\hbox{M, K, X他}}_{3,\,5,\,6}\Bigr]
+\node{\mibox{Np}}
+$$
+禁則処理に関係するpenaltyの挿入処理は,以下に述べるところ部分は共通の動作である.
 
-最後に,今まで説明した,JFM由来グルーと|\[x]kanjiskip|の処理によって,実際にどのようにnodeの
-並びが変わるかをいくつかの例で示す.上付きで$*$がついているnodeは,値が0だと挿入されないことを示す.
+\medskip 
+$\#\mibox{Bp}\ge 1$の場合には,{\bf 全ての}\IT{Bp}の元$p$~(penalty)に対して次を行う:
+$$p.\mibox{penalty}\mathrel{+}=a,\qquad a:=\mibox{Nq.post}+\mibox{Np.pre}.$$
+\item
+全ての\IT{Bp}の元に対して行うのは,
+実際にはどのpenaltyの位置で行分割が行われるかがわからないからである.
+\item 数ページ前の表で,左下が「×」 or 「---」となっていた場合は,上の計算式において
+\IT{Nq.post}は0と扱われる.右下が「×」 or 「---」なら,\IT{Np.pre}が0と扱われる.
+\item penalty値の計算では,$+10000$は正の無限大,$-10000$は負の無限大として扱っている.
+そのため,$a$の計算や$p.\mibox{penalty}$への加算代入のところでは,
+通常の加減算で絶対値が10000を越えたら分はカットし,さらに$(10000)+(-10000)=0$としている.
+\enditem
 
+$\#\mibox{Bp}=0$の場合が,penalty挿入の3種類の方法「normal」「always」「suppress」で
+異なる部分である:
 
-\item {\bf 例1: 2つの連続する和文文字の間}
-\setbox1=\hbox{|\kanjiskip|}
-$$\ncount=0
-\vbox{\halign{$#$\hfil\cr
-\node{\hbox{和文文字}}\node{\hbox{和文文字}}
-\cr
-\hfil\Downarrow\cr
-\vadjust{\bigskip}
-\node{\hbox{和文文字}}
-\node{\nk w}_{\rm E}^*
-\node{\np P}^*\longrightarrow
-\left\{\vcenter{%
-\halign{$#$\hfil\cr
-\ncount=0\node{{\rm glue/kern}\ g+w}_{\rm J}\cr
-\ncount=0\node{\copy1+w}_{\rm KS}\cr
-}}\right\}
-\node{\hbox{和文文字}}\cr
-}}
+\item {\bf「normal」の場合:}
+次の場合に,$p.\mibox{penalty}=a$であるpenalty~$p$を作成し,
+それを(M, K他のglue挿入前に)\IT{Np.first}の直前に挿入する:
 $$
-
-\item {\bf 例2: 和文文字と欧文文字の間}
-\setbox1=\hbox{|\xkanjiskip|}
-$$\ncount=0
-\vbox{\halign{$#$\hfil\cr
-\node{\hbox{和文文字}}\node{\hbox{欧文文字}}
-\cr
-\hfil\Downarrow\cr
-\vadjust{\bigskip}
-\node{\hbox{和文文字}}
-\node{\nk w}_{\rm E}^*
-\node{\np P}\longrightarrow
-\left\{\vcenter{%
-\halign{$#$\hfil\cr
-\ncount=0\node{{\rm glue/kern}\ g+w}_{\rm J}\cr
-\ncount=0\node{\copy1+w}_{\rm XS}\cr
-}}\right\}^*
-\node{\hbox{欧文文字}}\cr
-}}
+\hbox{左空白(E)が存在しているか,$a\neq 0$かつ右空白がkernである.}
 $$
-ここで,上の2つの例に出てきた記号の意味は次の通り:
-\itemitem $w$: 前側の和文文字と行末の間に入るkern量.
-\itemitem $g$: 2つの文字の間に入るglue/kern(JFM由来).
-\itemitem $P$: 2つの文字の禁則用penaltyの合計値.
-
-
-\par\vfill\eject
-\item {\bf 例3: 2つの和文文字の間にいくつかの「無視される」node達}
-\setbox1=\hbox{|\kanjiskip|}
-$$\ncount=0
-\vbox{\halign{$\relax#$\hfil&$\relax#$\hfil\cr
-\node{\hbox{和字}\ A}&
-\ncount=1\node{\nk i_A}_{\rm I}
-\longrightarrow \cdots
-\node{\np p_B}
-\node{\hbox{和字}\ B}
-\cr
-\span\Downarrow\cr
-\vadjust{\bigskip}
-% T
-\node{\hbox{和字}\ A}&
-\ncount=1\node{\nk w_A}_{\rm E}^*
-\node{\np P_A}_{\rm K}^*
-\node{\nk {-w_A}}_{\rm T}^*
-\node{\nk i_A}_{\rm I}
-\longrightarrow \cdots\cr
-&\ncount=1\node{\np p_B}
-\node{\np P_B}^*\longrightarrow 
-\left\{\vcenter{%
-\halign{$#$\hfil\cr
-\ncount=0\node{{\rm glue/kern}\ g_B}_{\rm J}\cr
-\ncount=0\node{\copy1}_{\rm KS}\cr
-}}\right\}
-\node{\hbox{和字}\ B}\cr
-\span\hbox{or}\cr
-% T
-\node{\hbox{和字}\ A}&
-\ncount=1\node{\nk w_A}_{\rm E}^*
-\node{\np P_A}_{\rm K}^*
-\node{{\rm glue/kern}\ g_A-w_A}_{\rm J}
-\node{\nk i_A}_{\rm I}\cr
-&\ncount=1
-\longrightarrow \cdots
-\node{\np p_B}
-\node{\np P_B}
-\node{{\rm glue/kern}\ g_B}_{\rm J}^*
-\node{\hbox{和字}\ B}\cr
-}}
+\item {\bf「always」の場合:}
+この場合は,\IT{Nq}, \IT{Np}の間で常に行分割可能にしたいので,挿入する条件は以下のようになる:
 $$
-ここで,
-\itemitem $w_A$: 和文文字$A$と行末の間に入るkern量.
-\itemitem $P_A$: 和文文字$A$の行末禁則用penalty.
-\itemitem $g_A$: 和文文字$A$と|'jcharbdd'|との間に入るglue/kern
-\itemitem $P_B$: 和文文字$B$の行頭禁則用penalty
-\itemitem $g_B$: |'jcharbdd'|と和文文字$B$の間に入るglue/kern
+\hbox{左空白(E)が存在しているか,右空白がglueでない(つまり,kernか未定義のとき).}
+$$
+
+\item {\bf「suppress」の場合:}このとき,\IT{Nq}と\IT{Np}の間での行分割は元々不可能である
+Lua\TeX-ja では,そのような場合を「わざわざ行分割可能に」することはしない
+つまり,右空白がglueであるとき,その直前に|\penalty 10000|を挿入する
 \enditem
 
+\beginparagraph いくつかの例:未完
+
+\beginsection main loop その2: その他の場合
+
+\setbox1=\hbox{hp}\setbox2=\hbox to 0.4pt{\vrule height\dimexpr \ht1+0.25em\relax depth \dimexpr \dp1+0.25em\relax}
+$$\def\:{\hskip0.5em}\lineskiplimit=\maxdimen\lineskip=0pt
+\vcenter{\halign{\hfil\IT{#}\hfil\hskip1em\copy2%
+\:&\:\hfil\IT{#}\hfil\:&\:\hfil\IT{#}\hfil\:&\:\hfil\IT{#}\hfil\:&\:\hfil\IT{#}\hfil%
+\:&\:\hfil\IT{#}\hfil\:&\:\hfil\IT{#}\hfil\:&\:\hfil\IT{#}\hfil\:&\:\hfil\IT{#}\hfil\cr
+\IT{Np}→&&id\_hlist 非文字\cr
+\IT{Nq}↓&$\mibox{head}(\mibox{Nq})$\rm: 欧文&id\_box\_like&id\_glue&id\_kern\cr
+\noalign{\vskip.25em\hrule\vskip.25em}
+id\_jglyph&\rm E${}+{}$({\rm $\rm O_B$→X})&\rm E${}+\rm O_B^*$&\rm E${}+\rm O_B$&\rm E${}+\rm O_B^+$\cr
+id\_pbox 和&\rm E${}+{}$({\rm $\rm O_B$→X})&\rm E${}+\rm O_B^*$&\rm E${}+\rm O_B$&\rm E${}+\rm O_B^+$\cr
+id\_hlist 和&\rm X${}^+$&---&---&---\cr
+他&---&---&---&---\cr
+}}$$
 
 \end
index 5224b01..4e21aba 100644 (file)
Binary files a/doc/sample1.pdf and b/doc/sample1.pdf differ
index 19bdb49..f34a978 100644 (file)
@@ -11,7 +11,6 @@
 \def\XyM{X\kern-.30em\smash{\raise.50ex\hbox{\UPSILON}}\kern-.30em{M}}%
 \def\XyMTeX{\XyM\kern-.1em\TeX}%
 
-
 % main matter
 \centerline{\big Lua\TeX-jaパッケージ}\bigskip
 \centerline{\large\the\year/\the\month/\the\day}\medskip
@@ -31,7 +30,8 @@
 ほげほげ){\gt (ふがふが}
 \endtt
 \item 欧文や和文のベースライン補正が可能.
-\item p\TeX とある程度コマンド名が互換.
+\item p\TeX とある程度コマンド名が互換ではあるが,{\bf 内部動作についてはp\TeX との100\%互換は
+目指していません{\small (p\TeX で不自然なところがあれば,積極的に改める)\inhibitglue}}.
 \enditem
 
 \beginparagraph 制限
 
 \beginparagraph ファイル構成
 
-
-\item {\tt luatexja-core.sty}: 
-コア部分.拡張子は{\tt sty}であるが,この単一のファイルでplain \TeX と\LaTeX 両方に
-対応するように設計する方針である.しかし,
-{\bf 現時点で\LaTeX での使用は全く考慮されていない.}
-\item {\tt luatexja-core.lua}: コア部分に使われるLuaコード.
-\item {\tt luatexja-jfont.lua}: 和文フォント定義部のLuaコード.
-\item {\tt luatexja-xkanji.lua}: |\[x]kanjiskip|自動挿入処理のLuaコード.
-\item {\tt luatexja-rmlgbm-data.lua}: 非埋込和文フォント用のデータ(小塚明朝Pr6N R由来).
-\item {\tt luatexja-rmlgbm.lua}: 非埋込和文フォント (Ryumin-Light etc.) 定義部.
-\item {\tt mk-rmlgbm-data.tex}: {\tt luatexja-rmlgbm-data.lua}作成用スクリプト
+\item {\tt src/}: 核となる\TeX ソースとLuaコードはこのディレクトリ内に入っている.
+\itemitem \TeX 用スタイルファイル達
+\itemT {\tt luatexja.sty}: 利用者はこのファイルを読み込む.
+拡張子は{\tt sty}であるが,plain \TeX と\LaTeX 両方に対応させる方針である.しかし,
+{\bf 現時点で\LaTeX での使用は考慮されていない.}
+\itemT {\tt luatexja-core.sty}: 
+\itemT {\tt luatexja-base.sty}: 
+\itemT {\tt luatexja-cctbreg.sty}: 
+\itemT {\tt luatexja-compat.sty}: p\TeX 互換用primitive(|\euc|, |\kansuji|)定義部.
+\itemT {\tt luatexja-compat-ptex.sty}: 
+\itemT {\tt luatexja-plain.sty}: 
+\itemT {\tt luatexja-kinsoku.tex}: 禁則用ペナルティ等のパラメータを書いたファイル.
+{\tt ukinsoku.tex} (in up\TeX-0.30) から自動生成されたもの.
+
+\itemT {\tt mk-rmlgbm-data.tex}: {\tt luatexja-rmlgbm-data.lua}作成用スクリプト
 {\small(小塚明朝を{\tt luaotfload}で読み込んだ時のキャッシュが必要)\inhibitglue}.
-\item {\tt luatexja-kinsoku.tex}: 禁則用ペナルティ等のパラメータを書いたファイル.
-下のファイルによって{\tt ukinsoku.tex} (in up\TeX-0.30) から自動生成されたもの.
-\item {\tt jfm-ujis.lua}: up\TeX-0.30の{\tt ujis.tfm}ベースのメトリックサンプル.
-\item {\tt jfm-mono.lua}: 「全文字が全角幅」のメトリックサンプル.
+
+\itemitem Luaコード達(旧フォーマット)
+\itemT {\tt luatexja-core.lua}: コア部分に使われるLuaコード.
+\itemT {\tt luatexja-rmlgbm-data.lua}: 非埋込和文フォント用のデータ(小塚明朝Pr6N R由来).
+\itemT {\tt jfm-ujis.lua}: up\TeX-0.30の{\tt ujis.tfm}ベースのメトリックサンプル.
+\itemT {\tt jfm-mono.lua}: 「全文字が全角幅」のメトリックサンプル.
+
+\itemitem Luaコード達(新フォーマット,{\tt src/luatexja/}以下)
+
+\itemT {\tt base.lua}
+\itemT {\tt compat.lua}: p\TeX 互換用primitive(|\euc|, |\kansuji|)実装部.
+\itemT {\tt jisx0208.lua}: |\euc|等で使うJIS~X~0208→Unicode変換表.
+\itemT {\tt infomute.lua}
+\itemT {\tt jfont.lua}: 和文フォント定義部のLuaコード.
+\itemT {\tt rmlgbm.lua}: 非埋込和文フォント (Ryumin-Light etc.) 定義用コード.
+\itemT {\tt jfmglue.lua}: 和文処理に伴う空白の挿入処理部.
+\itemT {\tt tangle.lua}
+\itemT {\tt charrange.lua}: 「和文文字の範囲」管理部.
+\itemT {\tt debug.lua}
+\itemT {\tt inputbuf.lua}: 「和文文字直後の改行」処理用.
+\itemT {\tt stack.lua}: Lua\TeX-ja スタック管理システム.
 \enditem
 
 \beginsection 使用方法
 
 大雑把に言うと,plain \TeX の状況で,以下のようにすればよい.
 \begintt
-\input luatexja-core.sty               % ←マクロ本体を読み込み
+\input luatexja.sty               % ←マクロ本体を読み込み
 \jfont\tenipam={file:ipam.ttf:jfm=ujis} at 13.5\jQ 
 \tenipam\parindent=1\zw 
 
@@ -97,7 +118,6 @@ JFM は和文文字の幅や,和文文字間の空白の入り方などを規
   \globaljfont<font>={<font_name>:<features>} <size> % global に定義
 \endtt
 
-
 \item {\bf <font_name> の指定について}\par\noindent
 内部でluaotfloadパッケージを読み込んでいる.大きくわけて,以下の4種類がある.
 このうち,前の2つはluaotfloadパッケージの機能である.
@@ -332,7 +352,7 @@ Lua\TeX-jaで用いる和文用のメトリック情報は,次のようなLua
 見本として,|jfm-ujis.lua|を入れてある.
 
 \begintt
-ltj.define_jfm {
+luatexja.jfont.define_jfm {
    dir = 'yoko', zw = 1.0, zh = 1.0,
    [0] = {
       align = 'left', left = 0.0, down = 0.0,
@@ -359,7 +379,7 @@ ltj.define_jfm {
 }
 \endtt
 
-全体は,「関数|ltj.define_jfm|にテーブルを引数として与える」という構造になっている.
+全体は,「関数|luatexja.jfont.define_jfm|にテーブルを引数として与える」という構造になっている.
 以下に,テーブルの中身を述べる.
 \item |dir|: 組方向を指定する.将来的にはいずれ縦組(|'tate'|)を実装したいが,
 現時点では横組(|'yoko'|)のみの対応.
@@ -437,9 +457,11 @@ $i$番の文字クラスの文字と$j$番の文字クラスの文字の間に
 \beginsection 互換用命令(書きかけ)
 
 {\tt luatexja-compat.sty}を読み込むことで,次が追加.
-\item |\euc|, |\jis|, |\sjis|, |\kuten|, |\ucs|: up\TeX と同じ動作.
+\item |\euc|, |\jis|, |\sjis|, |\kuten|, |\ucs|: 
+それぞれEUC-JP,ISO-2022-JP,Shift-JIS,区点コードからUnicodeへの変換を行う.
+JIS~X~0208→Unicodeへの変換テーブルとしては,up\TeX-0.30で用いられているものを利用している.
 \item |\kansuji|
-\item |kansujichar={<num>, <char>}| key in |\ltjsetparameter|.
+\item |kansujichar={<num>, <char>}|~key in |\ltjsetparameter|.
 \enditem
 
 
@@ -490,47 +512,9 @@ $p$は「現在の和文フォント」の番号もattribute |\ltj@curjfnt|と
 
 \item {\bf (luaotfloadパッケージによるグリフ置換等の処理はこの位置で)}
 
-\item {\bf JFM由来glue/kernの挿入: |pre_linebreak_filter|, |hpack_filter| callbacks}
-
-ここで,JFMに由来する和文文字間のglue/kernを挿入する.
-基本的には連続する和文文字(を表すnode)間に挿入するが,
-\itemitem 水平ボックスの先頭/末尾,段落の先頭/末尾には「文字コード|'boxbdd'|の文字」があると
-見做して空白を挿入する.
-\itemitem 和文文字とそうでないもの(欧文文字,ボックス等)の間に関しては,
-和文文字でない方は「文字コード|'jcharbdd'|の文字」であると見做す.
-\itemitem フォントの異なる2つの和文文字においても,
-両者のフォントのJFMとsizeが一致した場合は,
-挿入処理においては「同じフォント」であるかのように扱う.
-\itemitem  そうでない場合は,両者の間に「文字コード|'diffmet'|の文字」があると見做して,
-両和文文字からそれぞれglue/kern |gb|, |ga|を計算し,そこから実際に入るglue/kernを
-計算している(|\ltjsetparameter|中の|differentjfm|キーを参照).
-\itemitem もうちょっと詳しく書くと,本処理前において,和文文字を表す
-2つの連続した|glyph_node| $Q$, $P$の間には,次のnode達が挿入される:
-$$
- \ldots,\ Q,\ (\hbox{|\kern|}\ w\,{\rm pt}),\ (\hbox{|\penalty|}\ p),\ 
-(\hbox{|\kern|}\ (k-w)\,{\rm pt})
-,\ P,\ \ldots
-$$
-上に書いた全てのnodeが挿入されるとは限らず,また4つめのkernもglueに変わる可能性がある.
-上に出てきた量の意味は次の通りである:
-\itemT $w$: $Q$が行末にきたときに,行末からどれだけずらすかを指定した量.
-\itemT $p$: $Q$の行末禁則用penaltyと$P$の行頭禁則用penaltyの合計値.ウィドウ防止用の
-|\jcharwidowpenalty|が挿入される時は,値はここに加算される.
-\itemT |\kern| $k$: 本来の$Q$と$P$の間に入る空き(glueであることも).
-$w$のために自然長を補正している.
-
-\item {\bf |kanjiskip|, |xkanjiskip|の挿入: |pre_linebreak_filter|, |hpack_filter| callbacks}
-
-p\TeX の|adjust_hlist| procedureとほぼ同様の処理を用いて,
-和文間glue |kanjiskip|や和欧文間glue |xkanjiskip|を
-挿入する.
-\itemitem 数式境界 (|math_node|) との間に|xkanjiskip|を自動挿入するかの決定は,
-p\TeX では数字{\tt 0}との間に挿入するかどうかで判定していたが,Lua\TeX-jaでは
-「文字コード$-1$の文字」で判定している.
-\itemitem 合字の周囲の空白挿入については,構成要素の文字列を通じて判断している.例えば,
-「漢ffi字」という文字列に対して,
-\itemT 「漢」と「ffi」間の空白挿入:「漢」と「f」間に入るかで判断
-\itemT 「ffi」と「字」間の空白挿入:「i」と「字」間に入るかで判断
+\item {\bf 和文処理グルーの挿入: |pre_linebreak_filter|, |hpack_filter| callbacks}
+
+動作の詳細については,{\tt jfmglue.pdf}(未完)を参照.
 
 \item {\bf ベースライン補正: |pre_linebreak_filter|, |hpack_filter| callbacks}
 
index f3eb63b..185e817 100644 (file)
@@ -1,4 +1,4 @@
-ltj.define_jfm {
+luatexja.jfont.define_jfm {
    dir = 'yoko',
    zw = 1.0, zh = 1.0,
 
index 6b4324e..6c5ea0d 100644 (file)
@@ -1,4 +1,4 @@
-ltj.define_jfm {
+luatexja.jfont.define_jfm {
    dir = 'yoko',
    zw = 1.0, zh = 1.0,
 
diff --git a/src/lltjdefs.sty b/src/lltjdefs.sty
new file mode 100644 (file)
index 0000000..fd28c36
--- /dev/null
@@ -0,0 +1,28 @@
+\DeclareKanjiEncodingDefaults{}{}
+\DeclareErrorKanjiFont{JY3}{mc}{m}{n}{10}
+\DeclareYokoKanjiEncoding{JY3}{}{}
+\DeclareKanjiSubstitution{JY3}{mc}{m}{n}
+%JT3
+
+\newcommand\mcdefault{mc}
+\newcommand\gtdefault{gt}
+\newcommand\kanjiencodingdefault{JY3}
+\newcommand\kanjifamilydefault{\mcdefault}
+\newcommand\kanjiseriesdefault{\mddefault}
+\newcommand\kanjishapedefault{\updefault}
+\kanjiencoding{JY3}
+
+\DeclareKanjiFamily{JY3}{mc}{}
+\DeclareFontShape{JY3}{mc}{m}{n}{<-> psft:Ryumin-Light:jfm=ujis}{}
+\DeclareKanjiFamily{JY3}{gt}{}
+\DeclareFontShape{JY3}{gt}{m}{n}{<-> psft:GothicBBB-Medium:jfm=ujis}{}
+\DeclareFontShape{JY3}{mc}{bx}{n}{<->ssub*gt/m/n}{}
+
+%fontencoding{JT3}\selectfont
+\fontencoding{JY3}\selectfont
+\DeclareTextFontCommand{\textmc}{\mcfamily}
+\DeclareTextFontCommand{\textgt}{\gtfamily}
+\DeclareOldFontCommand{\mc}{\normalfont\mcfamily}{}
+\DeclareOldFontCommand{\gt}{\normalfont\gtfamily}{}
+
+\endinput
diff --git a/src/lltjfont.sty b/src/lltjfont.sty
new file mode 100644 (file)
index 0000000..9f2a0da
--- /dev/null
@@ -0,0 +1,608 @@
+%%
+%% luatexja-latex-fonts.sty: derived from plfonts.dtx in pLaTeX.
+%% 
+\makeatletter
+\let\k@encoding\@empty
+\let\ck@encoding\@empty
+% LuaTeX-ja uses JY3 and JT3 encodings.
+\def\cy@encoding{JY3}\def\ct@encoding{JT3}
+
+
+\let\k@family\@empty
+\let\k@series\@empty
+\let\k@shape\@empty
+\def\curr@kfontshape{\k@encoding/\k@family/\k@series/\k@shape}
+\def\rel@fontshape{\f@encoding/\f@family/\f@series/\f@shape}
+\newdimen\Cht
+\newdimen\cht
+\newdimen\Cdp
+\newdimen\cdp
+\newdimen\Cwd
+\newdimen\cwd
+\newdimen\Cvs
+\newdimen\cvs
+\newdimen\Chs
+\newdimen\chs
+\newdimen\cHT
+%\let\afont\font
+\def\inlist@#1#2{%
+  \def\in@@##1<#1>##2##3\in@@{%
+    \ifx\in@##2\in@false\else\in@true\fi}%
+  \in@@#2<#1>\in@\in@@}
+\def\fam@elt{\noexpand\fam@elt}
+\def\enc@elt{\noexpand\enc@elt}
+\def\fenc@list{\enc@elt<OML>\enc@elt<T1>\enc@elt<OT1>\enc@elt<OMS>%
+               \enc@elt<OMX>\enc@elt<TS1>\enc@elt<U>}
+\let\kenc@list\@empty
+\let\kyenc@list\@empty
+\let\ktenc@list\@empty
+\def\kfam@list{\fam@elt<mc>\fam@elt<gt>}
+\def\ffam@list{\fam@elt<cmr>\fam@elt<cmss>\fam@elt<cmtt>%
+               \fam@elt<cmm>\fam@elt<cmsy>\fam@elt<cmex>}
+\let\notkfam@list\ffam@list
+\let\notffam@list\kfam@list
+\newbox\tstrutbox
+\newbox\zstrutbox
+\def\strut{\relax
+  \ifydir
+    \ifmmode\copy\strutbox\else\unhcopy\strutbox\fi
+  \else
+    \ifmmode\copy\tstrutbox\else\unhcopy\tstrutbox\fi
+  \fi}
+\def\tstrut{\relax\hbox{\tate
+   \ifmmode\copy\tstrutbox\else\unhcopy\tstrutbox\fi}}
+\def\zstrut{\relax\hbox{\tate
+   \ifmmode\copy\zstrutbox\else\unhcopy\zstrutbox\fi}}
+\def\DeclareFontEncoding{%
+  \begingroup
+  \nfss@catcodes
+  \expandafter\endgroup
+  \DeclareFontEncoding@}
+\def\DeclareFontEncoding@#1#2#3{%
+  \expandafter
+  \ifx\csname T@#1\endcsname\relax
+     \def\cdp@elt{\noexpand\cdp@elt}%
+     \xdef\cdp@list{\cdp@list\cdp@elt{#1}%
+                    {\default@family}{\default@series}%
+                    {\default@shape}}%
+     \expandafter\let\csname#1-cmd\endcsname\@changed@cmd
+     \def\enc@elt{\noexpand\enc@elt}%
+     \xdef\fenc@list{\fenc@list\enc@elt<#1>}%
+  \else
+     \@font@info{Redeclaring font encoding #1}%
+  \fi
+  \global\@namedef{T@#1}{#2}%
+  \global\@namedef{M@#1}{\default@M#3}%
+  \xdef\LastDeclaredEncoding{#1}%
+  }
+\def\DeclareKanjiEncoding#1{%
+  \@latex@warning{%
+     The \string\DeclareKanjiEncoding\space is obsoleted command.  Please use
+     \MessageBreak
+     the \string\DeclareTateKanjiEncoding\space for `Tate-kumi' encoding, and
+     \MessageBreak
+     the \string\DeclareYokoKanjiEncoding\space for `Yoko-kumi' encoding.
+     \MessageBreak
+     I treat the `#1' encoding as `Yoko-kumi'.}
+  \DeclareYokoKanjiEncoding{#1}%
+}
+\def\DeclareYokoKanjiEncoding{%
+  \begingroup
+  \nfss@catcodes
+  \expandafter\endgroup
+  \DeclareYokoKanjiEncoding@}
+\def\DeclareYokoKanjiEncoding@#1#2#3{%
+  \expandafter
+  \ifx\csname T@#1\endcsname\relax
+    \def\cdp@elt{\noexpand\cdp@elt}%
+    \xdef\cdp@list{\cdp@list\cdp@elt{#1}%
+                    {\default@k@family}{\default@k@series}%
+                    {\default@k@shape}}%
+    \expandafter\let\csname#1-cmd\endcsname\@changed@kcmd
+    \def\enc@elt{\noexpand\enc@elt}%
+    \xdef\kyenc@list{\kyenc@list\enc@elt<#1>}%
+    \xdef\kenc@list{\kenc@list\enc@elt<#1>}%
+  \else
+    \@font@info{Redeclaring KANJI (yoko) font encoding #1}%
+  \fi
+  \global\@namedef{T@#1}{#2}%
+  \global\@namedef{M@#1}{\default@KM#3}%
+  }
+\def\DeclareTateKanjiEncoding{%
+  \begingroup
+  \nfss@catcodes
+  \expandafter\endgroup
+  \DeclareTateKanjiEncoding@}
+\def\DeclareTateKanjiEncoding@#1#2#3{%
+  \expandafter
+  \ifx\csname T@#1\endcsname\relax
+    \def\cdp@elt{\noexpand\cdp@elt}%
+    \xdef\cdp@list{\cdp@list\cdp@elt{#1}%
+                    {\default@k@family}{\default@k@series}%
+                    {\default@k@shape}}%
+    \expandafter\let\csname#1-cmd\endcsname\@changed@kcmd
+    \def\enc@elt{\noexpand\enc@elt}%
+    \xdef\ktenc@list{\ktenc@list\enc@elt<#1>}%
+    \xdef\kenc@list{\kenc@list\enc@elt<#1>}%
+  \else
+    \@font@info{Redeclaring KANJI (tate) font encoding #1}%
+  \fi
+  \global\@namedef{T@#1}{#2}%
+  \global\@namedef{M@#1}{\default@KM#3}%
+  }
+\@onlypreamble\DeclareKanjiEncoding
+\@onlypreamble\DeclareYokoKanjiEncoding
+\@onlypreamble\DeclareYokoKanjiEncoding@
+\@onlypreamble\DeclareTateKanjiEncoding
+\@onlypreamble\DeclareTateKanjiEncoding@
+\def\DeclareKanjiEncodingDefaults#1#2{%
+  \ifx\relax#1\else
+    \ifx\default@KT\@empty\else
+      \@font@info{Overwriting KANJI encoding scheme text defaults}%
+    \fi
+    \gdef\default@KT{#1}%
+  \fi
+  \ifx\relax#2\else
+    \ifx\default@KM\@empty\else
+      \@font@info{Overwriting KANJI encoding scheme math defaults}%
+    \fi
+    \gdef\default@KM{#2}%
+  \fi}
+\let\default@KT\@empty
+\let\default@KM\@empty
+\@onlypreamble\DeclareKanjiEncodingDefaults
+\def\DeclareFontFamily#1#2#3{%
+ \@ifundefined{T@#1}%
+    {\@latex@error{Encoding scheme `#1' unknown}\@eha}%
+    {\edef\tmp@item{{#2}}%
+     \expandafter\expandafter\expandafter
+     \inlist@\expandafter\tmp@item\expandafter{\ffam@list}%
+     \ifin@ \else
+        \def\fam@elt{\noexpand\fam@elt}%
+        \xdef\ffam@list{\ffam@list\fam@elt<#2>}%
+     \fi
+     \def\reserved@a{#3}%
+     \global
+     \expandafter\let\csname #1+#2\expandafter\endcsname
+            \ifx \reserved@a\@empty
+              \@empty
+            \else \reserved@a
+            \fi
+    }%
+}
+\def\DeclareKanjiFamily#1#2#3{%
+ \@ifundefined{T@#1}%
+    {\@latex@error{KANJI Encoding scheme `#1' unknown}\@eha}%
+    {\edef\tmp@item{{#2}}%
+     \expandafter\expandafter\expandafter
+     \inlist@\expandafter\tmp@item\expandafter{\kfam@list}%
+     \ifin@ \else
+        \def\fam@elt{\noexpand\fam@elt}%
+        \xdef\kfam@list{\kfam@list\fam@elt<#2>}%
+     \fi
+     \def\reserved@a{#3}%
+     \global
+     \expandafter\let\csname #1+#2\expandafter\endcsname
+            \ifx \reserved@a\@empty
+              \@empty
+            \else \reserved@a
+            \fi
+     }%
+}
+\def\DeclareKanjiSubstitution#1#2#3#4{%
+  \expandafter\ifx\csname T@#1\endcsname\relax
+    \@latex@error{KANJI Encoding scheme `#1' unknown}\@eha
+  \else
+    \begingroup
+       \def\reserved@a{#1}%
+       \toks@{}%
+       \def\cdp@elt##1##2##3##4{%
+         \def\reserved@b{##1}%
+         \ifx\reserved@a\reserved@b
+           \addto@hook\toks@{\cdp@elt{#1}{#2}{#3}{#4}}%
+         \else
+           \addto@hook\toks@{\cdp@elt{##1}{##2}{##3}{##4}}%
+         \fi}%
+       \cdp@list
+       \xdef\cdp@list{\the\toks@}%
+    \endgroup
+    \global\@namedef{D@#1}{\def\default@family{#2}%
+                           \def\default@series{#3}%
+                           \def\default@shape{#4}}%
+  \fi}
+\def\DeclareErrorKanjiFont#1#2#3#4#5{%
+   \xdef\error@kfontshape{%
+      \noexpand\expandafter\noexpand\split@name\noexpand\string
+      \expandafter\noexpand\csname#1/#2/#3/#4/#5\endcsname
+      \noexpand\@nil}%
+   \gdef\default@k@family{#2}%
+   \gdef\default@k@series{#3}%
+   \gdef\default@k@shape{#4}%
+   \global\let\k@family\default@k@family
+   \global\let\k@series\default@k@series
+   \global\let\k@shape\default@k@shape
+   \gdef\f@size{#5}%
+   \gdef\f@baselineskip{#5pt}}
+\@onlypreamble\DeclareKanjiSubstitution
+\@onlypreamble\DeclareErrorKanjiFont
+\def\DeclareFixedFont#1#2#3#4#5#6{%
+   \begingroup
+      \math@fontsfalse
+      \every@math@size{}%
+      \fontsize{#6}\z@
+      \edef\tmp@item{{#2}}%
+      \expandafter\expandafter\expandafter
+      \inlist@\expandafter\tmp@item\expandafter{\kyenc@list}%
+      \ifin@
+        \usekanji{#2}{#3}{#4}{#5}%
+        \global\let#1\getjfont
+      \else
+        %\expandafter\expandafter\expandafter
+        %\inlist@\expandafter\tmp@item\expandafter{\ktenc@list}%
+        %\ifin@
+        %  \usekanji{#2}{#3}{#4}{#5}%
+        %  \let\font\tfont
+        %\else
+          \useroman{#2}{#3}{#4}{#5}%
+          \global\expandafter\let\expandafter#1\the\font
+        %\fi
+      \fi
+   \endgroup
+  }
+\def\reDeclareMathAlphabet#1#2#3{%
+  \edef#1{\noexpand\protect\expandafter\noexpand\csname%
+    \expandafter\@gobble\string#1\space\space\endcsname}%
+  \edef\@tempa{\expandafter\@gobble\string#2}%
+  \edef\@tempb{\expandafter\@gobble\string#3}%
+  \edef\@tempc{\string @\expandafter\@gobbletwo\string#2}%
+  \ifx\@tempc\@tempa%
+    \edef\@tempa{\expandafter\@gobbletwo\string#2}%
+    \edef\@tempb{\expandafter\@gobbletwo\string#3}%
+  \fi
+  \expandafter\edef\csname\expandafter\@gobble\string#1\space\space\endcsname%
+    {\noexpand\DualLang@mathalph@bet%
+      {\expandafter\noexpand\csname\@tempa\space\endcsname}%
+      {\expandafter\noexpand\csname\@tempb\space\endcsname}%
+  }%
+}
+\@onlypreamble\reDeclareMathAlphabet
+\def\DualLang@mathalph@bet#1#2{%
+  \relax\ifmmode
+    \ifx\math@bgroup\bgroup%     2e normal style     (\mathrm{...})
+      \bgroup\let\DualLang@Mfontsw\DLMfontsw@standard
+    \else
+      \ifx\math@bgroup\relax%    2e two letter style (\rm->\mathrm)
+        \let\DualLang@Mfontsw\DLMfontsw@oldstyle
+      \else
+        \bgroup\let\DualLang@Mfontsw\DLMfontsw@standard
+      \fi
+    \fi
+  \else
+    \let\DualLang@Mfontsw\@firstoftwo
+  \fi
+  \DualLang@Mfontsw{#1}{#2}%
+}
+\def\DLMfontsw@standard#1#2#3{#1{#2{#3}}\egroup}
+\def\DLMfontsw@oldstyle#1#2{#1\relax\@fontswitch\relax{#2}}
+\def\DLMfontsw@oldlfont#1#2{#1\relax#2\relax}
+\def\all@shape{all}%
+\def\DeclareRelationFont#1#2#3#4#5#6#7#8{%
+  \def\rel@shape{#4}%
+  \ifx\rel@shape\@empty
+     \global
+     \expandafter\def\csname rel@#1/#2/#3/all\endcsname{%
+       \romanencoding{#5}\romanfamily{#6}%
+       \romanseries{#7}}%
+  \else
+     \global
+     \expandafter\def\csname rel@#1/#2/#3/#4\endcsname{%
+       \romanencoding{#5}\romanfamily{#6}%
+       \romanseries{#7}\romanshape{#8}}%
+  \fi
+}
+\def\SetRelationFont#1#2#3#4#5#6#7#8{%
+  \def\rel@shape{#4}%
+  \ifx\rel@shape\@empty
+     \expandafter\def\csname rel@#1/#2/#3/all\endcsname{%
+       \romanencoding{#5}\romanfamily{#6}%
+       \romanseries{#7}}%
+  \else
+     \expandafter\def\csname rel@#1/#2/#3/#4\endcsname{%
+       \romanencoding{#5}\romanfamily{#6}%
+       \romanseries{#7}\romanshape{#8}}%
+  \fi
+}
+\newif\if@knjcmd
+\def\userelfont{\@knjcmdtrue}
+\DeclareRobustCommand\selectfont{%
+  \let\tmp@error@fontshape\error@fontshape
+  \let\error@fontshape\error@kfontshape
+  \edef\tmp@item{{\k@encoding}}%
+  \expandafter\expandafter\expandafter
+  \inlist@\expandafter\tmp@item\expandafter{\kyenc@list}%
+  \ifin@
+    \let\cy@encoding\k@encoding
+    \edef\ct@encoding{\csname t@enc@\k@encoding\endcsname}%
+  \else
+    \expandafter\expandafter\expandafter
+    \inlist@\expandafter\tmp@item\expandafter{\ktenc@list}%
+    \ifin@
+      \let\ct@encoding\k@encoding
+      \edef\cy@encoding{\csname y@enc@\k@encoding\endcsname}%
+    \else
+      \@latex@error{KANJI Encoding scheme `\k@encoding' unknown}\@eha
+    \fi
+  \fi
+  %\let\font\tfont
+  %\let\k@encoding\ct@encoding
+  %\xdef\font@name{\csname\curr@kfontshape/\f@size\endcsname}%
+  %\pickup@font
+  %\font@name
+  \let\k@encoding\cy@encoding
+  \xdef\font@name{\csname\curr@kfontshape/\f@size\endcsname}%
+  \pickup@jfont
+  \font@name
+  \expandafter\def\expandafter\k@encoding\tmp@item
+  \kenc@update
+  \let\error@fontshape\tmp@error@fontshape
+  \if@knjcmd \@knjcmdfalse
+    \expandafter\ifx
+    \csname rel@\k@encoding/\k@family/\k@series/\k@shape\endcsname\relax
+      \expandafter\ifx
+         \csname rel@\k@encoding/\k@family/\k@series/all\endcsname\relax
+      \else
+         \csname rel@\k@encoding/\k@family/\k@series/all\endcsname
+      \fi
+    \else
+       \csname rel@\k@encoding/\k@family/\k@series/\k@shape\endcsname
+    \fi
+  \fi
+  %\let\font\afont
+  \xdef\font@name{\csname\curr@fontshape/\f@size\endcsname}%
+  \pickup@font
+  \font@name
+  \enc@update
+  \ifx\f@linespread\baselinestretch \else
+    \set@fontsize\baselinestretch\f@size\f@baselineskip
+  \fi
+  \size@update}
+\def\KanjiEncodingPair#1#2{\@namedef{t@enc@#1}{#2}\@namedef{y@enc@#2}{#1}}
+\KanjiEncodingPair{JY3}{JT3}
+\def\set@fontsize#1#2#3{%
+    \@defaultunits\@tempdimb#2pt\relax\@nnil
+    \edef\f@size{\strip@pt\@tempdimb}%
+    \@defaultunits\@tempskipa#3pt\relax\@nnil
+    \edef\f@baselineskip{\the\@tempskipa}%
+    \edef\f@linespread{#1}%
+    \let\baselinestretch\f@linespread
+    \def\size@update{%
+      \baselineskip\f@baselineskip\relax
+      \baselineskip\f@linespread\baselineskip
+      \normalbaselineskip\baselineskip
+      \adjustbaseline
+      \setbox\strutbox\hbox{%\yoko
+          \vrule\@width\z@
+                \@height.7\baselineskip \@depth.3\baselineskip}%
+      \setbox\tstrutbox\hbox{%\tate
+          \vrule\@width\z@
+                \@height.5\baselineskip \@depth.5\baselineskip}%
+      \setbox\zstrutbox\hbox{%\tate
+          \vrule\@width\z@
+                \@height.7\baselineskip \@depth.3\baselineskip}%
+        \let\size@update\relax}}
+\newbox\adjust@box
+\newdimen\adjust@dimen
+\def\adjustbaseline{%
+    \setbox\adjust@box\hbox{\ltjsetparameter{yjabaselineshift=\z@}あ}%
+    \cht\ht\adjust@box
+    \cdp\dp\adjust@box
+    \cwd\wd\adjust@box
+    \cvs\normalbaselineskip
+    \chs\cwd
+    \cHT\cht \advance\cHT\cdp
+  % \iftdir
+  %   \setbox\adjust@box\hbox{\tbaselineshift\z@ M}%
+  %   \adjust@dimen\ht\adjust@box
+  %   \advance\adjust@dimen\dp\adjust@box
+  %   \advance\adjust@dimen-\cHT
+  %   \divide\adjust@dimen\tw@
+  %   \advance\adjust@dimen\cdp
+  %   \advance\adjust@dimen-\dp\adjust@box
+  %   \tbaselineshift\adjust@dimen
+  % \fi
+  }
+\DeclareRobustCommand\romanencoding[1]{%
+    \expandafter\ifx\csname T@#1\endcsname\relax
+      \@latex@error{Encoding scheme `#1' unknown}\@eha
+    \else
+      \edef\f@encoding{#1}%
+      \ifx\cf@encoding\f@encoding
+        \let\enc@update\relax
+      \else
+        \let\enc@update\@@enc@update
+      \fi
+    \fi
+}
+\DeclareRobustCommand\kanjiencoding[1]{%
+    \expandafter\ifx\csname T@#1\endcsname\relax
+      \@latex@error{KANJI Encoding scheme `#1' unknown}\@eha
+    \else
+      \edef\k@encoding{#1}%
+      \ifx\ck@encoding\k@encoding
+         \let\kenc@update\relax
+      \else
+         \let\kenc@update\@@kenc@update
+      \fi
+    \fi
+}
+\DeclareRobustCommand\fontencoding[1]{%
+  \edef\tmp@item{{#1}}%
+  \expandafter\expandafter\expandafter
+  \inlist@\expandafter\tmp@item\expandafter{\kenc@list}%
+  \ifin@ \kanjiencoding{#1}\else\romanencoding{#1}\fi}
+\def\@@kenc@update{%
+  \default@KT
+  \csname T@\k@encoding\endcsname
+  \csname D@\k@encoding\endcsname
+  \let\kenc@update\relax
+  \let\ck@encoding\k@encoding
+  \edef\tmp@item{{\k@encoding}}%
+  \expandafter\expandafter\expandafter
+  \inlist@\expandafter\tmp@item\expandafter{\kyenc@list}%
+  \ifin@ \let\cy@encoding\k@encoding
+  \else
+    \expandafter\expandafter\expandafter
+    \inlist@\expandafter\tmp@item\expandafter{\ktenc@list}%
+    \ifin@ \let\ct@encoding\k@encoding
+    \else
+      \@latex@error{KANJI Encoding scheme `\k@encoding' unknown}\@eha
+    \fi
+  \fi
+}
+\let\kenc@update\relax
+\def\@changed@kcmd#1#2{%
+   \ifx\protect\@typeset@protect
+      \@inmathwarn#1%
+      \expandafter\ifx\csname\ck@encoding\string#1\endcsname\relax
+         \expandafter\ifx\csname ?\string#1\endcsname\relax
+            \expandafter\def\csname ?\string#1\endcsname{%
+               \TextSymbolUnavailable#1%
+            }%
+         \fi
+         \global\expandafter\let
+               \csname\cf@encoding \string#1\expandafter\endcsname
+               \csname ?\string#1\endcsname
+      \fi
+      \csname\ck@encoding\string#1%
+         \expandafter\endcsname
+   \else
+      \noexpand#1%
+   \fi}
+\newif\if@notkfam
+\newif\if@notffam
+\newif\if@tempswz
+\DeclareRobustCommand\romanfamily[1]{\edef\f@family{#1}}
+\DeclareRobustCommand\kanjifamily[1]{\edef\k@family{#1}}
+\DeclareRobustCommand\fontfamily[1]{%
+  \edef\tmp@item{{#1}}%
+  \@notkfamfalse
+  \@notffamfalse
+  \expandafter\expandafter\expandafter
+  \inlist@\expandafter\tmp@item\expandafter{\kfam@list}%
+  \ifin@ \edef\k@family{#1}%
+  \else
+    \expandafter\expandafter\expandafter
+    \inlist@\expandafter\tmp@item\expandafter{\notkfam@list}%
+    \ifin@ \@notkfamtrue
+    \else
+      \@tempswzfalse
+      \def\fam@elt{\noexpand\fam@elt}%
+      \message{(I search kanjifont definition file:}%
+      \def\enc@elt<##1>{\message{.}%
+        \edef\reserved@a{\lowercase{\noexpand\IfFileExists{##1#1.fd}}}%
+        \reserved@a{\@tempswztrue}{}\relax}%
+      \kenc@list
+      \message{)}%
+      \if@tempswz
+        \edef\k@family{#1}%
+      \else
+        \@notkfamtrue
+        \xdef\notkfam@list{\notkfam@list\fam@elt<#1>}%
+      \fi
+  \fi\fi
+  \expandafter\expandafter\expandafter
+  \inlist@\expandafter\tmp@item\expandafter{\ffam@list}%
+  \ifin@ \edef\f@family{#1}\else
+    \expandafter\expandafter\expandafter
+    \inlist@\expandafter\tmp@item\expandafter{\notffam@list}%
+    \ifin@ \@notffamtrue \else
+      \@tempswzfalse
+      \def\fam@elt{\noexpand\fam@elt}%
+      \message{(I search font definition file:}%
+      \def\enc@elt<##1>{\message{.}%
+        \edef\reserved@a{\lowercase{\noexpand\IfFileExists{##1#1.fd}}}%
+        \reserved@a{\@tempswztrue}{}\relax}%
+      \fenc@list
+      \message{)}%
+      \if@tempswz
+        \edef\f@family{#1}%
+      \else
+        \@notffamtrue
+        \xdef\notffam@list{\notffam@list\fam@elt<#1>}%
+      \fi
+  \fi\fi
+  \if@notkfam\if@notffam
+      \edef\k@family{#1}\edef\f@family{#1}%
+  \fi\fi}
+\DeclareRobustCommand\romanseries[1]{\edef\f@series{#1}}
+\DeclareRobustCommand\kanjiseries[1]{\edef\k@series{#1}}
+\DeclareRobustCommand\fontseries[1]{\kanjiseries{#1}\romanseries{#1}}
+\DeclareRobustCommand\romanshape[1]{\edef\f@shape{#1}}
+\DeclareRobustCommand\kanjishape[1]{\edef\k@shape{#1}}
+\DeclareRobustCommand\fontshape[1]{\kanjishape{#1}\romanshape{#1}}
+\def\usekanji#1#2#3#4{%
+    \kanjiencoding{#1}\kanjifamily{#2}\kanjiseries{#3}\kanjishape{#4}%
+    \selectfont\ignorespaces}
+\def\useroman#1#2#3#4{%
+    \romanencoding{#1}\romanfamily{#2}\romanseries{#3}\romanshape{#4}%
+    \selectfont\ignorespaces}
+\def\usefont#1#2#3#4{%
+  \edef\tmp@item{{#1}}%
+  \expandafter\expandafter\expandafter
+  \inlist@\expandafter\tmp@item\expandafter{\kenc@list}%
+  \ifin@ \usekanji{#1}{#2}{#3}{#4}%
+  \else\useroman{#1}{#2}{#3}{#4}%
+  \fi}
+\DeclareRobustCommand\normalfont{%
+    \kanjiencoding{\kanjiencodingdefault}%
+    \kanjifamily{\kanjifamilydefault}%
+    \kanjiseries{\kanjiseriesdefault}%
+    \kanjishape{\kanjishapedefault}%
+    \romanencoding{\encodingdefault}%
+    \romanfamily{\familydefault}%
+    \romanseries{\seriesdefault}%
+    \romanshape{\shapedefault}%
+    \selectfont\ignorespaces}
+\adjustbaseline
+\let\reset@font\normalfont
+\DeclareRobustCommand\mcfamily
+        {\not@math@alphabet\mcfamily\mathmc
+         \kanjifamily\mcdefault\selectfont}
+\DeclareRobustCommand\gtfamily
+        {\not@math@alphabet\gtfamily\mathgt
+         \kanjifamily\gtdefault\selectfont}
+\let\romanprocess@table\process@table
+\def\kanjiprocess@table{%
+  \kanjiencoding{\kanjiencodingdefault}%
+  \kanjifamily{\kanjifamilydefault}%
+  \kanjiseries{\kanjiseriesdefault}%
+  \kanjishape{\kanjishapedefault}%
+}
+\def\process@table{%
+  \romanprocess@table
+  \kanjiprocess@table
+}
+\@onlypreamble\romanprocess@table
+\@onlypreamble\kanjiprocess@table
+\DeclareTextCommandDefault{\textunderscore}{%
+  \leavevmode\kern.06em
+  %\iftdir\raise-\tbaselineshift\fi
+  \vbox{\hrule\@width.3em}}
+
+\let\extract@afont\extract@font
+\def\pickup@jfont{%
+    \expandafter \ifx \font@name \relax
+       \let\extract@font\extract@jfont
+       \define@newfont
+       \let\extract@font\extract@afont
+    \fi
+    \let\getjfont\font@name}
+
+\def\extract@jfont{%
+    \get@external@font
+    \expandafter\globaljfont\font@name\external@font\relax
+    \font@name\global\zw=\zw\global\zh=\zh
+    \csname \f@encoding+\f@family\endcsname
+    \csname\curr@fontshape\endcsname}
+
+\endinput
index c47e5d5..618b680 100644 (file)
 %% Load Lua modules.
 \RequireLuaModule{luatexja.base}
 \RequireLuaModule{luatexja.tangle}
-\RequireLuaModule{luatexja.charrange}
-\RequireLuaModule{luatexja.stack}
-\RequireLuaModule{luatexja.inputbuf}
-
 %%------------------ Tiny helpers
 
 %% Registers
index e4d1f04..a5c63bb 100644 (file)
@@ -1,6 +1,13 @@
-local ltjb = luatexja.base
-local ltjc = luatexja.charrange
-local ltjs = luatexja.stack
+require('lualibs')
+require('luatexja.rmlgbm');    local ltjr = luatexja.rmlgbm -- must be 1st
+require('luatexja.base');      local ltjb = luatexja.base
+require('luatexja.charrange'); local ltjc = luatexja.charrange
+require('luatexja.jfont');     local ltjf = luatexja.jfont
+require('luatexja.inputbuf');  local ltji = luatexja.inputbuf
+require('luatexja.jfmglue');   local ltjj = luatexja.jfmglue
+require('luatexja.pretreat');  local ltjp = luatexja.pretreat
+require('luatexja.stack');     local ltjs = luatexja.stack
+require('luatexja.setwidth');  local ltjw = luatexja.setwidth
 
 local node_type = node.type
 local node_new = node.new
@@ -27,24 +34,18 @@ local sid_user = node.subtype('user_defined')
 local attr_jchar_class = luatexbase.attributes['ltj@charclass']
 local attr_curjfnt = luatexbase.attributes['ltj@curjfnt']
 local attr_yablshift = luatexbase.attributes['ltj@yablshift']
-local attr_ykblshift = luatexbase.attributes['ltj@ykblshift']
 local attr_icflag = luatexbase.attributes['ltj@icflag']
 
-local lang_ja_token = token.create('ltj@japanese')
-local lang_ja = lang_ja_token[2]
-
--- 
-local ljfm_find_char_class = ltj.int_find_char_class
-
-
 local ITALIC = 1
-local TEMPORARY = 2
-local FROM_JFM = 3
-local KINSOKU = 4
+local PACKED = 2
+local KINSOKU = 3
+local FROM_JFM = 4
 local LINE_END = 5
 local KANJI_SKIP = 6
 local XKANJI_SKIP = 7
-local PACKED = 8
+local PROCESSED = 8
+local IC_PROCESSED = 9
+local BOXBDD = 15
 
 ------------------------------------------------------------------------
 -- naming:
@@ -100,12 +101,6 @@ local function print_spec(p)
 return out
 end
 
--- return true if and only if p is a Japanese character node
-local function is_japanese_glyph_node(p)
-   return p and (p.id==id_glyph) 
-   and (p.font==has_attr(p,attr_curjfnt))
-end
-
 function math.two_add(a,b) return a+b end
 function math.two_average(a,b) return (a+b)/2 end
 
@@ -132,13 +127,13 @@ function ltj.ext_get_parameter_unary(k)
    elseif k == 'autoxspacing' then
       tex.write(tex.getattribute('ltj@autoxspc'))
    elseif k == 'differentjfm' then
-      if ltj.ja_diffmet_rule == math.max then
+      if luatexja.jfmglue.diffmet_rule == math.max then
         tex.write('large')
-      elseif ltj.ja_diffmet_rule == math.min then
+      elseif luatexja.jfmglue.diffmet_rule == math.min then
         tex.write('small')
-      elseif ltj.ja_diffmet_rule == math.two_average then
+      elseif luatexja.jfmglue.diffmet_rule == math.two_average then
         tex.write('average')
-      elseif ltj.ja_diffmet_rule == math.two_add then
+      elseif luatexja.jfmglue.diffmet_rule == math.two_add then
         tex.write('both')
       else -- This can't happen.
         tex.write('???')
@@ -152,8 +147,8 @@ function ltj.ext_get_parameter_binary(k,c)
       if c<0 or c>216 then 
         ltjb.package_error('luatexja',
                            'invalid character range number (' .. c .. ')',
-                           {'A character range number should be in the range 0..216,',
-                            'So I changed this one to zero.'})
+                           'A character range number should be in the range 0..216,\n'..
+                            'So I changed this one to zero.')
         c=0
       end
       tex.write(ltjc.get_range_setting(c))
@@ -161,9 +156,9 @@ function ltj.ext_get_parameter_binary(k,c)
       if c<0 or c>0x10FFFF then
         ltjb.package_error('luatexja',
                            'bad character code (' .. c .. ')',
-                           {'A character number must be between -1 and 0x10ffff.',
-                            "(-1 is used for denoting `math boundary')",
-                            'So I changed this one to zero.'})
+                           'A character number must be between -1 and 0x10ffff.\n'..
+                              "(-1 is used for denoting `math boundary')\n"..
+                              'So I changed this one to zero.')
         c=0
       end
       if k == 'prebreakpenalty' then
@@ -185,155 +180,12 @@ function ltj.ext_print_global()
   if ltj.isglobal=='global' then tex.sprint('\\global') end
 end
 
-
-------------------------------------------------------------------------
--- MAIN PROCESS STEP 1: replace fonts (prefix: main1)
-------------------------------------------------------------------------
-ltj.box_stack_level = 0
--- This is used in Step 2 (JFM glue/kern) and Step 3 (\[x]kanjiskip).
-
-local function main1_suppress_hyphenate_ja(head)
-   for p in node.traverse_id(id_glyph, head) do
-      if ltjc.is_ucs_in_japanese_char(p) then
-        local v = has_attr(p, attr_curjfnt)
-        if v then 
-           p.font = v 
-           node.set_attribute(p, attr_jchar_class,
-                              ljfm_find_char_class(p.char, ltj.font_metric_table[v].jfm))
-        end
-        v = has_attr(p, attr_ykblshift)
-        if v then 
-           node.set_attribute(p, attr_yablshift, v)
-        else
-           node.unset_attribute(p, attr_yablshift)
-        end
-         if p.subtype%2==1 then p.subtype = p.subtype - 1 end
-        p.lang=lang_ja
-      end
-   end
-   lang.hyphenate(head)
-   return head
-end
-
--- mode: true iff this function is called from hpack_filter
-local function main1_set_box_stack_level(head, mode)
-   local box_set = false
-   local p = head
-   local cl = tex.currentgrouplevel + 1
-   while p do
-      if p.id==id_whatsit and p.subtype==sid_user and p.user_id==30112 then
-        local g = p
-        if mode and g.value==cl then box_set = true end
-        head, p = node.remove(head, g)
-      else p = node_next(p)
-      end
-   end
-   if box_set then 
-      ltj.box_stack_level = tex.getcount('ltj@@stack') + 1 
-   else 
-      ltj.box_stack_level = tex.getcount('ltj@@stack') 
-   end
-   if not head then -- prevent that the list is null
-      head = node_new(id_kern); head.kern = 0; head.subtype = 1
-   end
-   return head
-end
-
--- CALLBACKS
-luatexbase.add_to_callback('hpack_filter', 
-   function (head)
-     return main1_set_box_stack_level(head, true)
-   end,'ltj.hpack_filter_pre',1)
-luatexbase.add_to_callback('pre_linebreak_filter', 
-  function (head)
-     return main1_set_box_stack_level(head, false)
-  end,'ltj.pre_linebreak_filter_pre',1)
-luatexbase.add_to_callback('hyphenate', 
- function (head,tail)
-    return main1_suppress_hyphenate_ja(head)
- end,'ltj.hyphenate')
-
-
-------------------------------------------------------------------------
--- MAIN PROCESS STEP 4: width of japanese chars (prefix: main4)
-------------------------------------------------------------------------
-
--- TeX's \hss
-local function main4_get_hss()
-   local hss = node_new(id_glue)
-   local fil_spec = node_new(id_glue_spec)
-   fil_spec.width = 0
-   fil_spec.stretch = 65536
-   fil_spec.stretch_order = 2
-   fil_spec.shrink = 65536
-   fil_spec.shrink_order = 2
-   hss.spec = fil_spec
-   return hss
-end
-
-local function main4_set_ja_width(head)
-   local p = head
-   local met_tb, t, s, g, q, a, h
-   local m = false -- is in math mode?
-   while p do
-      local v=has_attr(p,attr_yablshift) or 0
-      if p.id==id_glyph then
-        p.yoffset = p.yoffset-v
-        if is_japanese_glyph_node(p) then
-           met_tb = ltj.font_metric_table[p.font]
-           t = ltj.metrics[met_tb.jfm]
-           s = t.char_type[has_attr(p,attr_jchar_class)]
-           if s.width ~= 'prop' and
-              not(s.left==0.0 and s.down==0.0 and s.align=='left' 
-                  and round(s.width*met_tb.size)==p.width) then
-              -- must be encapsuled by a \hbox
-              head, q = node.remove(head,p)
-              p.next = nil
-              p.yoffset=round(p.yoffset-met_tb.size*s.down)
-              p.xoffset=round(p.xoffset-met_tb.size*s.left)
-              if s.align=='middle' or s.align=='right' then
-                 h = node_insert_before(p, p, main4_get_hss())
-              else h=p end
-              if s.align=='middle' or s.align=='left' then
-                 node_insert_after(h, p, main4_get_hss())
-              end
-              g = node_hpack(h, round(met_tb.size*s.width), 'exactly')
-              g.height = round(met_tb.size*s.height)
-              g.depth = round(met_tb.size*s.depth)
-              node.set_attribute(g, attr_icflag, PACKED)
-              if q then
-                 head = node_insert_before(head, q, g)
-              else
-                 head = node_insert_after(head, node.tail(head), g)
-              end
-              p = q
-           else p=node_next(p)
-           end
-        else p=node_next(p)
-        end
-      elseif p.id==id_math then
-        m=(p.subtype==0); p=node_next(p)
-      else
-        if m then
-           if p.id==id_hlist or p.id==id_vlist then
-              p.shift=p.shift+v
-           elseif p.id==id_rule then
-              p.height=p.height-v; p.depth=p.depth+v 
-           end
-        end
-        p=node_next(p)
-      end
-   end
-return head
-end
-
 -- main process
 -- mode = true iff main_process is called from pre_linebreak_filter
-local function main_process(head, mode)
+local function main_process(head, mode, dir)
    local p = head
-   p = ltj.int_insert_jfm_glue(p,mode)
-   p = ltj.int_insert_kanji_skip(p)
-   p = main4_set_ja_width(p)
+   p = ltjj.main(p,mode)
+   p = ltjw.set_ja_width(p, dir)
    return p
 end
 
@@ -362,12 +214,16 @@ function debug_show_node_X(p,print_fn)
    local k = debug_depth
    local s
    local pt=node_type(p.id)
+   local base = debug_depth .. string.format('%X', has_attr(p,attr_icflag) or 0) 
+     .. ' ' .. pt .. ' ' ..  p.subtype 
    if pt == 'glyph' then
-      print_fn(debug_depth.. ' GLYPH  ', p.subtype, utf.char(p.char), p.font)
+      s = base .. ' ' .. utf.char(p.char) .. ' ' .. tostring(p.font)
+         .. ' (' .. print_scaled(p.height) .. '+' 
+         .. print_scaled(p.depth) .. ')x' .. print_scaled(p.width)
+      print_fn(s)
    elseif pt=='hlist' then
-      s = debug_depth .. ' hlist  ' ..  p.subtype
-        .. '(' .. print_scaled(p.height) .. '+' .. print_scaled(p.depth) .. ')x'
-         .. print_scaled(p.width)
+      s = base .. '(' .. print_scaled(p.height) .. '+' 
+         .. print_scaled(p.depth) .. ')x' .. print_scaled(p.width)
       if p.glue_sign >= 1 then 
         s = s .. ' glue set '
         if p.glue_sign == 2 then s = s .. '-' end
@@ -379,6 +235,9 @@ function debug_show_node_X(p,print_fn)
            for i = 2,  p.glue_order do s = s .. 'l' end
         end
       end
+      if has_attr(p, attr_icflag, PACKED) then
+        s = s .. ' (packed)'
+      end
       print_fn(s)
       local q = p.head
       debug_depth=debug_depth.. '.'
@@ -387,11 +246,8 @@ function debug_show_node_X(p,print_fn)
       end
       debug_depth=k
    elseif pt == 'glue' then
-      s = debug_depth.. ' glue   ' ..  p.subtype 
-        .. ' ' ..  print_spec(p.spec)
-      if has_attr(p, attr_icflag)==TEMPORARY then
-        s = s .. ' (might be replaced)'
-      elseif has_attr(p, attr_icflag)==FROM_JFM then
+      s = base .. ' ' ..  print_spec(p.spec)
+      if has_attr(p, attr_icflag)==FROM_JFM then
            s = s .. ' (from JFM)'
       elseif has_attr(p, attr_icflag)==KANJI_SKIP then
         s = s .. ' (kanjiskip)'
@@ -400,12 +256,13 @@ function debug_show_node_X(p,print_fn)
       end
       print_fn(s)
    elseif pt == 'kern' then
-      s = debug_depth.. ' kern   ' ..  p.subtype
-        .. ' ' .. print_scaled(p.kern) .. 'pt'
-      if has_attr(p, attr_icflag)==ITALIC then
+      s = base .. ' ' .. print_scaled(p.kern) .. 'pt'
+      if p.subtype==2 then
+        s = s .. ' (for accent)'
+      elseif has_attr(p, attr_icflag)==IC_PROCESSED then
         s = s .. ' (italic correction)'
-      elseif has_attr(p, attr_icflag)==TEMPORARY then
-        s = s .. ' (might be replaced)'
+      -- elseif has_attr(p, attr_icflag)==ITALIC then
+      --    s = s .. ' (italic correction)'
       elseif has_attr(p, attr_icflag)==FROM_JFM then
         s = s .. ' (from JFM)'
       elseif has_attr(p, attr_icflag)==LINE_END then
@@ -413,13 +270,13 @@ function debug_show_node_X(p,print_fn)
       end
       print_fn(s)
    elseif pt == 'penalty' then
-      s = debug_depth.. ' penalty ' ..  tostring(p.penalty)
+      s = base .. ' ' .. tostring(p.penalty)
       if has_attr(p, attr_icflag)==KINSOKU then
         s = s .. ' (for kinsoku)'
       end
       print_fn(s)
    elseif pt == 'whatsit' then
-      s = debug_depth.. ' whatsit ' ..  tostring(p.subtype)
+      s = base .. ' subtype: ' ..  tostring(p.subtype)
       if p.subtype==sid_user then
         s = s .. ' user_id: ' .. p.user_id .. ' ' .. p.value
       else
@@ -427,18 +284,23 @@ function debug_show_node_X(p,print_fn)
       end
       print_fn(s)
    else
-      print_fn(debug_depth.. ' ' .. node.type(p.id), p.subtype)
+      print_fn(base)
    end
    p=node_next(p)
 end
 
 
 -- callbacks
+
 luatexbase.add_to_callback('pre_linebreak_filter', 
    function (head,groupcode)
-     return main_process(head, true)
-   end,'ltj.pre_linebreak_filter',2)
+      return main_process(head, true, tex.textdir)
+   end,'ltj.pre_linebreak_filter',
+   luatexbase.priority_in_callback('pre_linebreak_filter',
+                                  'luaotfload.pre_linebreak_filter') + 1)
 luatexbase.add_to_callback('hpack_filter', 
-  function (head,groupcode,size,packtype)
-     return main_process(head, false)
-  end,'ltj.hpack_filter',2)
+  function (head,groupcode,size,packtype, dir)
+     return main_process(head, false, dir)
+  end,'ltj.hpack_filter',
+   luatexbase.priority_in_callback('hpack_filter',
+                                  'luaotfload.hpack_filter') + 1)
index 9571965..3d13c0e 100644 (file)
     texio.write_nl("("..path..")")
     dofile(path)
   end
-  require('lualibs')
-  ltj.loadlua('luatexja-rmlgbm.lua') 
-    % For Ryumin-Light and GothicBBB-Medium.
-  ltj.loadlua('luatexja-jfont.lua')
   ltj.loadlua('luatexja-core.lua')
-  ltj.loadlua('luatexja-jfmglue.lua')
-  ltj.loadlua('luatexja-xkanji.lua')
 }
 
 
 
 %%%%%%%% Redefine \/
 %\let\ltj@ic=\/ \protected\def\/{{\ltj@icflag=1\ltj@ic}}
-\protected\def\/{\directlua{ltj.ext_append_italic()}}
+\protected\def\/{\directlua{luatexja.jfont.append_italic()}}
 
 %%%%%%%% \jfont\CS={...:...;jfm=metric;...}, \globaljfont
-\protected\def\jfont{\afterassignment\ltj@@jfont\directlua{ltj.ext_jfontdefX(false)}}
+\protected\def\jfont{\afterassignment\ltj@@jfont\directlua{luatexja.jfont.jfontdefX(false)}}
 \protected\def\globaljfont{%
-  \afterassignment\ltj@@jfont\directlua{ltj.ext_jfontdefX(true)}}
-\def\ltj@@jfont{\directlua{ltj.ext_jfontdefY()}}
+  \afterassignment\ltj@@jfont\directlua{luatexja.jfont.jfontdefX(true)}}
+\def\ltj@@jfont{\directlua{luatexja.jfont.jfontdefY()}}
 
 %%%%%%%% \inhibitglue
-\protected\def\inhibitglue{\directlua{ltj.ext_create_inhibitglue_node()}}
+\protected\def\inhibitglue{\directlua{luatexja.jfmglue.create_inhibitglue_node()}}
 
 %%%%%%%% \ltjdefcharrange<name>{100-200,3000-,5000,...}
 \protected\def\ltjdefcharrange#1#2{%
 \define@choicekey*+[ltj]{japaram}{differentjfm}[\ltj@temp\ltj@tempr]%
   {large,small,average,both}{%
   \ifcase\ltj@tempr
-    \directlua{ltj.ja_diffmet_rule = math.max}\or
-    \directlua{ltj.ja_diffmet_rule = math.min}\or
-    \directlua{ltj.ja_diffmet_rule = math.two_average}\or
-    \directlua{ltj.ja_diffmet_rule = math.two_add}
+    \directlua{luatexja.jfmglue.diffmet_rule = math.max}\or
+    \directlua{luatexja.jfmglue.diffmet_rule = math.min}\or
+    \directlua{luatexja.jfmglue.diffmet_rule = math.two_average}\or
+    \directlua{luatexja.jfmglue.diffmet_rule = math.two_add}
   \fi
 }{\ltj@PackageError{luatexja}{invalid argument `#1' for `differentjfm'}{%
   Argument for `differentjfm' must be one of `large', `small', `average',^^J%
diff --git a/src/luatexja-jfmglue.lua b/src/luatexja-jfmglue.lua
deleted file mode 100644 (file)
index 5a3b9d5..0000000
+++ /dev/null
@@ -1,416 +0,0 @@
-------------------------------------------------------------------------
--- MAIN PROCESS STEP 2: insert glue/kerns from JFM (prefix: none)
-------------------------------------------------------------------------
-
-local ltjs = luatexja.stack
-
-local node_type = node.type
-local node_new = node.new
-local node_remove = node.remove
-local node_prev = node.prev
-local node_next = node.next
-local has_attr = node.has_attribute
-local set_attr = node.set_attribute
-local node_insert_before = node.insert_before
-local node_insert_after = node.insert_after
-local round = tex.round
-
-local id_penalty = node.id('penalty')
-local id_glyph = node.id('glyph')
-local id_glue_spec = node.id('glue_spec')
-local id_glue = node.id('glue')
-local id_kern = node.id('kern')
-local id_hlist = node.id('hlist')
-local id_whatsit = node.id('whatsit')
-local sid_user = node.subtype('user_defined')
-
-local TEMPORARY = 2
-local FROM_JFM = 3
-local KINSOKU = 4
-local LINE_END = 5
-
-
-local attr_jchar_class = luatexbase.attributes['ltj@charclass']
-local attr_curjfnt = luatexbase.attributes['ltj@curjfnt']
-local attr_icflag = luatexbase.attributes['ltj@icflag']
--- attr_icflag: 1: kern from \/, 2: 'lineend' kern from JFM
-
--- 
-local ljfm_find_char_class = ltj.int_find_char_class
-
--- arithmetic with penalty.
--- p += e
-local function add_penalty(p,e)
-   local i = p
-   if i>=10000 then
-      if e<=-10000 then i = 0 end
-   elseif i<=-10000 then
-      if e>=10000 then i = 0 end
-   else
-      i = i + e
-      if i>=10000 then i = 10000
-      elseif i<=-10000 then i = -10000 end
-   end
-   return i
-end
-
--- return true if and only if p is a Japanese character node
-local function is_japanese_glyph_node(p)
-   return (p.id==id_glyph) and (p.font==has_attr(p,attr_curjfnt))
-end
-
--- EXT: for \inhibitglue
-function ltj.ext_create_inhibitglue_node()
-   local g=node_new(id_whatsit, sid_user)
-   g.user_id=30111; g.type=100; g.value=1; node.write(g)
-end
-
--- In the beginning of a hlist created by line breaking, there are the followings:
---   - a hbox by \parindent
---   - a whatsit node which contains local paragraph materials.
--- When we insert jfm glues, we ignore these nodes.
-local function is_parindent_box(p)
-   if p.id==id_hlist then 
-      return (p.subtype==3)
-      -- hlist (subtype=3) is a box by \parindent
-   elseif p.id==id_whatsit then 
-      return (p.subtype==node.subtype('local_par'))
-   end
-end
-
-local function find_size_metric(px)
-   if is_japanese_glyph_node(px) then
-      return { ltj.font_metric_table[px.font].size, 
-              ltj.font_metric_table[px.font].jfm, ltj.font_metric_table[px.font].var }
-   else 
-      return nil
-   end
-end
-
-local function new_jfm_glue(size,mt,bc,ac)
--- mt: metric key, bc, ac: char classes
-   local g=nil
-   local z = ltj.metrics[mt].char_type[bc]
-   if z.glue and z.glue[ac] then
-      local h = node_new(id_glue_spec)
-      h.width   = round(size*z.glue[ac][1])
-      h.stretch = round(size*z.glue[ac][2])
-      h.shrink  = round(size*z.glue[ac][3])
-      h.stretch_order=0; h.shrink_order=0
-      g = node_new(id_glue)
-      g.subtype = 0; g.spec = h
-   elseif z.kern and z.kern[ac] then
-      g = node_new(id_kern)
-      g.subtype = 1; g.kern = round(size*z.kern[ac])
-   end
-   return g
-end
-
--- Insert jfm glue: main routine
--- local variables
-local p
-local q = nil  -- the previous node of p
-local q_post   -- the postbreakpenalty of q
-local ps, qs
-local widow_node -- 最後の「句読点扱いでない」和文文字
-local widow_bp -- 挿入位置 (a penalty)
-local last -- the sentinel 
-local chain = false -- is q a Japanese character?
-local ihb_flag = false -- is \inhibitglue specified?
-local head -- the head of current list
-local mode -- true iff insert_jfm_glue is called from pre_linebreak_filter
-
--- initialize (insert the sentinel, etc.)
-local function init_var()
-   p = head;  q = nil; widow_node = nil; widow_bp = nil
-   chain = false; ihb_flag = false; 
-   if mode then
-      while p and is_parindent_box(p) do p=node_next(p) end
-      last=node.tail(head)
-      if last and last.id==id_glue and last.subtype==15 then
-        last=node.prev(last)
-        while (last and last.id==id_penalty) do last=node.prev(last) end
-      end
-      if last then last=node_next(last) end
-   else -- 番人を挿入
-      last=node.tail(head); local g = node_new('kern')
-      node_insert_after(head, last, g); last = g
-   end
-end
-
--- Insert JFM glue before the first node (which is a Japanese glyph node)
-local function ins_gk_head()
-   if is_japanese_glyph_node(p) then
-      ps = find_size_metric(p)
-      local g = new_jfm_glue(ps[1], ps[2],
-                            ljfm_find_char_class('boxbdd',ps[2]),
-                            has_attr(p,attr_jchar_class))
-      if g then
-        set_attr(g, attr_icflag, FROM_JFM)
-        head = node_insert_before(head, p, g)
-      end
-      q_post = ltjs.get_penalty_table('post', p.char, 0, ltj.box_stack_level); chain = true
-   elseif p.id==id_glyph then
-      q_post = ltjs.get_penalty_table('post', p.char, 0, ltj.box_stack_level)
-   end
-   qs = ps; q = p; p = node_next(p)
-end
-
--- The real insertion process is handled in this procedure.
-local function real_insert(g, w, pen, always_penalty_ins)
-   -- g: glur/kern from JFM
-   -- w: the width of kern that will be inserted between q and the end of a line
-   -- pen: penalty
-   -- always_penalty_ins: true iff we insert a penalty,
-   --   for the linebreak between q and p.
-   if w~=0 then
-      if not g then
-        g = node_new(id_kern); g.kern = -w; g.subtype = 1
-        set_attr(g, attr_icflag, TEMPORARY)
-        -- this g might be replaced by \[x]kanjiskip in step 3.
-      else 
-        set_attr(g, attr_icflag, FROM_JFM)
-        if g.id==id_kern then w=0
-        else g.spec.width = round(g.spec.width - w) 
-        end
-      end
-   end
-   if w~=0 then
-      local h = node_new(id_kern)
-      set_attr(h, attr_icflag, LINE_END)
-      h.kern = w; h.subtype = 0; node_insert_before(head, p, h)
-   elseif g then
-      set_attr(g, attr_icflag, FROM_JFM)
-      if g.id==id_kern  then
-        pen=0; always_penalty_ins = false
-      end
-   end
-   if w~=0  or pen~=0 or ((not g) and always_penalty_ins) then
-      local h = node_new(id_penalty)
-      h.penalty = pen; set_attr(h, attr_icflag, KINSOKU)
-      node_insert_before(head, p, h)
-   end
-   if g then
-      node_insert_before(head, p, g); 
-   end
-end
-
--- This is a variant of real_insert (the case which a kern is related)
-local function real_insert_kern(g)
-   if g then
-      if g.id==id_glue then
-        local h = node_new(id_penalty)
-        h.penalty = 10000; set_attr(h, attr_icflag, KINSOKU)
-        node_insert_before(head, p, h)
-      end
-      set_attr(g, attr_icflag, FROM_JFM)
-      node_insert_before(head, p, g)
-   end
-end
-
-ltj.ja_diffmet_rule = math.two_average
-
-local function calc_ja_ja_aux(gb,ga)
-   if not gb then 
-      return ga
-   else
-      if not ga then return gb end
-      local k = node.type(gb.id) .. node.type(ga.id)
-      if k == 'glueglue' then 
-        -- 両方とも glue.
-        gb.spec.width   = round(ltj.ja_diffmet_rule(gb.spec.width, ga.spec.width))
-        gb.spec.stretch = round(ltj.ja_diffmet_rule(gb.spec.stretch,ga.spec.shrink))
-        gb.spec.shrink  = -round(ltj.ja_diffmet_rule(-gb.spec.shrink, -ga.spec.shrink))
-        return gb
-      elseif k == 'kernkern' then
-        -- 両方とも kern.
-        gb.kern = round(ltj.ja_diffmet_rule(gb.kern, ga.kern))
-        return gb
-      elseif k == 'kernglue' then 
-        -- gb: kern, ga: glue
-        ga.spec.width   = round(ltj.ja_diffmet_rule(gb.kern,ga.spec.width))
-        ga.spec.stretch = round(ltj.ja_diffmet_rule(ga.spec.stretch, 0))
-        ga.spec.shrink  = -round(ltj.ja_diffmet_rule(-ga.spec.shrink, 0))
-        return ga
-      else
-        -- gb: glue, ga: kern
-        gb.spec.width   = round(ltj.ja_diffmet_rule(ga.kern, gb.spec.width))
-        gb.spec.stretch = round(ltj.ja_diffmet_rule(gb.spec.stretch, 0))
-        gb.spec.shrink  = -round(ltj.ja_diffmet_rule(-gb.spec.shrink, 0))
-        return gb
-      end
-   end
-end
-
--- Calc the glue between two Japanese characters
-local function calc_ja_ja_glue()
-   if ihb_flag then return nil
-   elseif table.are_equal(qs,ps) then
-      return new_jfm_glue(ps[1],ps[2],
-                         has_attr(q,attr_jchar_class),
-                         has_attr(p,attr_jchar_class))
-   else
-      local g = new_jfm_glue(qs[1],qs[2],
-                            has_attr(q,attr_jchar_class),
-                            ljfm_find_char_class('diffmet',qs[2]))
-      local h = new_jfm_glue(ps[1],ps[2],
-                            ljfm_find_char_class('diffmet',ps[2]),
-                            has_attr(p,attr_jchar_class))
-      return calc_ja_ja_aux(g,h)
-   end
-end
-
-local function ins_gk_any_JA()
-   ps = find_size_metric(p)
-   if chain then -- (q,p): JA-JA
-      local g = calc_ja_ja_glue()
-      local w = 0; local x = ljfm_find_char_class('lineend', qs[2])
-      if (not ihb_flag) and x~=0  then
-        local h = ltj.metrics[qs[2]].char_type[has_attr(q, attr_jchar_class)]
-        if h.kern and h.kern[x] then w = round(qs[1]*h.kern[x]) end
-      end
-      q_post = add_penalty(q_post, ltjs.get_penalty_table('pre', p.char, 0, ltj.box_stack_level))
-      real_insert(g, w, q_post, false)
-   elseif q.id==id_glyph then -- (q,p): AL-JA
-      local g = nil
-      if not ihb_flag then
-        g = new_jfm_glue(ps[1], ps[2],
-                         ljfm_find_char_class('jcharbdd',ps[2]),
-                         has_attr(p,attr_jchar_class))
-      end
-      q_post = add_penalty(q_post, ltjs.get_penalty_table('pre', p.char, 0, ltj.box_stack_level))
-      real_insert(g, 0, q_post, true)
-   elseif q.id==id_kern then -- (q,p): kern-JA
-      local g = nil
-      if not ihb_flag then
-        g = new_jfm_glue(ps[1], ps[2],
-                         ljfm_find_char_class('jcharbdd',ps[2]),
-                         has_attr(p,attr_jchar_class))
-      end
-      real_insert_kern(g)
-   else
-      local g = nil
-      if not ihb_flag then
-        g = new_jfm_glue(ps[1], ps[2],
-                         ljfm_find_char_class('jcharbdd',ps[2]),
-                         has_attr(p,attr_jchar_class))
-      end
-      real_insert(g, 0, q_post, true)
-   end
-   q, qs, q_post = p, ps, ltjs.get_penalty_table('post', p.char, 0, ltj.box_stack_level)
-   if ltjs.get_penalty_table('kcat', p.char, 0, ltj.box_stack_level)%2~=1 then
-      widow_node = p
-   end
-   p = node_next(p); chain = true
-end
-
-local function ins_gk_JA_any()
-   -- the case (q,p): JA-JA is treated in ins_gk_any_JA()
-   local g = nil
-   if not ihb_flag then
-      g = new_jfm_glue(qs[1], qs[2],
-                      has_attr(q,attr_jchar_class),
-                      ljfm_find_char_class('jcharbdd',qs[2]))
-   end
-   if p.id==id_glyph then -- (q,p): JA-AL
-      local w = 0; local x = ljfm_find_char_class('lineend', qs[2])
-      if (not ihb_flag) and x~=0  then
-        local h = ltj.metrics[qs[2]].char_type[has_attr(q,attr_jchar_class)]
-        if h.kern and h.kern[x] then w = round(qs[1]*h.kern[x]) end
-      end
-      q_post = add_penalty(q_post, ltjs.get_penalty_table('pre', p.char, 0, ltj.box_stack_level))
-      real_insert(g, w, q_post, true)
-   elseif p.id==id_kern then -- (q,p): JA-kern
-      real_insert_kern(g)
-   else
-      local w = 0; local x = ljfm_find_char_class('lineend', qs[2])
-      if (not ihb_flag) and x~=0  then
-        local h = ltj.metrics[qs[2]].char_type[has_attr(q,attr_jchar_class)]
-        if h.kern and h.kern[x] then w = round(qs[1]*h.kern[x]) end
-      end
-      if p.id~=penalty then
-        real_insert(g, w, q_post, true)
-      else
-        real_insert(g, w, q_post, false)
-      end
-   end
-   chain = false; q, qs, q_post = p, nil, 0; p = node_next(p)
-end
-
--- Insert JFM glue after thr last node
-local function ins_gk_tail()
-   local g
-   if is_japanese_glyph_node(p) then
-      if mode then
-        local w = 0; local x = ljfm_find_char_class('lineend', qs[2])
-        if (not ihb_flag) and x~=0  then
-           local h = ltj.metrics[qs[2]].char_type[has_attr(q,attr_jchar_class)]
-           if h.kern and h.kern[x] then w = round(qs[1]*h.kern[x]) end
-        end
-        if w~=0 then
-           g = node_new(id_kern); g.subtype = 0; g.kern = w
-           set_attr(g, attr_icflag, LINE_END)
-           node_insert_before(head, last, g)
-        end
-      end
-   end
-end
-
-local function add_widow_penalty()
-   -- widoe_node: must be 
-   if not widow_node then return end
-   local a = node_prev(widow_node)
-   local i = has_attr(a, attr_icflag) or 0
-   local wp = ltjs.get_penalty_table('jwp', 0, 0, ltj.box_stack_level)
-   if i==4 then
-      a.penalty=add_penalty(a.penalty, wp)
-   elseif i>=2 then
-      local b = node_prev(a)
-      if i==4 then
-        b.penalty=add_penalty(b.penalty, wp)
-      else
-        local g = node_new(id_penalty)
-        g.penalty = wp; head = node_insert_before(head,a,g)
-      end
-   else
-      local g = node_new(id_penalty)
-      g.penalty = wp; head = node_insert_before(head,widow_node,g)
-   end
-end
-
--- Finishing: add \jcharwidowpenalty or remove the sentinel
-local function finishing()
-   if mode then
-      -- Insert \jcharwidowpenalty
-      add_widow_penalty()
-   else
-      head = node_remove(head, last)
-   end
-end
-
--- The interface
-function ltj.int_insert_jfm_glue(ahead, amode)
-   if not ahead then return ahead end
-   head = ahead; mode = amode; init_var(); 
-   while p~=last and p.id==id_whatsit and p.subtype==sid_user and p.user_id==30111 do
-      local g = p; p = node_next(p); ihb_flag = true; head, p = node.remove(head, g)
-   end
-   if p~=last then ins_gk_head() else finishing() return head end
-   while p~=last do
-      if p.id==id_whatsit and p.subtype==sid_user and p.user_id==30111 then
-        local g = p; p = node_next(p)
-        ihb_flag = true; head, p = node.remove(head, g)
-      else
-        if is_japanese_glyph_node(p) then -- p: JAchar
-           ins_gk_any_JA()
-        elseif chain then -- q: JAchar
-           ins_gk_JA_any()
-        else 
-           q, qs, q_post = p, nil, 0; p = node_next(p)
-        end
-        ihb_flag = false
-      end
-   end
-   ins_gk_tail(); finishing(); return head
-end
-
index a7c7083..90d317e 100644 (file)
@@ -1,3 +1,45 @@
+\ltj@tempcnta="0%"
+\loop\ifnum\ltj@tempcnta<"100%"
+  \ltjsetparameter{alxspmode={\ltj@tempcnta,0}}%
+  \advance\ltj@tempcnta by1
+\repeat
+
+\ltj@tempcnta=`\0%"
+\loop\ifnum\ltj@tempcnta<`\:%"
+  \ltjsetparameter{alxspmode={\ltj@tempcnta,3}}%
+  \advance\ltj@tempcnta by1
+\repeat
+
+\ltj@tempcnta=`\A%"
+\loop\ifnum\ltj@tempcnta<`\[%"
+  \ltjsetparameter{alxspmode={\ltj@tempcnta,3}}%
+  \advance\ltj@tempcnta by1
+\repeat
+
+\ltj@tempcnta=`\a%"
+\loop\ifnum\ltj@tempcnta<`\{%"
+  \ltjsetparameter{alxspmode={\ltj@tempcnta,3}}%
+  \advance\ltj@tempcnta by1
+\repeat
+
+\ltj@tempcnta="2000%"
+\loop\ifnum\ltj@tempcnta<"2070%"
+  \ltjsetparameter{kcatcode={\ltj@tempcnta,1}}%
+  \advance\ltj@tempcnta by1
+\repeat
+
+\ltj@tempcnta="3000%"
+\loop\ifnum\ltj@tempcnta<"3040%"
+  \ltjsetparameter{kcatcode={\ltj@tempcnta,1}}%
+  \advance\ltj@tempcnta by1
+\repeat
+
+\ltj@tempcnta="FF00%"
+\loop\ifnum\ltj@tempcnta<"FFF0%"
+  \ltjsetparameter{kcatcode={\ltj@tempcnta,1}}%
+  \advance\ltj@tempcnta by1
+\repeat
+
 %
 %      行頭、行末禁則パラメータ
 %
diff --git a/src/luatexja-latex.sty b/src/luatexja-latex.sty
new file mode 100644 (file)
index 0000000..98c656f
--- /dev/null
@@ -0,0 +1,38 @@
+%
+% luatexja-latex.sty
+%
+
+%! これは外から読まれない
+%% Avoid multiple loading.
+\csname luatexjalatexLoaded\endcsname
+\edef\ltj@latex@AtEnd{%
+\endlinechar=\the\endlinechar
+\relax}
+\endlinechar=-1 %
+\def\luatexjalatexLoaded{\endinput}
+
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{luatexja-latex}[2011/08/01 v0.1]
+
+\endlinechar=13
+
+
+%%% patch for LaTeX (similar to plfonts.dtx)
+\input{lltjfont.sty}
+\input{lltjdefs.sty}
+
+%%% parameter
+
+\ltjsetparameter{kanjiskip=0pt plus 0.4pt minus 0.4pt, 
+  xkanjiskip=.25\zw plus 1pt minus 1pt,
+  autospacing, autoxspacing, jacharrange={-1}, 
+  yalbaselineshift=0pt, yjabaselineshift=0pt,
+  jcharwidowpenalty=500, differentjfm=average
+}
+
+\input luatexja-kinsoku.tex
+
+%%------------------ all done
+\ltj@latex@AtEnd
+\endinput
+%% EOF
index 29610c1..c347946 100644 (file)
   jcharwidowpenalty=500, differentjfm=average
 }
 
-\ltj@tempcnta="0%"
-\loop\ifnum\ltj@tempcnta<"100%"
-  \ltjsetparameter{alxspmode={\ltj@tempcnta,0}}%
-  \advance\ltj@tempcnta by1
-\repeat
-
-\ltj@tempcnta=`\0%"
-\loop\ifnum\ltj@tempcnta<`\:%"
-  \ltjsetparameter{alxspmode={\ltj@tempcnta,3}}%
-  \advance\ltj@tempcnta by1
-\repeat
-
-\ltj@tempcnta=`\A%"
-\loop\ifnum\ltj@tempcnta<`\[%"
-  \ltjsetparameter{alxspmode={\ltj@tempcnta,3}}%
-  \advance\ltj@tempcnta by1
-\repeat
-
-\ltj@tempcnta=`\a%"
-\loop\ifnum\ltj@tempcnta<`\{%"
-  \ltjsetparameter{alxspmode={\ltj@tempcnta,3}}%
-  \advance\ltj@tempcnta by1
-\repeat
-
-\input luatexja-kinsoku.tex
-
-\ltj@tempcnta="2000%"
-\loop\ifnum\ltj@tempcnta<"2070%"
-  \ltjsetparameter{kcatcode={\ltj@tempcnta,1}}%
-  \advance\ltj@tempcnta by1
-\repeat
-
-\ltj@tempcnta="3000%"
-\loop\ifnum\ltj@tempcnta<"3040%"
-  \ltjsetparameter{kcatcode={\ltj@tempcnta,1}}%
-  \advance\ltj@tempcnta by1
-\repeat
-
-\ltj@tempcnta="FF00%"
-\loop\ifnum\ltj@tempcnta<"FFF0%"
-  \ltjsetparameter{kcatcode={\ltj@tempcnta,1}}%
-  \advance\ltj@tempcnta by1
-\repeat
-%\endinput
-%! ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
-
 %%------------------ all done
 \ltj@plain@AtEnd
 \endinput
diff --git a/src/luatexja-xkanji.lua b/src/luatexja-xkanji.lua
deleted file mode 100644 (file)
index 2335966..0000000
+++ /dev/null
@@ -1,417 +0,0 @@
-------------------------------------------------------------------------
--- MAIN PROCESS STEP 3: insert \xkanjiskip (prefix: none)
-------------------------------------------------------------------------
-local ltjs = luatexja.stack
-
-local node_type = node.type
-local node_new = node.new
-local node_prev = node.prev
-local node_next = node.next
-local node_copy = node.copy
-local has_attr = node.has_attribute
-local set_attr = node.set_attribute
-local node_insert_before = node.insert_before
-local node_insert_after = node.insert_after
-local node_hpack = node.hpack
-local round = tex.round
-
-local id_penalty = node.id('penalty')
-local id_glyph = node.id('glyph')
-local id_glue = node.id('glue')
-local id_glue_spec = node.id('glue_spec')
-local id_kern = node.id('kern')
-local id_hlist = node.id('hlist')
-local id_ins = node.id('ins')
-local id_mark = node.id('mark')
-local id_adjust = node.id('adjust')
-local id_math = node.id('math')
-local id_whatsit = node.id('whatsit')
-
-local attr_icflag = luatexbase.attributes['ltj@icflag']
-local attr_autospc = luatexbase.attributes['ltj@autospc']
-local attr_autoxspc = luatexbase.attributes['ltj@autoxspc']
-local attr_curjfnt = luatexbase.attributes['ltj@curjfnt']
-local max_dimen = 1073741823
-
-local ITALIC = 1
-local TEMPORARY = 2
-local FROM_JFM = 3
-local KINSOKU = 4
-local LINE_END = 5
-local KANJI_SKIP = 6
-local XKANJI_SKIP = 7
-local PACKED = 8
-
-local kanji_skip
-local xkanji_skip
-
--- (glyph_node nr) ... (node nq) <GLUE> ,,, (node np)
-local np, nq, nrc, nrf
-local np_spc, nr_spc
-local no_skip = 0 
-local after_schar = 1
-local after_wchar = 2 -- nr is a Japanese glyph_node
-local insert_skip = no_skip
-local head
-
-local function is_japanese_glyph_node(p)
-   return p and (p.id==id_glyph) 
-   and (p.font==has_attr(p,attr_curjfnt))
-end
-
-local function get_zero_glue()
-   local g = node_new(id_glue_spec)
-   g.width = 0; g.stretch_order = 0; g.stretch = 0
-   g.shrink_order = 0; g.shrink = 0
-   return g
-end
-
-local function skip_table_to_spec(n)
-   local g = node_new(id_glue_spec)
-   local st = ltjs.get_skip_table(n, ltj.box_stack_level)
-   g.width = st.width; g.stretch = st.stretch; g.shrink = st.shrink
-   g.stretch_order = st.stretch_order; g.shrink_order = st.shrink_order
-   return g
-end
-
-local function add_glue_spec(g,h)
-   -- g := g + h
-   g.width = g.width + h.width
-   if g.stretch_order<h.stretch_order then
-      g.stretch_order = h.stretch_order
-      g.stretch = h.stretch
-   elseif g.stretch_order==h.stretch_order then
-      g.stretch = g.stretch + h.stretch
-   end
-   if g.shrink_order<h.shrink_order then
-      g.shrink_order = h.shrink_order
-      g.shrink = h.shrink
-   elseif g.shrink_order==h.shrink_order then
-      g.shrink = g.shrink + h.shrink
-   end
-end
-
--- lowest part of \xkanjiskip 
-local function get_xkanji_skip_from_jfm(pf)
-   if pf then
-      local px = { ltj.font_metric_table[pf].size, 
-                  ltj.font_metric_table[pf].jfm }
-      local i = ltj.metrics[px[2]].xkanjiskip
-      if i then
-        return { round(i[1]*px[1]), round(i[2]*px[1]), round(i[3]*px[1]) }
-      else return nil
-      end
-   else return nil
-   end
-end
-
-local function insert_xkanjiskip_node(q, f, p)
-   if nr_spc[2] or np_spc[2] then
-      local g = node_new(id_glue); g.subtype = 0
-      if xkanji_skip.width==max_dimen then -- use xkanjiskip from JFM
-        local gx = node_new(id_glue_spec)
-        gx.stretch_order = 0; gx.shrink_order = 0
-        local ak = get_xkanji_skip_from_jfm(f)
-        if ak then
-           gx.width = ak[1]; gx.stretch = ak[2]; gx.shrink = ak[3]
-        else gx = get_zero_glue() -- fallback
-        end
-        g.spec = gx
-      else g.spec=node_copy(xkanji_skip)
-      end
-      local h = node_prev(p)
-      if h  and has_attr(h, attr_icflag)==TEMPORARY then
-        if h.id==id_kern then
-           g.spec.width = g.spec.width + h.kern
-           set_attr(g,attr_icflag,XKANJI_SKIP)
-           node_insert_after(head, q, g)
-           head = node.remove(head, h)
-           node.free(h)
-        else
-           add_glue_spec(h.spec, g.spec)
-           node.free(g.spec); node.free(g)
-        end
-      else
-        set_attr(g,attr_icflag,XKANJI_SKIP)
-        node_insert_after(head, q, g)
-      end
-   end
-end
-
-local function insert_ascii_kanji_xkskip(q, p)
-   if ltjs.get_penalty_table('xsp', p.char, 3, ltj.box_stack_level)<=1 then return end
-   insert_xkanjiskip_node(q, p.font, p)
-end
-
-local function insert_kanji_ascii_xkskip(q, p)
-   local g = true
-   local c = p.char
-   while p.components and p.subtype 
-      and math.floor(p.subtype/2)%2==1 do
-      p = p.components; c = p.char
-   end
-   if ltjs.get_penalty_table('xsp', c, 3, ltj.box_stack_level)%2 == 1 then
-      if ltjs.get_penalty_table('xsp', nrc, 3, ltj.box_stack_level)%2 == 0 then g = false end
-   else g = false
-   end
-   if g then insert_xkanjiskip_node(q, nrf, p) end
-end
-
-local function set_insert_skip_after_achar(p)
-   local c = p.char
-   while p.components and p.subtype 
-      and math.floor(p.subtype/2)%2 == 1 do
-      p=node.tail(p.components); c = p.char
-   end
-  if ltjs.get_penalty_table('xsp', c, 3, ltj.box_stack_level)>=2 then
-     insert_skip = after_schar
-  else
-     insert_skip = no_skip
-  end
-end
-
--- lowest part of \kanjiskip 
-local function get_kanji_skip_from_jfm(pf)
-   if pf then
-      local px = { ltj.font_metric_table[pf].size, 
-                  ltj.font_metric_table[pf].jfm }
-      local i = ltj.metrics[px[2]].kanjiskip
-      if i then
-        return { round(i[1]*px[1]), round(i[2]*px[1]), round(i[3]*px[1]) }
-      else return nil
-      end
-   else return nil
-   end
-end
-
-local function insert_kanji_skip(ope, p)
-   local g = node_new(id_glue); g.subtype=0
-   if nr_spc[1] or np_spc[1] then
-      if kanji_skip.width==max_dimen then -- use kanjiskip from JFM
-        local gx = node_new(id_glue_spec);
-        gx.stretch_order = 0; gx.shrink_order = 0
-        local bk = get_kanji_skip_from_jfm(nrf)
-        local ak = get_kanji_skip_from_jfm(p.font)
-        if bk then
-           if ak then
-              gx.width = round(ltj.ja_diffmet_rule(bk[1], ak[1]))
-              gx.stretch = round(ltj.ja_diffmet_rule(bk[2], ak[2]))
-              gx.shrink = -round(ltj.ja_diffmet_rule(-bk[3], -ak[3]))
-           else
-              gx.width = bk[1]; gx.stretch = bk[2]; gx.shrink = bk[3]
-           end
-        elseif ak then
-           gx.width = ak[1]; gx.stretch = ak[2]; gx.shrink = ak[3]
-        else gx = get_zero_glue() -- fallback
-        end
-        g.spec = gx
-      else g.spec=node_copy(kanji_skip)
-      end
-   else g.spec = get_zero_glue()
-   end
-   local h = node_prev(p)
-   if h  and has_attr(h, attr_icflag)==TEMPORARY then
-      if h.id==id_kern then
-        g.spec.width = g.spec.width + h.kern
-        head = node.remove(head, h)
-        node.free(h)
-        set_attr(g,attr_icflag,KANJI_SKIP)
-        ope(head, p, g)
-      else
-        add_glue_spec(h.spec, g.spec)
-        node.free(g.spec); node.free(g)
-      end
-   else
-      set_attr(g,attr_icflag,KANJI_SKIP)
-      ope(head, p, g)
-   end
-end
-
--- When p is a glyph_node ...
-local function insks_around_char()
-   if is_japanese_glyph_node(np) then
-      if insert_skip==after_wchar then
-        insert_kanji_skip(node_insert_before, np)
-      elseif insert_skip==after_schar then
-        insert_ascii_kanji_xkskip(nq, np)
-      end
-      insert_skip=after_wchar
-      nrc = np.char; nrf = np.font; nr_spc = np_spc
-   else
-      if insert_skip==after_wchar then
-        insert_kanji_ascii_xkskip(nq, np)
-      end
-      set_insert_skip_after_achar(np); nr_spc = np_spc
-   end
-   nq = np
-end
-
--- Return first and last glyph nodes in a hbox
-local first_char = nil
-local last_char = nil
-local find_first_char = nil
-local function check_box(box_ptr)
-   local p = box_ptr; local found_visible_node = false
-   if not p then 
-      find_first_char = false; first_char = nil; last_char = nil
-      return true
-   end
-   while p do
-      if p.id==id_glyph then
-        repeat 
-           if find_first_char then
-              first_char = p; find_first_char = false
-           end
-           last_char = p; found_visible_node = true; p=node_next(p)
-           if not p then return found_visible_node end
-        until p.id~=id_glyph
-      end
-      if p.id==id_hlist then
-        if has_attr(p, attr_icflag)==PACKED then
-           for q in node.traverse_id(id_glyph, p.head) do
-              if find_first_char then
-                 first_char = q; find_first_char = false
-              end
-              last_char = q; found_visible_node = true
-           end
-        else
-           if p.shift==0 then
-              if check_box(p.head) then found_visible_node = true end
-           else if find_first_char then 
-                 find_first_char = false
-              else 
-                 last_char = nil
-              end
-           end
-        end
-      elseif p.id==id_ins    or p.id==id_mark
-          or p.id==id_adjust or p.id==id_whatsit
-          or p.id==id_penalty then
-        p=p
-      else
-        found_visible_node = true
-        if find_first_char then 
-           find_first_char = false
-        else 
-           last_char = nil
-        end
-      end
-      p = node_next(p)
-   end
-   return found_visible_node
-end 
-
--- When np is a hlist_node ...
-local function insks_around_hbox()
-   if np.shift==0 then
-      find_first_char = true; first_char = nil; last_char = nil
-      if check_box(np.head) then
-        -- first char
-        if is_japanese_glyph_node(first_char) then
-           nrc = first_char.char; nrf = first_char.font
-           if insert_skip==after_schar then 
-              insert_ascii_kanji_xkskip(nq, first_char)
-           elseif insert_skip==after_wchar then
-              np_spc = { has_attr(first_char, attr_autospc)==1, 
-                         has_attr(first_char, attr_autoxspc)==1 }
-              insert_kanji_skip(node_insert_before, np)
-           end
-           insert_skip = after_wchar
-        elseif first_char then
-           if insert_skip==after_wchar then
-              insert_kanji_ascii_xkskip(nq, first_char)
-           end
-           set_insert_skip_after_achar(first_char)
-        end
-        -- last char
-        if is_japanese_glyph_node(last_char) then
-           insert_skip = after_wchar
-           nrc = last_char.char; nrf = last_char.font
-           nr_spc = { has_attr(last_char, attr_autospc)==1, 
-                      has_attr(last_char, attr_autoxspc)==1 }
-           if is_japanese_glyph_node(node_next(np)) then
-              insert_kanji_skip(node_insert_after, np)
-           end
-        elseif last_char then
-           set_insert_skip_after_achar(last_char)
-           nr_spc = { has_attr(last_char, attr_autospc)==1, 
-                      has_attr(last_char, attr_autoxspc)==1 }
-        else insert_skip = no_skip
-        end
-      else insert_skip = no_skip
-      end
-   else insert_skip = no_skip
-   end
-   nq = np
-end
-
--- When np is a penalty ...
-local function insks_around_penalty()
-   nq = np
-end
-
--- When np is a kern ...
--- 
-local function insks_around_kern()
-   if np.subtype==1 then -- \kern or \/
-      local i = has_attr(np, attr_icflag)
-      if not i or i==FROM_JFM then -- \kern
-        insert_skip = no_skip
-      elseif i==ITALIC or i==LINE_END or i==TEMPORARY then
-        nq = np
-      end
-   elseif np.subtype==2 then 
-      -- (np = kern from \accent) .. (accent char) .. (kern from \accent) .. (glyph)
-      np = node_next(node_next(np))
-   else  -- kern from TFM
-      nq = np
-   end
-end
-
--- When np is a math_node ...
-local function insks_around_math()
-   local g = { char = -1 }
-   if (np.subtype==0) and (insert_skip==after_wchar) then
-      insert_kanji_ascii_xkskip(nq, g)
-      insert_skip = no_skip
-   else
-      nq = np; set_insert_skip_after_achar(g); nr_spc = np_spc
-   end
-end
-
-function ltj.int_insert_kanji_skip(ahead)
-   kanji_skip=skip_table_to_spec('kanjiskip')
-   xkanji_skip=skip_table_to_spec('xkanjiskip')
-   head = ahead
-   np = head; nq = nil; insert_skip = no_skip
-   while np do
-      np_spc = { (has_attr(np, attr_autospc)==1), 
-                (has_attr(np, attr_autoxspc)==1) }
-      if np.id==id_glyph then
-        repeat 
-           np_spc = { has_attr(np, attr_autospc)==1, 
-                      has_attr(np, attr_autoxspc)==1 }
-           insks_around_char(); np=node_next(np)
-        until (not np) or np.id~=id_glyph
-      else
-        if np.id==id_hlist then
-           insks_around_hbox()
-        elseif np.id==id_penalty then
-           insks_around_penalty()
-        elseif np.id==id_kern then
-           insks_around_kern()
-        elseif np.id==id_math then
-           insks_around_math()
-        elseif np.id==id_ins    or np.id==id_mark
-             or np.id==id_adjust or np.id==id_whatsit then
-           -- do nothing
-           np = np
-        else
-           -- rule, disc, glue, margin_kern
-           insert_skip = no_skip
-        end
-        np = node_next(np)
-      end
-   end
-   return head
-end
\ No newline at end of file
index be7bbb6..d69d74f 100644 (file)
@@ -10,7 +10,7 @@ luatexbase.provides_module({
 module('luatexja.charrange', package.seeall)
 local err, warn, info, log = luatexbase.errwarinf(_NAME)
 
-local ltjb = luatexja.base
+require('luatexja.base');      local ltjb = luatexja.base
 
 local floor = math.floor
 local has_attr = node.has_attribute
index b6916d4..7b4e3fa 100644 (file)
@@ -10,8 +10,8 @@ luatexbase.provides_module({
 module('luatexja.compat', package.seeall)
 local err, warn, info, log = luatexbase.errwarinf(_NAME)
 
-local ltjb = luatexja.base
-local ltjs = luatexja.stack
+require('luatexja.base');      local ltjb = luatexja.base
+require('luatexja.stack');     local ltjs = luatexja.stack
 
 -- \kuten, \jis, \euc, \sjis, \ucs, \kansuji
 function to_kansuji(num)
index 09f35dd..9ba3d82 100644 (file)
@@ -10,7 +10,7 @@ luatexbase.provides_module({
 module('luatexja.inputbuf', package.seeall)
 local err, warn, info, log = luatexbase.errwarinf(_NAME)
 
-local ltjc = luatexja.charrange
+require('luatexja.charrange'); local ltjc = luatexja.charrange
 
 local node_new = node.new
 local id_glyph = node.id('glyph')
diff --git a/src/luatexja/jfmglue.lua b/src/luatexja/jfmglue.lua
new file mode 100644 (file)
index 0000000..1cb9db7
--- /dev/null
@@ -0,0 +1,828 @@
+--
+-- luatexja/jfmglue.lua
+--
+luatexbase.provides_module({
+  name = 'luatexja.jfmglue',
+  date = '2011/06/27',
+  version = '0.2',
+  description = 'Insertion process of JFM glues and kanjiskip',
+})
+module('luatexja.jfmglue', package.seeall)
+local err, warn, info, log = luatexbase.errwarinf(_NAME)
+
+require('luatexja.base');      local ltjb = luatexja.base
+require('luatexja.stack');     local ltjs = luatexja.stack
+require('luatexja.jfont');     local ltjf = luatexja.jfont
+require('luatexja.pretreat');  local ltjp = luatexja.pretreat
+
+local node_type = node.type
+local node_new = node.new
+local node_remove = node.remove
+local node_prev = node.prev
+local node_next = node.next
+local node_copy = node.copy
+local node_tail = node.tail
+local node_free = node.free
+local has_attr = node.has_attribute
+local set_attr = node.set_attribute
+local node_insert_before = node.insert_before
+local node_insert_after = node.insert_after
+local round = tex.round
+
+local id_glyph = node.id('glyph')
+local id_hlist = node.id('hlist')
+local id_vlist = node.id('vlist')
+local id_rule = node.id('rule')
+local id_ins = node.id('ins')
+local id_mark = node.id('mark')
+local id_adjust = node.id('adjust')
+local id_disc = node.id('disc')
+local id_whatsit = node.id('whatsit')
+local id_math = node.id('math')
+local id_glue = node.id('glue')
+local id_kern = node.id('kern')
+local id_penalty = node.id('penalty')
+
+local id_glue_spec = node.id('glue_spec')
+local id_jglyph = node.id('glyph') + 256
+local id_box_like = node.id('hlist') + 256
+local id_pbox = node.id('hlist') + 512
+local sid_user = node.subtype('user_defined')
+
+local ITALIC = 1
+local PACKED = 2
+local KINSOKU = 3
+local FROM_JFM = 4
+local LINE_END = 5
+local KANJI_SKIP = 6
+local XKANJI_SKIP = 7
+local PROCESSED = 8
+local IC_PROCESSED = 9
+local BOXBDD = 15
+
+local kanji_skip
+local xkanji_skip
+
+local attr_jchar_class = luatexbase.attributes['ltj@charclass']
+local attr_curjfnt = luatexbase.attributes['ltj@curjfnt']
+local attr_icflag = luatexbase.attributes['ltj@icflag']
+local attr_autospc = luatexbase.attributes['ltj@autospc']
+local attr_autoxspc = luatexbase.attributes['ltj@autoxspc']
+local max_dimen = 1073741823
+
+
+
+-------------------- Helper functions
+
+local function find_char_class(c,m)
+   return m.chars[c] or 0
+end
+
+local function get_zero_glue()
+   local g = node_new(id_glue_spec)
+   g.width = 0; g.stretch_order = 0; g.stretch = 0
+   g.shrink_order = 0; g.shrink = 0
+   return g
+end
+
+local function skip_table_to_spec(n)
+   local g = node_new(id_glue_spec)
+   local st = ltjs.get_skip_table(n, ltjp.box_stack_level)
+   g.width = st.width; g.stretch = st.stretch; g.shrink = st.shrink
+   g.stretch_order = st.stretch_order; g.shrink_order = st.shrink_order
+   return g
+end
+
+-- penalty 値の計算
+local function add_penalty(p,e)
+   if p.penalty>=10000 then
+      if e<=-10000 then p.penalty = 0 end
+   elseif p.penalty<=-10000 then
+      if e>=10000 then p.penalty = 0 end
+   else
+      p.penalty = p.penalty + e
+      if p.penalty>=10000 then p.penalty = 10000
+      elseif p.penalty<=-10000 then p.penalty = -10000 end
+   end
+   return
+end
+
+-- 「異なる JFM」の間の調整方法
+diffmet_rule = math.two_average
+function math.two_add(a,b) return a+b end
+function math.two_average(a,b) return (a+b)/2 end
+
+-------------------- idea
+-- 2 node の間に glue/kern/penalty を挿入する.
+-- 基本方針: char node q と char node p の間
+
+--  Np: 「p を核とする塊」
+--   first: 最初の node,nuc: p,last: 最後の node
+--   id: 核 node の種類
+--  Nq: 「q を核とする塊」
+--   実際の glue は Np.last, Nq.first の間に挿入される
+--  Bp: Np.last, Nq.first の間の penalty node 達の配列
+
+-- 核の定義:
+--  node x が non-char node のときは,x のみ
+--  x が char_node のときは,
+--  - x が \accent の第二引数だったとき
+--    [kern2 kern y kern2] x の 3 node が核に加わる
+--  - x の直後に \/ 由来 kern があったとき
+--    その \/ 由来の kern が核に加わる
+-- p, q の走査で無視するもの:
+--  ins, mark, adjust, whatsit, penalty
+--
+-- Nq.last .. + .. Bp.first .... Bp[last] .... * .. Np.first
+-- +: kern from LINEEND はここに入る
+-- *: jfm glue はここに入る
+
+local head -- the head of current list
+local last -- the last node of current list
+local lp   -- 外側での list 走査時のカーソル
+
+local Np, Nq, Bp
+local widow_Bp, widow_Np -- \jcharwidowpenalty 挿入位置管理用
+
+local ihb_flag -- JFM グルー挿入抑止用 flag
+               -- on: \inhibitglue 指定時,hlist の周囲
+
+-------------------- hlist 内の文字の検索
+
+local first_char, last_char, find_first_char
+
+local function check_box(box_ptr, box_end)
+   local p = box_ptr; local found_visible_node = false
+   if not p then 
+      find_first_char = false; first_char = nil; last_char = nil
+      return true
+   end
+   while p and p~=box_end do
+      local pid = p.id
+      if pid==id_kern then
+        if p.subtype==2 then
+           p = node_next(node_next(node_next(p))); pid = p.id
+        elseif has_attr(p, attr_icflag)==IC_PROCESSED then
+           p = node_next(p); pid = p.id
+        end
+      end
+      if pid==id_glyph then
+        repeat 
+           if find_first_char then 
+              first_char = p; find_first_char = false
+           end
+           last_char = p; found_visible_node = true; p=node_next(p)
+           if (not p) or p==box_end then return found_visible_node end
+        until p.id~=id_glyph
+      end
+      if pid==id_hlist then
+        if has_attr(p, attr_icflag)==PACKED then
+           for q in node.traverse_id(id_glyph, p.head) do
+              if find_first_char then
+                 first_char = q; find_first_char = false
+              end
+              last_char = q; found_visible_node = true; break
+           end
+        else
+           if p.shift==0 then
+              if check_box(p.head, nil) then found_visible_node = true end
+           else if find_first_char then 
+                 find_first_char = false
+              else 
+                 last_char = nil
+              end
+           end
+        end
+      elseif not (pid==id_ins   or pid==id_mark
+                 or pid==id_adjust or pid==id_whatsit
+                 or pid==id_penalty) then
+        found_visible_node = true
+        if find_first_char then 
+           find_first_char = false
+        else 
+           last_char = nil
+        end
+      end
+      p = node_next(p)
+   end
+   return found_visible_node
+end 
+
+-------------------- Np の計算と情報取得
+-- calc next Np
+local function set_attr_icflag_processed(p)
+   local a = has_attr(p, attr_icflag) or 0
+   if a<=1 then set_attr(p, attr_icflag, PROCESSED) end
+end
+
+local function check_next_ickern()
+   if lp.id == id_kern and has_attr(lp, attr_icflag)==ITALIC then
+      set_attr(lp, attr_icflag, IC_PROCESSED); Np.last = lp; lp = node_next(lp)
+   else Np.last = Np.nuc end
+end
+
+local function calc_np_pbox()
+   Np.first = lp; Np.id = id_pbox
+   lpa = KINSOKU -- dummy
+   while lp~=last and lpa>=PACKED and lpa~=BOXBDD do
+      Np.nuc = lp; lp = node_next(lp); lpa = has_attr(lp, attr_icflag) or 0
+   end
+   check_next_ickern()
+end
+
+local function calc_np()
+   -- We assume lp = node_next(Np.last)
+   local pBp = Bp; local lpi, lpa
+   Nq = Np; Bp = {}; Bp[0] = 0; Np = {}; ihb_flag = false 
+   while true do
+      lpi = lp.id; lpa = has_attr(lp, attr_icflag) or 0
+      if lp==last then Np = nil; return
+      elseif lpa>=PACKED then
+        if lpa == BOXBDD then
+           local lq = node_next(lp)
+           head = node_remove(head, lp); lp = lq
+        else calc_np_pbox(); return end -- id_pbox
+      elseif lpi == id_ins or lpi == id_mark or lpi == id_adjust then
+        set_attr_icflag_processed(lp); lp = node_next(lp)
+      elseif lpi == id_penalty then
+        table.insert(Bp, lp); Bp[0] = Bp[0] + 1
+        set_attr_icflag_processed(lp); lp = node_next(lp)
+      elseif lpi == id_whatsit then
+        if lp.subtype==sid_user and lp.user_id==30111 then
+           local lq = node_next(lp)
+           head = node_remove(head, lp); lp = lq; ihb_flag = true
+        else
+           set_attr_icflag_processed(lp); lp = node_next(lp)
+        end
+      else -- a `cluster' is found
+        Np.first = lp
+        if lpi == id_glyph then -- id_[j]glyph
+           if lp.font == has_attr(lp, attr_curjfnt) then Np.id = id_jglyph 
+           else Np.id = id_glyph end
+           Np.nuc = lp; set_attr_icflag_processed(lp)
+           lp = node_next(lp); check_next_ickern(); return
+        elseif lpi == id_hlist then -- hlist
+           Np.last = lp; Np.nuc = lp; set_attr_icflag_processed(lp)
+           if lp.shift~=0 then Np.id = id_box_like
+           else Np.id = lpi end
+           lp = node_next(lp); return
+        elseif lpi == id_vlist or lpi == id_rule then -- id_box_like
+           Np.nuc = lp; Np.last = lp; Np.id = id_box_like; break
+        elseif lpi == id_math then -- id_math
+           Np.nuc = lp
+           while lp.id~=id_math do 
+              set_attr_icflag_processed(lp); lp  = node_next(lp) 
+           end; break
+        elseif lpi == id_kern and lp.subtype==2 then -- id_kern
+           set_attr_icflag_processed(lp); lp = node_next(lp)
+           set_attr_icflag_processed(lp); lp = node_next(lp)
+           set_attr_icflag_processed(lp); lp = node_next(lp)
+           set_attr_icflag_processed(lp); Np.nuc = lp
+           if lp.font == has_attr(lp, attr_curjfnt) then Np.id = id_jglyph 
+           else Np.id = id_glyph end
+           lp = node_next(lp); check_next_ickern(); return
+        else -- id_disc, id_glue, id_kern
+           Np.nuc = lp; break
+        end
+      end
+   end
+   set_attr_icflag_processed(lp); Np.last = lp; Np.id = lpi; lp = node_next(lp)
+end
+
+-- extract informations from Np
+-- We think that "Np is a Japanese character" if Np.met~=nil,
+--            "Np is an alphabetic character" if Np.pre~=nil,
+--            "Np is not a character" otherwise.
+
+-- 和文文字のデータを取得
+local function set_np_xspc_jachar(c,x)
+   Np.class = has_attr(x, attr_jchar_class)
+   Np.char = c
+   local z = ltjf.font_metric_table[x.font]
+   Np.size= z.size
+   Np.met = ltjf.metrics[z.jfm]
+   Np.var = z.var
+   Np.pre = ltjs.get_penalty_table('pre', c, 0, ltjp.box_stack_level)
+   Np.post = ltjs.get_penalty_table('post', c, 0, ltjp.box_stack_level)
+   z = find_char_class('lineend', Np.met)
+   local y = Np.met.char_type[Np.class]
+   if y.kern and y.kern[z] then 
+      Np.lend = round(Np.size*y.kern[z]) 
+   else 
+      Np.lend = 0 
+   end
+   y = ltjs.get_penalty_table('xsp', c, 3, ltjp.box_stack_level)
+   Np.xspc_before = (y>=2)
+   Np.xspc_after  = (y%2==1)
+   Np.auto_kspc = (has_attr(x, attr_autospc)==1)
+   Np.auto_xspc = (has_attr(x, attr_autoxspc)==1)
+end
+
+-- 欧文文字のデータを取得
+local ligature_head = 1
+local ligature_tail = 2
+local function set_np_xspc_alchar(c,x, lig)
+   if c~=-1 then
+      if lig == ligature_head then
+        while x.components and x.subtype and math.floor(x.subtype/2)%2==1 do
+           x = x.components; c = x.char
+        end
+      else
+        while x.components and x.subtype and math.floor(x.subtype/2)%2==1 do
+           x = node_tail(x.components); c = x.char
+        end
+      end
+      Np.pre = ltjs.get_penalty_table('pre', c, 0, ltjp.box_stack_level)
+      Np.post = ltjs.get_penalty_table('post', c, 0, ltjp.box_stack_level)
+   else
+      Np.pre = 0; Np.post = 0
+   end
+   Np.met = nil
+   local y = ltjs.get_penalty_table('xsp', c, 3, ltjp.box_stack_level)
+   Np.xspc_before = (y%2==1)
+   Np.xspc_after  = (y>=2)
+   Np.auto_xspc = (has_attr(x, attr_autoxspc)==1)
+end
+
+-- Np の情報取得メインルーチン
+local function extract_np()
+   local x = Np.nuc
+   if Np.id ==  id_jglyph then
+      set_np_xspc_jachar(x.char, x)
+   elseif Np.id == id_glyph then
+      set_np_xspc_alchar(x.char, x, ligature_head)
+   elseif Np.id == id_hlist then
+      find_first_char = true; first_char = nil; last_char = nil
+      if check_box(x.head, nil) then
+        if first_char then
+           if first_char.font == has_attr(first_char, attr_curjfnt) then 
+              set_np_xspc_jachar(first_char.char,first_char)
+           else
+              set_np_xspc_alchar(first_char.char,first_char, ligature_head)
+           end
+        end
+      end
+   elseif Np.id == id_pbox then --  mikann 
+      find_first_char = true; first_char = nil; last_char = nil
+      if check_box(Np.first, node_next(Np.last)) then
+        if first_char then
+           if first_char.font == has_attr(first_char, attr_curjfnt) then 
+              set_np_xspc_jachar(first_char.char,first_char)
+           else
+              set_np_xspc_alchar(first_char.char,first_char, ligature_head)
+           end
+        end
+      end
+   elseif Np.id == id_disc then 
+      find_first_char = true; first_char = nil; last_char = nil
+      if check_box(x.replace, nil) then
+        if first_char then
+           if first_char.font == has_attr(first_char, attr_curjfnt) then 
+              set_np_xspc_jachar(first_char.char,first_char)
+           else
+              set_np_xspc_alchar(first_char.char,first_char, ligature_head)
+           end
+        end
+      end
+   elseif Np.id == id_math then
+      set_np_xspc_alchar(-1, x)
+   end
+end
+
+-- change the information for the next loop
+-- (will be done if Np is an alphabetic character or a hlist)
+local function after_hlist()
+   if last_char then
+      if last_char.font == has_attr(last_char, attr_curjfnt) then 
+        set_np_xspc_jachar(last_char.char,last_char, ligature_after)
+      else
+        set_np_xspc_alchar(last_char.char,last_char, ligature_after)
+      end
+   else
+      Np.pre = nil; Np.met = nil
+   end
+end
+local function after_alchar()
+   local x = Np.nuc
+   set_np_xspc_alchar(x.char,x, ligature_after)
+end
+
+
+-------------------- 最下層の処理
+
+local function lineend_fix(g)
+   if g and g.id==id_kern then 
+      Nq.lend = 0
+   elseif Nq.lend and Nq.lend~=0 then
+      if not g then
+        g = node_new(id_kern); g.subtype = 1
+        g.kern = -Nq.lend; set_attr(g, attr_icflag, LINEEND)
+      elseif g.id==id_kern then
+        g.kern = g.kern - Nq.lend
+      else
+        g.spec.width = g.spec.width - Nq.lend
+      end
+   end
+   return g
+end
+
+-- change penalties (or create a new penalty, if needed)
+local function handle_penalty_normal(post, pre, g)
+   local a = (pre or 0) + (post or 0)
+   if Bp[0] == 0 then
+      if (a~=0 and not(g and g.id==id_kern)) or (Nq.lend and Nq.lend~=0) then
+        local p = node_new(id_penalty)
+        if a<-10000 then a = -10000 elseif a>10000 then a = 10000 end
+        p.penalty = a
+        head = node_insert_before(head, Np.first, p)
+        Bp[1] = p; Bp[0] = 1; set_attr(p, attr_icflag, KINSOKU)
+      end
+   else for i, v in ipairs(Bp) do add_penalty(v,a) end
+   end
+end
+
+local function handle_penalty_always(post, pre, g)
+   local a = (pre or 0) + (post or 0)
+   if Bp[0] == 0 then
+      if not (g and g.id==id_glue) or (Nq.lend and Nq.lend~=0) then
+        local p = node_new(id_penalty)
+        if a<-10000 then a = -10000 elseif a>10000 then a = 10000 end
+        p.penalty = a
+        head = node_insert_before(head, Np.first, p)
+        Bp[1] = p; Bp[0] = 1; set_attr(p, attr_icflag, KINSOKU)
+      end
+   else for i, v in ipairs(Bp) do add_penalty(v,a) end
+   end
+end
+
+local function handle_penalty_suppress(post, pre, g)
+   local a = (pre or 0) + (post or 0)
+   if Bp[0] == 0 then
+      if g and g.id==id_glue then
+        local p = node_new(id_penalty)
+        p.penalty = 10000; head = node_insert_before(head, Np.first, p)
+        Bp[1] = p; Bp[0] = 1; set_attr(p, attr_icflag, KINSOKU)
+      end
+   else for i, v in ipairs(Bp) do add_penalty(v,a) end
+   end
+end
+
+-- 和文文字間の JFM glue を node 化
+local function new_jfm_glue(Nn, bc, ac)
+-- bc, ac: char classes
+   local g = nil
+   local z = Nn.met.char_type[bc]
+   if z.glue and z.glue[ac] then
+      local h = node_new(id_glue_spec)
+      h.width   = round(Nn.size*z.glue[ac][1])
+      h.stretch = round(Nn.size*z.glue[ac][2])
+      h.shrink  = round(Nn.size*z.glue[ac][3])
+      h.stretch_order=0; h.shrink_order=0
+      g = node_new(id_glue)
+      g.subtype = 0; g.spec = h
+   elseif z.kern and z.kern[ac] then
+      g = node_new(id_kern)
+      g.subtype = 1; g.kern = round(Nn.size*z.kern[ac])
+   end
+   if g then set_attr(g, attr_icflag, FROM_JFM) end
+   return g
+end
+
+-- Nq.last (kern w) .... (glue/kern g) Np.first
+local function real_insert(w, g)
+   if w~=0 then
+      local h = node_new(id_kern)
+      set_attr(h, attr_icflag, LINE_END)
+      h.kern = Nq.lend; h.subtype = 1
+      head = node_insert_after(head, Nq.last, h)
+   end
+   if g then
+      head = node_insert_before(head, Np.first, g)
+      Np.first = g
+   end
+end
+
+-------------------- 和文文字間空白量の決定
+
+-- get kanjiskip
+local function get_kanji_skip_from_jfm(Nn)
+   local i = Nn.met.kanjiskip
+   if i then
+      return { round(i[1]*Nn.size), round(i[2]*Nn.size), round(i[3]*Nn.size) }
+   else return nil
+   end
+end
+local function get_kanjiskip()
+   local g = node_new(id_glue)
+   if Np.auto_kspc or Nq.auto_kspc then
+      if kanji_skip.width == max_dimen then
+        local gx = node_new(id_glue_spec);
+        gx.stretch_order = 0; gx.shrink_order = 0
+        local bk = get_kanji_skip_from_jfm(Nq)
+        local ak
+        if (Np.met==Nq.met) and (Nq.size==Np.size) and (Nq.var==Np.var) then
+           ak = nil
+        else
+           ak = get_kanji_skip_from_jfm(Np)
+        end
+        if bk then
+           if ak then
+              gx.width = round(diffmet_rule(bk[1], ak[1]))
+              gx.stretch = round(diffmet_rule(bk[2], ak[2]))
+              gx.shrink = -round(diffmet_rule(-bk[3], -ak[3]))
+           else
+              gx.width = bk[1]; gx.stretch = bk[2]; gx.shrink = bk[3]
+           end
+        elseif ak then
+           gx.width = ak[1]; gx.stretch = ak[2]; gx.shrink = ak[3]
+        else gx = get_zero_glue() -- fallback
+        end
+        g.spec = gx
+      else g.spec=node_copy(kanji_skip) end
+   else
+      local gx = get_zero_glue()
+      g.spec = gx
+   end
+   set_attr(g, attr_icflag, KANJI_SKIP)
+   return g
+end
+
+local function calc_ja_ja_aux(gb,ga)
+   if not gb then 
+      return ga
+   else
+      if not ga then return gb end
+      local k = node.type(gb.id) .. node.type(ga.id)
+      if k == 'glueglue' then 
+        -- 両方とも glue.
+        gb.spec.width   = round(diffmet_rule(gb.spec.width, ga.spec.width))
+        gb.spec.stretch = round(diffmet_rule(gb.spec.stretch,ga.spec.shrink))
+        gb.spec.shrink  = -round(diffmet_rule(-gb.spec.shrink, -ga.spec.shrink))
+        node_free(ga)
+        return gb
+      elseif k == 'kernkern' then
+        -- 両方とも kern.
+        gb.kern = round(diffmet_rule(gb.kern, ga.kern))
+        node_free(ga)
+        return gb
+      elseif k == 'kernglue' then 
+        -- gb: kern, ga: glue
+        ga.spec.width   = round(diffmet_rule(gb.kern,ga.spec.width))
+        ga.spec.stretch = round(diffmet_rule(ga.spec.stretch, 0))
+        ga.spec.shrink  = -round(diffmet_rule(-ga.spec.shrink, 0))
+        node_free(gb)
+        return ga
+      else
+        -- gb: glue, ga: kern
+        gb.spec.width   = round(diffmet_rule(ga.kern, gb.spec.width))
+        gb.spec.stretch = round(diffmet_rule(gb.spec.stretch, 0))
+        gb.spec.shrink  = -round(diffmet_rule(-gb.spec.shrink, 0))
+        node_free(ga)
+        return gb
+      end
+   end
+end
+
+local function calc_ja_ja_glue()
+   if  ihb_flag then return nil
+   elseif (Nq.size==Np.size) and (Nq.met==Np.met) and (Nq.var==Np.var) then
+      return new_jfm_glue(Nq, Nq.class, Np.class)
+   else
+      local g = new_jfm_glue(Nq, Nq.class,
+                            find_char_class('diffmet',Nq.met))
+      local h = new_jfm_glue(Np, find_char_class('diffmet',Np.met),
+                            Np.class)
+      return calc_ja_ja_aux(g,h)
+   end
+end
+
+-------------------- 和欧文間空白量の決定
+
+-- get xkanjiskip
+local function get_xkanji_skip_from_jfm(Nn)
+   local i = Nn.met.xkanjiskip
+   if i then
+      return { round(i[1]*Nn.size), round(i[2]*Nn.size), round(i[3]*Nn.size) }
+   else return nil
+   end
+end
+local function get_xkanjiskip(Nn)
+   local g = node_new(id_glue)
+   if Nq.xspc_after and Np.xspc_before and (Nq.auto_xspc or Np.auto_xspc) then
+      if xkanji_skip.width == max_dimen then
+        local gx = node_new(id_glue_spec);
+        gx.stretch_order = 0; gx.shrink_order = 0
+        local bk = get_xkanji_skip_from_jfm(Nn)
+        if bk then
+           gx.width = bk[1]; gx.stretch = bk[2]; gx.shrink = bk[3]
+        else gx = get_zero_glue() -- fallback
+        end
+        g.spec = gx
+      else g.spec=node_copy(xkanji_skip) end
+   else
+      local gx = get_zero_glue()
+      g.spec = gx
+   end
+   set_attr(g, attr_icflag, XKANJI_SKIP)
+   return g
+end
+
+
+-------------------- 隣接した「塊」間の処理
+
+local function get_OA_skip()
+   if not ihb_flag then
+      return new_jfm_glue(Np, find_char_class('jcharbdd',Np.met), Np.class)
+   else return nil
+   end
+end
+local function get_OB_skip()
+   if not ihb_flag then
+      return new_jfm_glue(Nq, Nq.class, find_char_class('jcharbdd',Nq.met))
+   else return nil
+   end
+end
+
+-- (anything) .. jachar
+local function handle_np_jachar()
+   local g = nil
+   if Nq.id==id_jglyph or (Nq.id==id_pbox and Nq.met) then 
+      g = calc_ja_ja_glue() or get_kanjiskip() -- M->K
+      g = lineend_fix(g)
+      handle_penalty_normal(Nq.post, Np.pre, g); real_insert(Nq.lend, g)
+   elseif Nq.met then  -- Nq.id==id_hlist
+      g = get_OA_skip() or get_kanjiskip() -- O_A->K
+      handle_penalty_normal(0, Np.pre, g); real_insert(0, g)
+   elseif Nq.pre then 
+      g = get_OA_skip() or get_xkanjiskip(Np) -- O_A->X
+      handle_penalty_normal(Nq.post, Np.pre, g); real_insert(0, g)
+   else
+      g = get_OA_skip() -- O_A
+      if Nq.id==id_glue then handle_penalty_normal(0, Np.pre, g)
+      elseif Nq.id==id_kern then handle_penalty_suppress(0, Np.pre, g)
+      else handle_penalty_always(0, Np.pre, g)
+      end
+      real_insert(0, g)
+   end
+   -- \jcharwidowpenalty 挿入予定箇所更新
+   if ltjs.get_penalty_table('kcat', Np.char, 0, ltjp.box_stack_level)%2~=1 then
+      widow_Np = Np; widow_Bp = Bp
+   end
+end
+
+-- jachar .. (anything)
+local function handle_nq_jachar()
+   local g = nil
+   if Np.pre then 
+      g = get_OB_skip() or get_xkanjiskip(Nq) -- O_B->X
+      g = lineend_fix(g)
+      handle_penalty_normal(Nq.post, Np.pre, g); real_insert(Nq.lend, g)
+   else
+      g = get_OB_skip(); g = lineend_fix(g) -- O_B
+      if Np.id==id_glue then handle_penalty_normal(Nq.post, 0, g)
+      elseif Np.id==id_kern then handle_penalty_suppress(Nq.post, 0, g)
+      else handle_penalty_always(Nq.post, 0, g)
+      end
+      real_insert(Nq.lend, g)
+   end
+end
+
+-- (anything) .. (和文文字で終わる hlist)
+local function handle_np_ja_hlist()
+   local g = nil
+   if Nq.id==id_jglyph or (Nq.id==id_pbox and Nq.met) then 
+      g = get_OB_skip() or get_kanjiskip() -- O_B->K
+      g = lineend_fix(g)
+      handle_penalty_normal(Nq.post, 0, g); real_insert(Nq.lend, g)
+   elseif Nq.met then  -- Nq.id==id_hlist
+      g = get_kanjiskip() -- K
+      handle_penalty_suppress(0, 0, g); real_insert(0, g)
+   elseif Nq.pre then 
+      g = get_xkanjiskip(Np) -- X
+      handle_penalty_suppress(0, 0, g); real_insert(0, g)
+   end
+end
+
+-- (和文文字で終わる hlist) .. (anything)
+local function handle_nq_ja_hlist()
+   local g = nil
+   if Np.pre then 
+      g = get_xkanjiskip(Nq) -- X
+      handle_penalty_suppress(0, 0, g); real_insert(0, g)
+   end
+end
+
+-------------------- 開始・終了時の処理
+
+-- リスト末尾の処理
+local function handle_list_tail()
+   Np = Nq
+   if mode then
+      -- the current list is to be line-breaked:
+      if Np.id == id_jglyph or (Np.id==id_pbox and Np.met) then 
+        if Np.lend~=0 then
+           g = node_new(id_kern); g.subtype = 0; g.kern = Np.lend
+           set_attr(g, attr_icflag, BOXBDD)
+           node_insert_after(head, Np.last, g)
+        end
+      end
+      -- Insert \jcharwidowpenalty
+      Bp = widow_Bp; Np = widow_Np
+      if Np then
+        handle_penalty_normal(0,
+                              ltjs.get_penalty_table('jwp', 0, 0, ltjp.box_stack_level))
+      end
+   else
+      -- the current list is the contents of a hbox
+      if Np.id == id_jglyph or (Np.id==id_pbox and Np.met) then 
+        local g = new_jfm_glue(Np, Np.class, find_char_class('boxbdd',Np.met))
+        if g then
+           set_attr(g, attr_icflag, BOXBDD)
+           head = node_insert_after(head, Np.last, g)
+        end
+      end
+      head = node_remove(head, last) -- remove the sentinel
+   end
+end
+
+-- リスト先頭の処理
+local function handle_list_head()
+   if Np.id ==  id_jglyph or (Np.id==id_pbox and Np.met) then 
+      local g = new_jfm_glue(Np, find_char_class('boxbdd',Np.met), Np.class)
+      if g then
+        set_attr(g, attr_icflag, BOXBDD)
+        if g.id==id_glue and Bp[0]==0 then
+           local h = node_new(id_penalty)
+           h.penalty = 10000; set_attr(h, attr_icflag, BOXBDD)
+        end
+        head = node_insert_before(head, Np.first, g)
+      end
+   end
+end
+
+-- initialize
+local function init_var()
+   lp = head; widow_Bp = nil; widow_Np = nil
+   kanji_skip=skip_table_to_spec('kanjiskip')
+   xkanji_skip=skip_table_to_spec('xkanjiskip')
+   if mode then 
+      -- the current list is to be line-breaked:
+      -- hbox from \parindent is skipped.
+      while lp and (lp.id==id_whatsit or ((lp.id==id_hlist) and (lp.subtype==3))) do
+        lp=node_next(lp) end
+      last=node.tail(head)
+   else 
+      -- the current list is the contents of a hbox:
+      -- insert a sentinel
+      last=node.tail(head); local g = node_new(id_kern)
+      node_insert_after(head, last, g); last = g
+   end
+end
+
+-------------------- 外部から呼ばれる関数
+
+-- main interface
+function main(ahead, amode)
+   if not ahead then return ahead end
+   head = ahead; mode = amode; init_var(); calc_np()
+   if Np then 
+      extract_np(); handle_list_head()
+      if Np.id==id_glyph then after_alchar()
+      elseif Np.id==id_hlist or Np.id==id_pbox or Np.id==id_disc then after_hlist()
+      end
+   else
+      if not mode then head = node_remove(head, last) end
+      return head
+   end
+   calc_np()
+   while Np do
+      extract_np()
+      -- 挿入部
+      if Np.id == id_jglyph then 
+        handle_np_jachar()
+      elseif Np.met then 
+        if Np.id==id_hlist then handle_np_ja_hlist()
+        else handle_np_jachar() end
+      elseif Nq.met then 
+        if Nq.id==id_hlist then handle_nq_ja_hlist()
+        else handle_nq_jachar() end
+      end
+      -- Np の後処理
+      if Np.id==id_glyph then after_alchar()
+      elseif Np.id==id_hlist or Np.id==id_pbox or Np.id==id_disc then after_hlist()
+      end
+      calc_np()
+   end
+   handle_list_tail()
+   -- adjust attr_icflag
+   tex.attribute[attr_icflag] = -(0x7FFFFFFF)
+   return head
+end
+
+-- \inhibitglue
+function create_inhibitglue_node()
+   local g=node_new(id_whatsit, sid_user)
+   g.user_id=30111; g.type=100; g.value=1; node.write(g)
+end
+
+-- TODO: 二重挿入の回避
similarity index 76%
rename from src/luatexja-jfont.lua
rename to src/luatexja/jfont.lua
index 81c35b6..61a3af6 100644 (file)
@@ -1,5 +1,16 @@
-local ltjb = luatexja.base
-local ltjc = luatexja.charrange
+--
+-- luatexja/jfont.lua
+--
+luatexbase.provides_module({
+  name = 'luatexja.jfont',
+  date = '2011/06/27',
+  version = '0.1',
+  description = 'Loader for Japanese fonts',
+})
+module('luatexja.jfont', package.seeall)
+
+require('luatexja.base');      local ltjb = luatexja.base
+require('luatexja.charrange'); local ltjc = luatexja.charrange
 
 local node_new = node.new
 local has_attr = node.has_attribute
@@ -12,16 +23,16 @@ local id_kern = node.id('kern')
 
 local ITALIC = 1
 ------------------------------------------------------------------------
--- LOADING JFM (prefix: ljfm)
+-- LOADING JFM
 ------------------------------------------------------------------------
 
-ltj.metrics={} -- this table stores all metric informations
-ltj.font_metric_table={} -- [font number] -> jfm_name, jfm_var, size
+metrics={} -- this table stores all metric informations
+font_metric_table={} -- [font number] -> jfm_name, jfm_var, size
 
 local jfm_file_name, jfm_var
 local defjfm_res
 
-function ltj.define_jfm(t)
+function define_jfm(t)
    local real_char -- Does current character class have the 'real' character?
    if t.dir~='yoko' then
       defjfm_res= nil; return
@@ -71,14 +82,13 @@ function ltj.define_jfm(t)
    defjfm_res= t
 end
 
-local function ljfm_find_char_class(c,m)
+function find_char_class(c,m)
 -- c: character code, m
-   if not ltj.metrics[m] then return 0 end
-   return ltj.metrics[m].chars[c] or 0
+   if not metrics[m] then return 0 end
+   return metrics[m].chars[c] or 0
 end
-ltj.int_find_char_class = ljfm_find_char_class
 
-local function ljfm_load_jfont_metric()
+local function load_jfont_metric()
    if jfm_file_name=='' then 
       ltjb.package_error('luatexja',
                         'no JFM specified',
@@ -86,14 +96,14 @@ local function ljfm_load_jfont_metric()
                          "The JFM 'ujis' will be  used for now."})
       jfm_file_name='ujis'
    end
-   for j,v in ipairs(ltj.metrics) do 
+   for j,v in ipairs(metrics) do 
       if v.name==jfm_file_name then return j end
    end
    ltj.loadlua('jfm-' .. jfm_file_name .. '.lua')
    if defjfm_res then
       defjfm_res.name = jfm_file_name
-      table.insert(ltj.metrics,defjfm_res)
-      return #ltj.metrics
+      table.insert(metrics, defjfm_res)
+      return #metrics
    else 
       return nil
    end
@@ -101,12 +111,12 @@ end
 
 
 ------------------------------------------------------------------------
--- LOADING JAPANESE FONTS (prefix: ljft)
+-- LOADING JAPANESE FONTS
 ------------------------------------------------------------------------
 local cstemp
 
 -- EXT
-function ltj.ext_jfontdefX(g)
+function jfontdefX(g)
   local t = token.get_next()
   cstemp=token.csname_name(t)
   if g then ltj.is_global = '\\global' else ltj.is_global = '' end
@@ -114,32 +124,32 @@ function ltj.ext_jfontdefX(g)
 end
 
 -- EXT
-function ltj.ext_jfontdefY() -- for horizontal font
-   local j = ljfm_load_jfont_metric()
+function jfontdefY() -- for horizontal font
+   local j = load_jfont_metric()
    local fn = font.id(cstemp)
    local f = font.fonts[fn]
    if not j then 
       ltjb.package_error('luatexja',
                         "bad JFM `" .. jfm_file_name .. "'",
-                        {'The JFM file you specified is not valid JFM file.',
-                         'So defining Japanese font is cancelled.'})
+                        'The JFM file you specified is not valid JFM file.\n'..
+                           'So defining Japanese font is cancelled.')
       tex.sprint(ltj.is_global .. '\\expandafter\\let\\csname '
                 .. cstemp .. '\\endcsname=\\relax')
      return 
    end
-   ltj.font_metric_table[fn]={}
-   ltj.font_metric_table[fn].jfm=j
-   ltj.font_metric_table[fn].size=f.size
-   ltj.font_metric_table[fn].var=jfm_var
+   font_metric_table[fn]={}
+   font_metric_table[fn].jfm=j
+   font_metric_table[fn].size=f.size
+   font_metric_table[fn].var=jfm_var
    tex.sprint(ltj.is_global .. '\\protected\\expandafter\\def\\csname '
               .. cstemp .. '\\endcsname'
               .. '{\\csname ltj@curjfnt\\endcsname=' .. fn
-              .. ' \\zw=' .. round(f.size*ltj.metrics[j].zw) .. 'sp'
-              .. '\\zh=' .. round(f.size*ltj.metrics[j].zh) .. 'sp\\relax}')
+              .. ' \\zw=' .. round(f.size*metrics[j].zw) .. 'sp'
+              .. '\\zh=' .. round(f.size*metrics[j].zh) .. 'sp\\relax}')
 end
 
 -- extract jfm_file_name and jfm_var
-local function ljft_extract_metric(name)
+local function extract_metric(name)
    local basename=name
    local tmp = utf.sub(basename, 1, 5)
    jfm_file_name = ''; jfm_var = ''
@@ -168,7 +178,7 @@ end
 -- replace fonts.define.read()
 local ljft_dr_orig = fonts.define.read
 function fonts.define.read(name, size, id)
-   ljft_extract_metric(name)
+   extract_metric(name)
    -- In the present imple., we don't remove "jfm=..." from name.
    return ljft_dr_orig(name, size, id)
 end
@@ -178,7 +188,7 @@ end
 ------------------------------------------------------------------------
 
 -- EXT: italic correction
-function ltj.ext_append_italic()
+function append_italic()
    local p = tex.nest[tex.nest.ptr].tail
    if p and p.id==id_glyph then
       local f = p.font
@@ -186,9 +196,9 @@ function ltj.ext_append_italic()
       g.subtype = 1; node.set_attribute(g, attr_icflag, ITALIC)
       if ltjc.is_ucs_in_japanese_char(p) then
         f = has_attr(p, attr_curjfnt)
-        local j = ltj.font_metric_table[f]
-        local c = ljfm_find_char_class(p.char, j.jfm)
-        g.kern = round(j.size * ltj.metrics[j.jfm].char_type[c].italic)
+        local j = font_metric_table[f]
+        local c = find_char_class(p.char, j.jfm)
+        g.kern = round(j.size * metrics[j.jfm].char_type[c].italic)
       else
         g.kern = font.fonts[f].characters[p.char].italic
       end
diff --git a/src/luatexja/pretreat.lua b/src/luatexja/pretreat.lua
new file mode 100644 (file)
index 0000000..286a0ba
--- /dev/null
@@ -0,0 +1,96 @@
+--
+-- luatexja/pretreat.lua
+--
+luatexbase.provides_module({
+  name = 'luatexja.pretreat',
+  date = '2011/06/27',
+  version = '0.1',
+  description = '',
+})
+module('luatexja.pretreat', package.seeall)
+local err, warn, info, log = luatexbase.errwarinf(_NAME)
+
+require('luatexja.charrange'); local ltjc = luatexja.charrange
+require('luatexja.jfont');     local ltjf = luatexja.jfont
+require('luatexja.stack');     local ltjs = luatexja.stack
+
+local has_attr = node.has_attribute
+local set_attr = node.set_attribute
+local unset_attr = node.unset_attribute
+local node_remove = node.remove
+local node_next = node.next
+
+local id_glyph = node.id('glyph')
+local id_whatsit = node.id('whatsit')
+local sid_user = node.subtype('user_defined')
+
+local attr_jchar_class = luatexbase.attributes['ltj@charclass']
+local attr_curjfnt = luatexbase.attributes['ltj@curjfnt']
+local attr_yablshift = luatexbase.attributes['ltj@yablshift']
+local attr_ykblshift = luatexbase.attributes['ltj@ykblshift']
+
+local lang_ja_token = token.create('ltj@japanese')
+local lang_ja = lang_ja_token[2]
+
+------------------------------------------------------------------------
+-- MAIN PROCESS STEP 1: replace fonts
+------------------------------------------------------------------------
+box_stack_level = 0
+-- This is used in jfmglue.lua.
+
+local function suppress_hyphenate_ja(head)
+   for p in node.traverse_id(id_glyph, head) do
+      if ltjc.is_ucs_in_japanese_char(p) then
+        local v = has_attr(p, attr_curjfnt)
+        if v then 
+           p.font = v 
+           set_attr(p, attr_jchar_class,
+                    ltjf.find_char_class(p.char, ltjf.font_metric_table[v].jfm))
+        end
+        v = has_attr(p, attr_ykblshift)
+        if v then 
+           set_attr(p, attr_yablshift, v)
+        else
+           unset_attr(p, attr_yablshift)
+        end
+         if p.subtype%2==1 then p.subtype = p.subtype - 1 end
+        p.lang=lang_ja
+      end
+   end
+   lang.hyphenate(head)
+   return head
+end
+
+-- mode: true iff this function is called from hpack_filter
+function set_box_stack_level(head, mode)
+   local box_set = false
+   local p = head
+   local cl = tex.currentgrouplevel + 1
+   for p in node.traverse_id(id_whatsit, head) do
+      if p.subtype==sid_user and p.user_id==30112 then
+        local g = p
+        if mode and g.value==cl then box_set = true end
+        head, p = node_remove(head, g); break
+      end
+   end
+   if box_set then 
+      box_stack_level = tex.getcount('ltj@@stack') + 1 
+   else 
+      box_stack_level = tex.getcount('ltj@@stack') 
+   end
+   return head
+end
+
+-- CALLBACKS
+luatexbase.add_to_callback('hpack_filter', 
+   function (head)
+     return set_box_stack_level(head, true)
+   end,'ltj.hpack_filter_pre',1)
+luatexbase.add_to_callback('pre_linebreak_filter', 
+  function (head)
+     return set_box_stack_level(head, false)
+  end,'ltj.pre_linebreak_filter_pre',1)
+luatexbase.add_to_callback('hyphenate', 
+ function (head,tail)
+    return suppress_hyphenate_ja(head)
+ end,'ltj.hyphenate')
similarity index 90%
rename from src/luatexja-rmlgbm.lua
rename to src/luatexja/rmlgbm.lua
index 7e78ef8..cbf7a2b 100644 (file)
@@ -1,3 +1,15 @@
+--
+-- luatexja/rmlgbm.lua
+--
+luatexbase.provides_module({
+  name = 'luatexja.rmlgbm',
+  date = '2011/06/27',
+  version = '0.1',
+  description = 'Definitions of non-embedded Japanese fonts',
+})
+module('luatexja.rmlgbm', package.seeall)
+local err, warn, info, log = luatexbase.errwarinf(_NAME)
+
 local rmlgbm_data = require('luatexja-rmlgbm-data')
 local cache_chars = { [655360] = rmlgbm_data.characters }
 
diff --git a/src/luatexja/setwidth.lua b/src/luatexja/setwidth.lua
new file mode 100644 (file)
index 0000000..a1c528e
--- /dev/null
@@ -0,0 +1,122 @@
+--
+-- luatexja/setwidth.lua
+--
+luatexbase.provides_module({
+  name = 'luatexja.setwidth',
+  date = '2011/06/28',
+  version = '0.1',
+  description = '',
+})
+module('luatexja.setwidth', package.seeall)
+local err, warn, info, log = luatexbase.errwarinf(_NAME)
+
+require('luatexja.base');      local ltjb = luatexja.base
+require('luatexja.jfont');     local ltjf = luatexja.jfont
+
+local node_type = node.type
+local node_new = node.new
+local node_tail = node.tail
+local node_next = node.next
+local has_attr = node.has_attribute
+local set_attr = node.set_attribute
+local node_insert_before = node.insert_before
+local node_insert_after = node.insert_after
+local round = tex.round
+
+local id_glyph = node.id('glyph')
+local id_kern = node.id('kern')
+local id_hlist = node.id('hlist')
+local id_vlist = node.id('vlist')
+local id_rule = node.id('rule')
+local id_math = node.id('math')
+
+local attr_jchar_class = luatexbase.attributes['ltj@charclass']
+local attr_curjfnt = luatexbase.attributes['ltj@curjfnt']
+local attr_yablshift = luatexbase.attributes['ltj@yablshift']
+local attr_icflag = luatexbase.attributes['ltj@icflag']
+
+local PACKED = 2
+
+local met_tb = {}
+local char_data = {}
+local head
+
+-- return true if and only if p is a Japanese character node
+local function is_japanese_glyph_node(p)
+   return p.font==has_attr(p, attr_curjfnt)
+end
+
+local function capsule_glyph(p, dir)
+   local h, box, q, fwidth, fheight, fdepth
+   p.xoffset= p.xoffset - round(met_tb.size*char_data.left)
+   if char_data.width ~= 'prop' then
+      fwidth = round(char_data.width*met_tb.size)
+   else fwidth = p.width end
+   fheight = round(met_tb.size*char_data.height)
+   fdepth = round(met_tb.size*char_data.depth)
+   if p.width ~= fwidth or p.height ~= fheight or p.depth ~= fdepth then
+      local y_shift = - p.yoffset + (has_attr(p,attr_yablshift) or 0)
+      p.yoffset = -round(met_tb.size*char_data.down)
+      head, q = node.remove(head, p)
+      local total = fwidth - p.width
+      if total == 0 then
+        h = p; p.next = nil
+      else
+        h = node_new(id_kern); h.subtype = 0
+        if char_data.align=='left' then
+           h.kern = total; p.next = h; h = p
+        elseif char_data.align=='right' then
+           h.kern = total; p.next = nil; h.next = p
+        elseif char_data.align=='middle' then
+           h.kern = round(total/2); p.next = h
+           h = node_new(id_kern); h.subtype = 0
+           h.kern = total - round(total/2); h.next = p
+        end
+      end
+      box = node_new(id_hlist); 
+      box.width = fwidth; box.height = fheight; box.depth = fdepth
+      box.glue_set = 0; box.glue_order = 0; box.head = h
+      box.shift = y_shift; box.dir = dir or 'TLT'
+      set_attr(box, attr_icflag, PACKED)
+      if q then
+        head = node_insert_before(head, q, box)
+      else
+        head = node_insert_after(head, node_tail(head), box)
+      end
+      return q
+   else
+      p.yoffset = p.yoffset - (has_attr(p, attr_yablshift) or 0) - round(met_tb.size*char_data.down)
+      return node_next(p)
+   end
+end
+
+function set_ja_width(ahead, dir)
+   local p = ahead; head  = ahead
+   local m = false -- is in math mode?
+   while p do
+      if p.id==id_glyph then
+        if is_japanese_glyph_node(p) then
+           met_tb = ltjf.font_metric_table[p.font]
+           char_data = ltjf.metrics[met_tb.jfm].char_type[has_attr(p, attr_jchar_class)]
+           p = capsule_glyph(p, dir)
+        else 
+           p.yoffset = p.yoffset - (has_attr(p,attr_yablshift) or 0); p = node_next(p)
+        end
+      elseif p.id==id_math then
+        m = (p.subtype==0); p = node_next(p)
+      else
+        if m then
+           if p.id==id_hlist or p.id==id_vlist then
+              p.shift = p.shift + (has_attr(p,attr_yablshift) or 0)
+           elseif p.id==id_rule then
+              local v = has_attr(p,attr_yablshift) or 0
+              p.height = p.height - v; p.depth = p.depth + v 
+           end
+        end
+        p = node_next(p)
+      end
+   end
+   -- adjust attr_icflag
+   tex.attribute[attr_icflag] = -(0x7FFFFFFF)
+   return head
+end
index 244d186..263706b 100644 (file)
@@ -10,7 +10,7 @@ luatexbase.provides_module({
 module('luatexja.stack', package.seeall)
 local err, warn, info, log = luatexbase.errwarinf(_NAME)
 
-local ltjb = luatexja.base
+require('luatexja.base');      local ltjb = luatexja.base
 
 local node_new = node.new
 local id_whatsit = node.id('whatsit')
index 422006f..aa45cd4 100644 (file)
@@ -1,4 +1,4 @@
-ltj.define_jfm {
+luatexja.jfont.define_jfm {
    dir = 'yoko2',
    zw = 1.0, zh = 1.0,
 
index 9d88f6c..a88a058 100644 (file)
@@ -1,4 +1,4 @@
-ltj.define_jfm {
+luatexja.jfont.define_jfm {
    dir = 'yoko',
    zw = 1.0, zh = 1.0,
    
index 2b159b9..aa74647 100644 (file)
@@ -1,4 +1,4 @@
-ltj.define_jfm {
+luatexja.jfont.define_jfm {
    dir = 'yoko',
    zw = 1.0, zh = 1.0,
    kanjiskip = { 0.1, 0.04, 0.05 },
@@ -42,6 +42,12 @@ ltj.define_jfm {
       width = 1.0, height = 0.88, depth = 0.12, italic=0.0,
       kern = { [8] = -1.41 , [2] = 2.0}
    },
+   [51] = {
+      chars = { 'か' },
+      align = 'left', left = 0.0, down = 0.0,
+      width = 1.0, height = 0.88, depth = 0.12, italic=0.0,
+      kern = { [199] = 0.85 },
+   },
 
    [2] = {
       chars = { 'ア' },
@@ -55,14 +61,14 @@ ltj.define_jfm {
    },
    [99] = {
       chars = { 'jcharbdd' },
-      align = 'left', left = 0.0, down = 0.0,
-      width = 1.0, height = 0.88, depth = 0.12, italic=0.0,
       glue = { [11] = { 1.41, 0, 0} },
       kern = { [21] = 2.0, }
    },
+   [199] = {
+      chars = { 'boxbdd' },
+      glue = { [51] = { 1.03, 0, 0} , [1] = { 0.94, 0.23, 0.45 }},
+   },
    [8] = {
       chars = { 'lineend' },
-      align = 'left', left = 0.0, down = 0.0,
-      width = 1.0, height = 0.88, depth = 0.12, italic=0.0,
    }
 }
index 327b77a..3f92bad 100644 (file)
Binary files a/test/test01-noembed.pdf and b/test/test01-noembed.pdf differ
index a6ae9a8..ef939f6 100644 (file)
Binary files a/test/test01.pdf and b/test/test01.pdf differ
index d4eb87e..141782a 100644 (file)
@@ -2,6 +2,7 @@
 \input luatexja-core.sty
 
 \jfont\jisninety={file:ipaexm.ttf:script=latn;+jp90;jfm=ujis}
+\jfont\jisfour={file:ipaexm.ttf:script=latn;+jp04;jfm=ujis}
 \jfont\jisexpt={file:ipaexm.ttf:script=latn;+expt;jfm=ujis}
 \jfont\jishwid={file:ipaexm.ttf:script=latn;+hwid;jfm=ujis}
 %\font\tmihwid={file:ipaexm.ttf:script=latn;+hwid}
@@ -23,6 +24,8 @@
 
 {\tentt jp90} feature: 辻→{\jisninety 辻}
 
+{\tentt jp04} feature: 辻→{\jisfour 辻}
+
 {\tentt hwid} feature: アイウエ→{\jishwid アイウエ}\hfil\break
 ↑文字クラスが変わらないので幅も変わらない.
 
index 5b6990c..74ec84f 100644 (file)
Binary files a/test/test02-latex.pdf and b/test/test02-latex.pdf differ
index 87b4195..2ff7dd8 100644 (file)
@@ -1,5 +1,41 @@
 %#! lualatex
 \documentclass{article}
+\usepackage{luatexja}
+
+\makeatletter
+% from jsclasses
+\def\@setfontsize#1#2#3{%
+  \ifx\protect\@typeset@protect
+    \let\@currsize#1%
+  \fi
+  \fontsize{#2}{#3}\selectfont
+  \ifdim\parindent>\z@
+      \parindent=1\zw
+  \fi
+  \ltjsetparameter{kanjiskip={0\zw plus .1\zw minus .01\zw}}%
+  \@tempskipa=\ltjgetparameter{xkanjiskip}%
+  \ifdim\@tempskipa>\z@
+    \ltjsetparameter{xkanjiskip={0.25em plus 0.15em minus 0.06em}}%
+  \fi}
+
+\begin{document}
+\section{NFSS2}
+
+◆あいうえおabcかきく{\gt かきくa{\bf uyあ}いう}
+
+{\ltjsetparameter{xkanjiskip=0pt}イタリック補正\textit{f}◆\par}
+
+\DeclareFixedFont{\dr}{JY3}{gt}{m}{n}{12}
+あいうえおpqr{\dr かaiu}きく){\bf (漢字}
+
+\section{fontspec}
+
+かいてない
+\end{document}
+
+
+%%%%%%%%%%%%%%%%%%%%% OLD TEST
+\documentclass{article}
 \usepackage{fontspec,pdftexcmds}
 
 \input luatexja-core.sty
@@ -55,4 +91,4 @@
 % \unkern がないとうなくいかない
 
 \tracingonline=1\scrollmode\showboxdepth=10000\showboxbreadth=10000\showlists
-\end{document}
\ No newline at end of file
+\end{document}
index 0a5b8de..679b21a 100644 (file)
Binary files a/test/test04-jfm.pdf and b/test/test04-jfm.pdf differ
index b209b95..f7a82aa 100644 (file)
@@ -79,7 +79,9 @@
 \def\dumplist#1{\par\noindent\leavevmode
 \hbox to 0.2\hsize{\copy#1\hss}%
 \vbox{\hsize=0.6\hsize\sixtt\baselineskip=7.2pt\sixgt\let\\=\relax
-\directlua{ltj.ext_show_node_list(tex.getbox(#1).head, '\\par', tex.print)}\hrule}}
+\directlua{ltj.ext_show_node_list(tex.getbox(#1).head, '\\par ', tex.print)}\hrule}}
+
+%\tracingonline=1\tracingoutput=1\showboxdepth=3\showboxbreadth=100
 
 \head{JA--JA (penなし)}
 
 
 \setbox0=\hbox{\rmlh え\hbox{}}\dumplist0
 
+\setbox0=\hbox{\rmlh あ\hbox{ア}}\dumplist0
+
+\setbox0=\hbox{\rmlh あ\hbox{a}}\dumplist0
+
+\setbox0=\hbox{\rmlh い\hbox{a}}\dumplist0
+
 \head{hbox--JA (penなし)}
 
 \setbox0=\hbox{\rmlh \hbox{}あ}\dumplist0
 
 \setbox0=\hbox{\rmlh \hbox{}う}\dumplist0
 
-\head{JA--penalty (penなし)} TODO: この場合の挙動はこれで良いか?
-
-\setbox0=\hbox{\rmlh あ\penalty567}\dumplist0
-
-\setbox0=\hbox{\rmlh い\penalty567}\dumplist0
-
-\setbox0=\hbox{\rmlh う\penalty567}\dumplist0
-
-\setbox0=\hbox{\rmlh え\penalty567}\dumplist0
-
-\head{penalty--JA (penなし)} TODO: この場合の挙動はこれで良いか?
-
-\setbox0=\hbox{\rmlh \penalty567あ}\dumplist0
-
-\setbox0=\hbox{\rmlh \penalty567い}\dumplist0
-
-\setbox0=\hbox{\rmlh \penalty567う}\dumplist0
-
 {\vfill\eject%
 
 \ltjsetparameter{prebreakpenalty={`(,123}}
 \ltjsetparameter{postbreakpenalty={`あ,123}}
-\ltjsetparameter{postbreakpenalty={`い,123}}
+\ltjsetparameter{prebreakpenalty={`い,571}, postbreakpenalty={`い,123}}
 \ltjsetparameter{postbreakpenalty={`う,123}}
 \ltjsetparameter{postbreakpenalty={`え,123}}
 \ltjsetparameter{postbreakpenalty={`お,123}}
 
 \setbox0=\hbox{\rmlh aう}\dumplist0
 
+\head{JA--hbox (penあり)}
+
+\setbox0=\hbox{\rmlh あ\hbox{ア}}\dumplist0
+
+\setbox0=\hbox{\rmlh あ\hbox{a}}\dumplist0
+
+\setbox0=\hbox{\rmlh い\hbox{a}}\dumplist0
+
+\setbox0=\hbox{\rmlh \hbox{(}い\hbox{)}}\dumplist0
+
 \head{italic correction}
 
 \setbox0=\hbox{\it f\/(\/あ}\dumplist0
 {\ltjsetparameter{alxspmode={`x,postonly}}
 \setbox0=\hbox{\rmlh まx}\dumplist0}
 
-\head{kanjiskip from JFM/autoxspacing (EN--JA)}
+\head{xkanjiskip from JFM/autoxspacing (EN--JA)}
 \setbox0=\hbox{\rmlh xま}\dumplist0
 
 \setbox0=\hbox{\rmlh x\naxspc ま}\dumplist0
 \setbox0=\hbox{\rmlh あ\penalty1701\penalty1701\penalty1701お}
 \dumplist0
 
-\setbox0=\hbox{\tenrm あ\/\v{A}あ}
+\head{その他: italic correction and accents}
+
+\setbox0=\hbox{\tenrm あ\/j}
+\dumplist0
+\setbox0=\hbox{\tenrm\rmlh れ\v{A})}
+\dumplist0
+
+\head{その他: box boundary}
+
+\setbox0=\hbox{\rmlh かあか}
+\dumplist0
+\setbox0=\hbox{a\setbox3=\hbox{\rmlh  かあか}\unhbox3a}
+\dumplist0
+\setbox0=\hbox{a\setbox3=\hbox{\rmlh  か}\box3a}
 \dumplist0
+\setbox0=\hbox{\rmlh き\hbox{か}き\hbox{き}き}
+\dumplist0
+
+{\ltjsetparameter{postbreakpenalty={`あ,1000},prebreakpenalty={`あ,1000}}
+\setbox0=\hbox{あ\hbox{(}あ\setbox3=\hbox{(}\unhbox3あ}
+\dumplist0}
+
 
 \end
diff --git a/test/test05-speed.pdf b/test/test05-speed.pdf
deleted file mode 100644 (file)
index 1754fea..0000000
Binary files a/test/test05-speed.pdf and /dev/null differ
index 62f9331..1be795a 100644 (file)
@@ -1,10 +1,10 @@
-%#! time luatex  test05-speed.tex
+%#! time luatex  "\count300=40\input test05-speed.tex"
 \input luatexja-core.sty
 
 \newcount\cnt\newcount\cnta
-\cnt=0
+\cnt=0\output={\deadcycles=0\setbox2000=\box255}
 \long\def\loop#1\repeat{\def\body{#1}\iterate}
-\loop\ifnum\cnt<10 % <= this value
+\loop\ifnum\cnt<\count300 % <= this value
   \cnta=0 \message{\the\cnt:}\par
   {\loop\ifnum\cnta<500 あ.「い,うえお・か(き)く)(けこ\advance\cnta1\repeat}
   \advance\cnt1
@@ -13,6 +13,8 @@
 \end
 
 %     real time:
-% 20:  9.950s
-% 10:  5.209s
+% 40: 17.453
+% 30: 13.254
+% 20:  8.771
+% 10:  4.927
 % env: C2D E7300, Mem 4GB, LuaTeX 0.71.0pre, Gentoo amd64 unstable
\ No newline at end of file
diff --git a/test/test06-offset.pdf b/test/test06-offset.pdf
new file mode 100644 (file)
index 0000000..9b1e3bf
Binary files /dev/null and b/test/test06-offset.pdf differ
diff --git a/test/test06-offset.tex b/test/test06-offset.tex
new file mode 100644 (file)
index 0000000..461c51d
--- /dev/null
@@ -0,0 +1,44 @@
+%#!luatex
+\input luatexja.sty
+
+\def\gbox#1{\noindent\setbox0=\hbox{\d#1}
+  \vrule height 0.2pt depth 0.2pt width \dimexpr \wd0+10pt\relax
+  \kern\dimexpr -\wd0-5pt\relax\vrule height\ht0 depth \dp0\hbox{\copy0}%
+  \vrule height\ht0 depth \dp0\relax}
+\font\d=cmr17 at 20pt
+\baselineskip=40pt
+
+\jfont\sixgt={psft:GothicBBB-Medium:jfm=ujis} at 6pt
+\font\sixtt=cmtt10 at 6pt
+\def\dumplist#1{\par\noindent\leavevmode
+\hbox to 0.2\hsize{\copy#1\hss}%
+\vbox{\hsize=0.6\hsize\sixtt\baselineskip=7.2pt\sixgt\let\\=\relax
+\directlua{ltj.ext_show_node_list(tex.getbox(#1).head, '\\par ', tex.print)}\hrule}}
+
+\ltjsetparameter{yalbaselineshift=0pt,yjabaselineshift=0pt}
+\setbox0=\hbox{\d Hy}\dumplist0
+
+\ltjsetparameter{yalbaselineshift=-10pt}\gbox{Hy}
+\ltjsetparameter{yalbaselineshift=-0pt}\gbox{Hy}
+\ltjsetparameter{yalbaselineshift=10pt}\gbox{Hy}
+\ltjsetparameter{yalbaselineshift=20pt}\gbox{Hy}
+
+\jfont\f=psft:Ryumin-Light:jfm=ujis at 20pt\f
+\ltjsetparameter{yalbaselineshift=0pt,yjabaselineshift=0pt}
+\setbox0=\hbox{\f あ}\dumplist0
+
+\ltjsetparameter{yjabaselineshift=-10pt}\gbox{あ}
+\ltjsetparameter{yjabaselineshift=0pt}\gbox{あ}
+\ltjsetparameter{yjabaselineshift=10pt}\gbox{あ}
+\ltjsetparameter{yjabaselineshift=20pt}\gbox{あ}
+
+\jfont\f=name:IPAMincho:jfm=ujis at 20pt\f
+\ltjsetparameter{yalbaselineshift=0pt,yjabaselineshift=0pt}
+\setbox0=\hbox{\f あ}\dumplist0
+
+\ltjsetparameter{yjabaselineshift=-10pt}\gbox{あ}
+\ltjsetparameter{yjabaselineshift=0pt}\gbox{あ}
+\ltjsetparameter{yjabaselineshift=10pt}\gbox{あ}
+\ltjsetparameter{yjabaselineshift=20pt}\gbox{あ}
+
+\end