pTeX での \kanjiskip, \xkanjiskip の扱い

前提

資料-TeXにおける段落/ボックスの内部表現 をお読み下さい. §xxx とあるのは,pTeX のソース(同ページの付録を参照)でのセクション番号です.

\kanjiskip について

pTeX においては,和文間空白 \kanjiskip は,(メモリ節約のために)明示的に glue として挿入されることは行われない.

  • 行分割処理や hbox の寸法決定の際に,和文文字を表す char_node が2つ連続した場合, その間には暗黙に \kanjiskip が挿入されているものとして分割位置や hbox の寸法を決定する.
  • ボックスの中身を実際に dvi へと出力する時にも,連続した和文文字の間には \kanjiskip が挿入されているものとして文字間に間隔が入る.

そのため,\kanjiskip は

  • グループ境界は透過する: 「あ{\gt い}う」において,「あ」「い」の間,「い」「う」の間には \kanjiskip が入る.なぜなら,これらは内部リスト表現においても連続しているから.
  • 空の hbox は透過しない: 「あ\hbox{}い」において,「あ」「い」の間には \kanjiskip は入らない. なぜなら,(dvi 上では何もないように見えても)「あ」「い」の間に hlist_node があるから.

しかし,透過する例外が2つある.この2つの場合は重なってもよい. これらは,実際には後に述べる adjust_hlist procedure において,glue として明示的に挿入している.

  • 和文文字の間に penalty がある場合: 正確に言うと,和文を表す 2つの char_node の間に penalty_node が1つ以上ある場合, 最後の penalty_node の直後に \kanjiskip を挿入する.
    例:
    (あ) (\penalty 10) (\penalty 20) (い) → (あ) (\penalty 10) (\penalty 20) (\kanjiskip) (い)
    
  • hbox 内外の文字間にも入る:\xkanjiskip の場合と同様の処理がおこなわれている.
    例に留めよう:
    (あ) (\hbox{あ}) (い) → (あ) (\kanjiskip) (\hbox{あ}) (\kanjiskip) (い) 
    

\xkanjiskip について

和欧文間空白 \xkanjiskip は,段落の行分割処理の前や,hbox の寸法決定の前に glue として挿入される.

  • 挿入処理自体は,adjust_hlist なる procedure (§1451--1464) に,段落/hbox の中身を表すリストを 渡すことにより行われる.
  • primitive \noautoxspacing で「\xkanjiskip を自動挿入しない」ことが行えるが,それは実際には 挿入する \xkanjiskip の値を 0 にしているだけ(glue として挿入はされる)である.

以下,adjust_hlist の中身を概説する.斜体英小文字でノードを表す.

  • 基本形:2つの char_node(文字)が連続している時
    両者の文字コードの値から 2つのノード間に\xkanjiskip を挿入するかを判断し,挿入することになれば挿入する.
  • hbox p の周囲
    • 垂直ボックス (vbox) や,異なる組方向のボックスの周囲には \xkanjiskip は入らない.
    • \raise/\lower によって縦にシフトされている hbox の周囲にも入らない.
    • まず,関数 check_box (§1450) を用いて,「pの最初のchar pf」「pの最後のchar pl」を取得する.
      • 最初/最後が char_node でなければ,null 値になる.
      • この2つは,縦シフト量が 0 であるような hbox について再帰的に探索が進む.つまり,
        \hbox{\hbox{あい}う\hbox{えお}} → pf = 「あ」, pl = 「お」
        \hbox{\raise2pt\hbox{あい}う\vbox{えお}} → pf =  null, pl = null
        
    • p の前に \xkanjiskip が入るかどうかは,pf の前に入るかどうかで決定.
    • p の後に \xkanjiskip が入るかどうかは,pl の後に入るかどうかで決定.
  • 数式境界 math_node p の周囲
    • p が数式開始を示す math_node のとき: p の後には入らない.pの前に入るかどうかは,数字 0 の前に入るかどうかで決定される.
    • p が数式終了を示す math_node のとき: p の前には入らない.pの後に入るかどうかは,数字 0 の後に入るかどうかで決定される. 例:
      (あ) $ ... $ (.) →  (あ) (\xkanjiskip) $ ... $ (.)
      
  • 合字 ligature_node p の周囲
    • p の前に入るかどうかは,pを構成している元の文字列の先頭文字に関して判定.
    • p の後に入るかどうかは,pを構成している元の文字列の末尾文字に関して判定.
    • 例えば,\xspcode`\f=0 (文字「f」の前後には \xkanjiskip は入らない)の元では,
      (あ) (ligature fi) (い) → (あ) (ligature fi) (\xkanjiskip) (い)
      
  • penalty, displacement node p 周り
    • 挿入判定に関しては透過.ただし,次回の挿入判定において, 挿入がおこる場所は今問題にしている penalty (or disp) の直後に変更される.
      例:
      (A) (\penalty 100) (あ) →(A) (\penalty 100) (\xkanjiskip) (あ)
      (あ) (\penalty 100) (\penalty 20) (\hbox{a}) → (あ) (\penalty 100) (\penalty 20) (\xkanjiskip) (\hbox{a})
      
    • 禁則ペナルティ等のため,和文 char_node が p の前後にある場合は, 暗黙に挿入される \kanjiskip がこの場合では挿入されないので,ここで \kanjiskip の明示的な挿入を行う.
      例:
      (あ) (\penalty 20) (い) →(あ) (\penalty 20) (\kanjiskip) (い)
      
  • kern pの周囲:問題にしている kern の subtype により異なる.
    • 明示的な \kern 由来:この p の周囲には \xkanjiskip は入らない.
    • イタリック補正由来:挿入判定に関しては透過.挿入がおこる場所は p の直後となる.
    • アクセント由来:アクセント部を表すノード列は無視される(詳細な説明は書きかけ).
  • rule(黒箱),discretionary,glue の周囲:これらの p の周囲には \xkanjiskip は入らない.
  • mark, insertion, adjust, whatsit:挿入判定に関しては透過.挿入がおこる場所は 問題とする場所の直後となる.