OSDN Git Service

Redefine \lastbox.
authorHironori Kitagawa <h_kitagawa2001@yahoo.co.jp>
Sun, 8 Jun 2014 11:39:50 +0000 (20:39 +0900)
committerHironori Kitagawa <h_kitagawa2001@yahoo.co.jp>
Sun, 8 Jun 2014 11:40:00 +0000 (20:40 +0900)
doc/luatexja.dtx
src/ltj-direction.lua
src/luatexja-core.sty

index 271315a..5ee0134 100644 (file)
@@ -2740,7 +2740,7 @@ Down-TO-Upの意味なのだろう.\verb+\dtou+ を使用する機会はない
 \pTeX ではこれらのプリミティブは,「現在の組方向におけるボックスの寸法」を指すものであった.
 
 \LuaTeX-jaにおいては状況が異なり,\verb+\wd+,~\verb+\ht+,~\verb+\dp+ は\emph{組方向が
-混在する状況においては正しく機能しない}.まず,現在の組方向に依存しないことが挙げられる.
+混在する状況においては正しく機能しない}.具体的には,現在の組方向に依存しないことが挙げられる.
 \begin{LTXexample}
 % yoko direction
 \setbox0=\hbox to 20pt{foo}
@@ -2748,20 +2748,6 @@ Down-TO-Upの意味なのだろう.\verb+\dtou+ を使用する機会はない
 \wd0=100pt
 \the\wd0,~\hbox{\tate \the\wd0}
 \end{LTXexample}
-また,異方向のボックスの配置処理の関係で,
-\verb+\lastbox+ を駆使してボックスのコピーを
-作成した場合でも,\verb+\wd+ 等の値が異なる場合もある.
-例えば,下の実行例における \verb+\wd1+ の値は,「縦組で組んだ時の \verb+\box0+ の
-専有する幅」となる.
-\begin{LTXexample}
-% yoko direction
-\setbox0=\hbox to 20pt{Xy}
-\the\wd0,
-\setbox0=\hbox{\tate\copy0}
-\setbox0=\hbox{\tate\unhbox0
-  \global\setbox1\lastbox}
-\the\wd1
-\end{LTXexample}
 
 \paragraph{\texttt{\textbackslash wd} 等の代替命令}
 
@@ -2826,6 +2812,22 @@ Down-TO-Upの意味なのだろう.\verb+\dtou+ を使用する機会はない
 
 \end{cslist}
 
+\subsection{プリミティブの再定義}
+異なる組方向に対応するために,以下に挙げるプリミティブは
+\LuaTeX-jaによる前処理もしくは後処理が行われるように
+\ \verb+\protected\def+ により再定義してある.
+\begin{cslist}
+ \item[unhbox<num>\textrm{, }\textbackslash unvbox<num>]
+ ボックスの組方向が現在のリストと異なる場合は事前にエラーメッセージを出力する.
+ \pTeX と異なり,エラーを無視して無理矢理 \verb+\unhbox+, \verb+\unvbox+ を
+ 続行させることもできるが,その場合の組版結果は保証しない.
+ \item[vadjust\{<material>\}] 一旦プリミティブ本来の挙動を行う.その後,<material>の組方向が
+ 周囲の垂直リストの組方向と一致しない場合にエラーを出力し,
+ 該当の \verb+\vadjust+ を無効にする.
+ \item[lastbox] 異なる組方向のボックスを配置した場合に位置合わせ用に作られるノード類を
+ 除去し,正しく「中身」のボックスが返されるように前処理をする.
+\end{cslist}
+
 %</ja>
 
 %<en>\section{Font Metric and Japanese Font}
@@ -5737,14 +5739,18 @@ $i$は7より小さい自然数.
 
 \attr{ltj@dir}
 %<*ja>
-ボックスにおける組方向を示す.上記の3つの値(1,~3,~4)の他に,
-それらに次を加えた値(17,~19, 20, 33, 35,~36)もとり得る.
+ボックスにおける組方向を示す.通常のボックスでは上記の3つの値(1,~3,~4)をとり得るが,
+内部処理によりそれらに次を加えた値(17,~19, 20, 33, 35,~36)をとるボックスが作られることもあ
+                        る(\ref{sec-dir-imp}章参照).
 %</ja>
 \begin{description}
 \item[\textit{dir\_node\_auto} (16)]
+%<ja> 異なる組方向に配置するために自動的に作られたボックス.
 \item[\textit{dir\_node\_manual} (32)]
+%<ja> \verb+\ltjsetwd+ によって「ボックスの本来の組方向とは異なる組方向での寸法」を
+%<ja> 設定したときに,それを記録するためのボックス.
 \end{description}
-
+%<ja> \TeX 側から見える値,つまり \verb+\the\ltj@dir+ の値は常に0である.
 
 \end{list}
 
@@ -7813,6 +7819,46 @@ nilでない<data>をキャッシュ<filename>に保存する.
 
 %<*ja>
 \section{縦組の実装}
+\label{sec-dir-imp}
+\ref{sec-direction}章の最初でも述べたように,
+\LuaTeX-jaは横組(\texttt{TLT})で組んだボックスを回転させる方式で
+縦組を実装している.
+
+\LuaTeX-jaにおける縦組の実装は
+\pTeX における実装(\cite{ptexdoc,ptextug})をベースにしており,……
+
+\subsection{\textit{direction}~whatsit}
+\textit{direction}~whatsitとは,\textit{direction}という特定の \verb+user_id+ を持つ
+whatsitのことである.このwhatsitは,以下の3つの役割がある.
+\begin{enumerate}
+\def\labelenumi{(\roman{enumi})}
+ \item 「現在作成中のリストの組方向が \verb+\tate+ 等により変更された」ことを表す.\\
+「現在の組方向」は \verb+\ltj@dir@count+ というカウンタに格納されているが,それだけでは
+\verb+hpack_filter+コールバックなどから正しく処理対象のリストの組方向を正しく取得すること
+       はできない(\ref{ssec-stack}節参照)ため,このように別途whatsitを用いている.
+ \item \verb+\hbox+,~\verb+\vbox+によって作成されたボックスの組方向を表す.\\
+原則として,ボックスの組方向はattribute \verb+\ltj@dir+ に格納されることになっている.しか
+       し,新規に作成されるボックスのattributeをコールバックの内部から制御するには,
+\verb+tex.setattribute+ による方法しかなく,これは不安定……
+ \item 「異方向における寸法」の記録用
+\end{enumerate}
+このように複数の役割をもたせているので,
+\begin{verbatim}
+% yoko direction
+\setbox0=\hbox{\tate B}
+\noindent \unhbox0 A
+\end{verbatim}
+のような場合に,「(ii)の役割の\textit{direction}~whatsitが(i)の役割として認識され,
+このリストは縦組とみなされるのではないか?」と思うかもしれない.しかし,
+(i)の役割と(ii)の枠割の\textit{direction}~whatsitは \verb+\ltj@icflag+ の値により
+区別されているので,そのような混乱は起こらない.
+
+
+\subsection{異方向のボックスの整合処理}
+縦中横など異方向のボックスを配置する場合に,周囲の組方向と大きさを整合させるため,
+\LuaTeX-jaでは \verb+\ltj@dir+ が16以降の\textit{hlist\_node}, \textit{vlist\_node}を
+用いる.
+
 
 
 %</ja>
index ae34f7d..fba6cd3 100644 (file)
@@ -42,6 +42,7 @@ local sid_restore = node.subtype('pdf_restore')
 local sid_matrix = node.subtype('pdf_setmatrix')
 local sid_user = node.subtype('user_defined')
 
+local tex_nest = tex.nest
 local tex_getcount = tex.getcount
 local tex_set_attr = tex.setattribute
 local PROCESSED    = luatexja.icflag_table.PROCESSED
@@ -67,7 +68,7 @@ do
    local node_next = node.next
    local node_set_attr = node.set_attribute
    local function set_list_direction(v, name)
-      local lv, w = tex.nest[tex.nest.ptr], tex.lists.page_head
+      local lv, w = tex_nest[tex_nest.ptr], tex.lists.page_head
       if lv.mode == 1 and w then
         if w.id==id_whatsit and w.subtype==sid_user
         and w.user_id==DIR then
@@ -336,6 +337,7 @@ end
 -- b に DIR whatsit があればその内容を attr_dir にうつす (1st ret val)
 -- 2nd ret val はその DIR whatsit
 local function get_box_dir(b, default)
+   start_time_measure('get_box_dir')
    local dir = has_attr(b, attr_dir) or 0
    local bh = getfield(b,'head') 
    -- b は insert node となりうるので getlist() は使えない
@@ -352,21 +354,28 @@ local function get_box_dir(b, default)
       end
       bh = node_next(bh)
    end
+   stop_time_measure('get_box_dir')
    return (dir==0 and default or dir), c
 end
 
-function luatexja.direction.check_dir(reg_num)
-   local list_dir = get_dir_count()
-   local b = tex.getbox(reg_num)
-   if b then
-      local box_dir = get_box_dir(to_direct(b), dir_yoko)
-      if box_dir%dir_node_auto ~= list_dir%dir_node_auto then
-        ltjb.package_error(
-                 'luatexja',
-                 "Incompatible direction list can't be unboxed",
-                'I refuse to unbox a box in differrent direction.')
+do
+   local getbox = tex.getbox
+   local function check_dir(reg_num)
+      start_time_measure('box_primitive_hook')
+      local list_dir = get_dir_count()
+      local b = tex.getbox(tex_getcount('ltj@tempcnta'))
+      if b then
+        local box_dir = get_box_dir(to_direct(b), dir_yoko)
+        if box_dir%dir_node_auto ~= list_dir%dir_node_auto then
+           ltjb.package_error(
+              'luatexja',
+              "Incompatible direction list can't be unboxed",
+              'I refuse to unbox a box in differrent direction.')
+        end
       end
+      stop_time_measure('box_primitive_hook')
    end
+   luatexja.direction.check_dir = check_dir
 end
 
 -- dir_node に包まれている「本来の中身」を取り出し,
@@ -492,15 +501,13 @@ do
               else
                  db_head, db_tail = nn, nn
               end
-           --end
-           setfield(db, 'head', db_head)
-           ret, flag = db, true
+              setfield(db, 'head', db_head)
+              ret, flag = db, true
         end
         return nh, nb, ret, flag
       end
    end
    process_dir_node = function (hd, gc)
-      start_time_measure('direction_vpack')
       local x, new_dir = hd, ltjs.list_dir or dir_yoko
       while x do
         local xid = getid(x)
@@ -511,11 +518,34 @@ do
            x = node_next(x)
         end
       end
-      stop_time_measure('direction_vpack')
       return hd
    end
+
+   -- lastbox
+   local node_prev = (Dnode~=node) and Dnode.getprev or node.prev
+   local function lastbox_hook()
+      start_time_measure('box_primitive_hook')
+      local bn = tex_nest[tex_nest.ptr].tail
+      if bn then
+        local b, head = to_direct(bn), to_direct(tex_nest[tex_nest.ptr].head)
+        local bid = getid(b)
+        if bid==id_hlist or bid==id_vlist then
+           local box_dir =  get_box_dir(b, 0)
+           if box_dir>= dir_node_auto then -- unwrap
+              local p = node_prev(b)
+              local dummy1, dummy2, nb = unwrap_dir_node(b, nil, box_dir)
+              setfield(p, 'next', nb);  tex_nest[tex_nest.ptr].tail = to_node(nb)
+              setfield(b, 'next', nil); setfield(b, 'head', nil)
+              node_free(b)
+           end
+        end
+      end
+      stop_time_measure('box_primitive_hook')
+   end
+
+   luatexja.direction.make_dir_whatsit = make_dir_whatsit
+   luatexja.direction.lastbox_hook = lastbox_hook
 end
-luatexja.direction.make_dir_whatsit = make_dir_whatsit
 
 -- \wd, \ht, \dp の代わり
 do
@@ -751,8 +781,9 @@ end
 -- adjust and insertion
 local id_adjust = node.id('adjust')
 function luatexja.direction.check_adjust_direction()
+   start_time_measure('box_primitive_hook')
    local list_dir = tex_getcount('ltj@adjdir@count')
-   local a = tex.nest[tex.nest.ptr].tail
+   local a = tex_nest[tex_nest.ptr].tail
    local ad = to_direct(a)
    if a and getid(ad)==id_adjust then
       local adj_dir = get_box_dir(ad)
@@ -764,12 +795,14 @@ function luatexja.direction.check_adjust_direction()
          Dnode.last_node()
       end
    end
+   stop_time_measure('box_primitive_hook')
 end
 
 -- vsplit
 do
    local split_dir_whatsit
    local function dir_adjust_vpack(h, gc)
+      start_time_measure('direction_vpack')
       local hd = to_direct(h)
       if gc=='split_keep' then
         -- supply dir_whatsit
@@ -792,7 +825,9 @@ do
         split_dir_whatsit=nil
       else
         hd = process_dir_node(create_dir_whatsit_vbox(hd, gc), gc)
+        split_dir_whatsit=nil
       end
+      stop_time_measure('direction_vpack')
       return to_node(hd)
    end
    luatexbase.add_to_callback('vpack_filter', 
index 4a5d3f0..78ccde5 100644 (file)
 
 \newcount\ltj@adjdir@count@backup
 %%%% insert
-\let\orig@insert=\insert
-\protected\def\insert{\begingroup\afterassignment\ltj@@insert@A\ltj@tempcnta}
-\protected\def\ltj@@insert@A{\orig@insert\ltj@tempcnta\bgroup\aftergroup\endgroup\let\next}
+%\let\orig@insert=\insert
+%\protected\def\insert{\begingroup\afterassignment\ltj@@insert@A\ltj@tempcnta}
+%\protected\def\ltj@@insert@A{\orig@insert\ltj@tempcnta\bgroup\aftergroup\endgroup\let\next}
 %%%% vadjust
 \let\ltj@@orig@vadjust=\vadjust
 \protected\def\vadjust{%
 \protected\def\ltj@@unvbox{%
   \directlua{luatexja.direction.check_dir(\the\ltj@tempcnta)}%
   \ltj@@orig@unvbox\ltj@tempcnta\endgroup}
+%%%% lastbox
+\let\ltj@@orig@lastbox=\lastbox
+\protected\def\lastbox{%
+  \directlua{luatexja.direction.lastbox_hook()}\ltj@@orig@lastbox
+}
 
 %%%%%%%% \ltjgetwd<box_num> etc.
 %\def\ltjgetwd{\expandafter\expandafter\expandafter\ltj@@getwd\ltj@grab@num}