OSDN Git Service

Updated documents'
[luatex-ja/luatexja.git] / src / ltj-jfmglue.lua
index 1cd7c98..b080005 100644 (file)
@@ -76,13 +76,21 @@ local sid_end_thread = node.subtype('pdf_end_thread')
 local ITALIC       = luatexja.icflag_table.ITALIC
 local PACKED       = luatexja.icflag_table.PACKED
 local KINSOKU      = luatexja.icflag_table.KINSOKU
-local FROM_JFM     = luatexja.icflag_table.FROM_JFM
 local PROCESSED    = luatexja.icflag_table.PROCESSED
 local IC_PROCESSED = luatexja.icflag_table.IC_PROCESSED
 local BOXBDD       = luatexja.icflag_table.BOXBDD
 local PROCESSED_BEGIN_FLAG = luatexja.icflag_table.PROCESSED_BEGIN_FLAG
-local kanji_skip
-local xkanji_skip
+
+local attr_icflag = luatexbase.attributes['ltj@icflag']
+local kanji_skip = node_new(id_glue)
+local xkanji_skip = node_new(id_glue)
+do
+   local KANJI_SKIP   = luatexja.icflag_table.KANJI_SKIP
+   local XKANJI_SKIP   = luatexja.icflag_table.XKANJI_SKIP
+   set_attr(kanji_skip, attr_icflag, KANJI_SKIP)
+   set_attr(xkanji_skip, attr_icflag, XKANJI_SKIP)
+end
+
 local table_current_stack
 local list_dir
 local capsule_glyph
@@ -91,7 +99,6 @@ local attr_ablshift
 local set_np_xspc_jachar
 local set_np_xspc_jachar_hbox
 
-local attr_icflag = luatexbase.attributes['ltj@icflag']
 local ltjs_orig_char_table = ltjs.orig_char_table
 
 local function get_attr_icflag(p)
@@ -490,6 +497,7 @@ local calc_np_auxtable = {
    end,
    [id_kern] = function(lp)
       if getsubtype(lp)==2 then
+        Np.first = Np.first or lp
         set_attr(lp, attr_icflag, PROCESSED); lp = node_next(lp)
         set_attr(lp, attr_icflag, PROCESSED); lp = node_next(lp)
         set_attr(lp, attr_icflag, PROCESSED); lp = node_next(lp)
@@ -639,16 +647,18 @@ end
 -------------------- 最下層の処理
 
 -- change penalties (or create a new penalty, if needed)
+local pen_skel = node_new(id_penalty)
+set_attr(pen_skel, attr_icflag, KINSOKU)
+
 local function handle_penalty_normal(post, pre, g)
    local a = (pre or 0) + (post or 0)
    if #Bp == 0 then
       if (a~=0 and not(g and getid(g)==id_kern)) then
-        local p = node_new(id_penalty)
+        local p = node_copy(pen_skel)
         if a<-10000 then a = -10000 elseif a>10000 then a = 10000 end
         setfield(p, 'penalty', a)
         head = insert_before(head, Np.first, p)
         Bp[1]=p;
-        set_attr(p, attr_icflag, KINSOKU)
       end
    else for _, v in pairs(Bp) do add_penalty(v,a) end
    end
@@ -658,12 +668,11 @@ local function handle_penalty_always(post, pre, g)
    local a = (pre or 0) + (post or 0)
    if #Bp == 0 then
       if not (g and getid(g)==id_glue) or a~=0 then
-        local p = node_new(id_penalty)
+        local p = node_copy(pen_skel)
         if a<-10000 then a = -10000 elseif a>10000 then a = 10000 end
         setfield(p, 'penalty', a)
         head = insert_before(head, Np.first, p)
         Bp[1]=p
-         set_attr(p, attr_icflag, KINSOKU)
       end
    else for _, v in pairs(Bp) do add_penalty(v,a) end
    end
@@ -673,30 +682,36 @@ local function handle_penalty_suppress(post, pre, g)
    local a = (pre or 0) + (post or 0)
    if #Bp == 0 then
       if g and getid(g)==id_glue then
-        local p = node_new(id_penalty)
+        local p = node_copy(pen_skel)
         setfield(p, 'penalty', 10000); head = insert_before(head, Np.first, p)
         Bp[1]=p
-         set_attr(p, attr_icflag, KINSOKU)
       end
    else for _, v in pairs(Bp) do add_penalty(v,a) end
    end
 end
 
 -- 和文文字間の JFM glue を node 化
-local function new_jfm_glue(m, bc, ac)
--- bc, ac: char classes
-   local g, d = m.char_type[bc][ac], 0
-   local n
-   if g then
-      n,d = node_copy(g[2]), g[3]
-      if g[1] then
-        local f = node_new(id_glue)
-        set_attr(f, attr_icflag, g[4])
-        setfield(f, 'spec', n)
-        return f, d
+local new_jfm_glue
+do
+   local FROM_JFM = luatexja.icflag_table.FROM_JFM
+   local glue_skel = {}
+   for i=FROM_JFM-2,FROM_JFM+2 do
+      glue_skel[i]= node_new(id_glue); set_attr(glue_skel[i], attr_icflag, i)
+   end
+   function new_jfm_glue(m, bc, ac)
+      -- bc, ac: char classes
+      local g = m.char_type[bc][ac]
+      if g then
+        if g[1] then
+           local f = node_copy(glue_skel[g[4]])
+           setfield(f, 'spec', node_copy(g[2]))
+           return f, g[3]
+        else
+           return node_copy(g[2]), g[3]
+        end
       end
+      return nil, 0
    end
-   return n, d
 end
 
 -- Nq.last (kern w) .... (glue/kern g) Np.first
@@ -709,7 +724,7 @@ end
 
 
 -------------------- 和文文字間空白量の決定
-
+local null_skip_table = {0, 0, 0}
 -- get kanjiskip
 local get_kanjiskip
 local get_kanjiskip_normal, get_kanjiskip_jfm
@@ -733,13 +748,13 @@ do
         local gx = node_new(id_glue_spec);
         setfield(gx, 'stretch_order', 0); setfield(gx, 'shrink_order', 0)
         local pm, qm = Np.met, Nq.met
-        local bk = qm.kanjiskip or {0, 0, 0}
+        local bk = qm.kanjiskip or null_skip_table
         if (pm.char_type==qm.char_type) and (qm.var==pm.var) then
            setfield(gx, 'width', bk[1])
            setfield(gx, 'stretch', bk[2])
            setfield(gx, 'shrink', bk[3])
         else
-           local ak = pm.kanjiskip or {0, 0, 0}
+           local ak = pm.kanjiskip or null_skip_table
            setfield(gx, 'width', round(diffmet_rule(bk[1], ak[1])))
            setfield(gx, 'stretch', round(diffmet_rule(bk[2], ak[2])))
            setfield(gx, 'shrink', -round(diffmet_rule(-bk[3], -ak[3])))
@@ -859,7 +874,7 @@ do
         g = node_new(id_glue)
         local gx = node_new(id_glue_spec);
         setfield(gx, 'stretch_order', 0); setfield(gx, 'shrink_order', 0)
-        local bk = Nn.met.xkanjiskip or {0, 0, 0}
+        local bk = Nn.met.xkanjiskip or null_skip_table
         setfield(gx, 'width', bk[1])
         setfield(gx, 'stretch', bk[2])
         setfield(gx, 'shrink', bk[3])
@@ -889,7 +904,7 @@ end
 local function handle_np_jachar(mode)
    local qid = Nq.id
    if qid==id_jglyph or ((qid==id_pbox or qid==id_pbox_w) and Nq.met) then
-       local g = non_ihb_flag and calc_ja_ja_glue() or get_kanjiskip() -- M->K
+      local g = non_ihb_flag and calc_ja_ja_glue() or get_kanjiskip() -- M->K
       handle_penalty_normal(Nq.post, Np.pre, g); real_insert(g)
    elseif Nq.met then  -- qid==id_hlist
       local g = non_ihb_flag and get_OA_skip() or get_kanjiskip() -- O_A->K
@@ -982,8 +997,7 @@ local function handle_list_tail(mode)
       -- Insert \jcharwidowpenalty
       Bp = widow_Bp; Np = widow_Np
       if Np.first then
-        handle_penalty_normal(0,
-                              table_current_stack[JWP] or 0)
+        handle_penalty_normal(0,table_current_stack[JWP] or 0)
       end
    else
       -- the current list is the contents of a hbox
@@ -1028,39 +1042,35 @@ do
    local dir_tate = luatexja.dir_table.dir_tate
    local attr_yablshift = luatexbase.attributes['ltj@yablshift']
    local attr_tablshift = luatexbase.attributes['ltj@tablshift']
+   local table_pool = {
+      {}, {}, {first=nil},
+      { auto_kspc=nil, auto_xspc=nil, char=nil, class=nil,
+       first=nil, id=nil, last=nil, met=nil, nuc=nil,
+       post=nil, pre=nil, xspc=nil, }, 
+      { auto_kspc=nil, auto_xspc=nil, char=nil, class=nil,
+       first=nil, id=nil, last=nil, met=nil, nuc=nil,
+       post=nil, pre=nil, xspc=nil, },
+   }
    init_var = function (mode,dir)
       -- 1073741823: max_dimen
-      Bp, widow_Bp, widow_Np = {}, {}, {first = nil}
+      Bp, widow_Bp, widow_Np, Np, Nq
+        = table_pool[1], table_pool[2], table_pool[3], table_pool[4], table_pool[5]
+      for i=1,5 do for j,_ in pairs(table_pool[i]) do table_pool[i][j]=nil end end
       table_current_stack = ltjs.table_current_stack
 
-      list_dir = ltjs.list_dir or dir_yoko
+      list_dir, tex_dir = (ltjs.list_dir or dir_yoko), (dir or 'TLT')
       local is_dir_tate = list_dir==dir_tate
       capsule_glyph = is_dir_tate and ltjw.capsule_glyph_tate or ltjw.capsule_glyph_yoko
       attr_ablshift = is_dir_tate and attr_tablshift or attr_yablshift
 
-      tex_dir = dir or 'TLT'
-      kanji_skip = node_new(id_glue)
       setfield(kanji_skip, 'spec', skip_table_to_spec(KSK))
-      set_attr(kanji_skip, attr_icflag, KANJI_SKIP)
       get_kanjiskip = (getfield(getfield(kanji_skip, 'spec'), 'width') == 1073741823)
         and get_kanjiskip_jfm or get_kanjiskip_normal
 
-      xkanji_skip = node_new(id_glue)
       setfield(xkanji_skip, 'spec', skip_table_to_spec(XSK))
-      set_attr(xkanji_skip, attr_icflag, XKANJI_SKIP)
       get_xkanjiskip = (getfield(getfield(xkanji_skip, 'spec'), 'width') == 1073741823)
         and get_xkanjiskip_jfm or get_xkanjiskip_normal
 
-      Np = {
-        auto_kspc=nil, auto_xspc=nil, char=nil, class=nil,
-        first=nil, id=nil, last=nil, met=nil, nuc=nil,
-        post=nil, pre=nil, xspc=nil,
-      }
-      Nq = {
-        auto_kspc=nil, auto_xspc=nil, char=nil, class=nil,
-        first=nil, id=nil, last=nil, met=nil, nuc=nil,
-        post=nil, pre=nil, xspc=nil,
-      }
       if mode then
         -- the current list is to be line-breaked:
         -- hbox from \parindent is skipped.
@@ -1082,8 +1092,9 @@ end
 local tex_set_attr = tex.setattribute
 local function cleanup(mode)
    -- adjust attr_icflag for avoiding error
-   tex_set_attr('global', attr_icflag, 0)
-   node_free(kanji_skip); node_free(xkanji_skip)
+   if tex.getattribute(attr_icflag)~=0 then tex_set_attr('global', attr_icflag, 0) end
+   node_free(getfield(kanji_skip, 'spec'))
+   node_free(getfield(xkanji_skip, 'spec'))
    if mode then
       local h = node_next(head)
       if getid(h) == id_penalty and getfield(h, 'penalty') == 10000 then
@@ -1103,22 +1114,22 @@ function main(ahead, mode, dir)
    head = ahead;
    local lp, last, par_indented = init_var(mode,dir)
    lp = calc_np(last, lp)
-   if lp then
+   if Np then
       handle_list_head(par_indented)
       lp = calc_np(last,lp); while Np do
-        adjust_nq();
-        local pid, pm = Np.id, Np.met
-        -- 挿入部
-        if pid == id_jglyph then
-           handle_np_jachar(mode)
-        elseif pm then
-           if pid==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
-        lp = calc_np(last,lp)
+        adjust_nq();
+        local pid, pm = Np.id, Np.met
+        -- 挿入部
+        if pid == id_jglyph then
+           handle_np_jachar(mode)
+        elseif pm then
+           if pid==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
+        lp = calc_np(last,lp)
       end
       handle_list_tail(mode)
    end