OSDN Git Service

Merge branch 'kmaeda-manual' into kitagawa_test
[luatex-ja/luatexja.git] / src / luatexja / jfmglue.lua
index 8aec0fd..5163c91 100644 (file)
@@ -73,6 +73,7 @@ local max_dimen = 1073741823
 
 local ltjs_get_penalty_table = ltjs.get_penalty_table
 local ltjs_get_skip_table = ltjs.get_skip_table
+local ltjf_find_char_class = ltjf.find_char_class
 local ltjf_font_metric_table = ltjf.font_metric_table
 local ltjf_metrics = ltjf.metrics
 local box_stack_level
@@ -81,7 +82,7 @@ local par_indented -- is the paragraph indented?
 -------------------- Helper functions
 
 -- This function is called only for acquiring `special' characters.
-local function find_char_class(c,m)
+local function fast_find_char_class(c,m)
    return m.chars[c] or 0
 end
 
@@ -245,6 +246,106 @@ local function calc_np_pbox()
    check_next_ickern()
 end
 
+local calc_np_auxtable = {
+   [id_glyph] = function() 
+                  Np.first = lp
+                  if lp.font == has_attr(lp, attr_curjfnt) then 
+                     Np.id = id_jglyph 
+                  else 
+                     Np.id = id_glyph 
+                  end
+                  Np.first = lp; Np.nuc = lp; set_attr_icflag_processed(lp)
+                  lp = node_next(lp); check_next_ickern(); return true
+               end,
+   [id_hlist] = function() 
+                  Np.first = lp; Np.last = lp; Np.nuc = lp; 
+                  set_attr_icflag_processed(lp)
+                  if lp.shift~=0 then 
+                     Np.id = id_box_like
+                  else 
+                     Np.id = id_hlist 
+                  end
+                  lp = node_next(lp); return true
+               end,
+   [id_vlist] = function()
+                  Np.first = lp; Np.nuc = lp; Np.last = lp;
+                  Np.id = id_box_like; set_attr_icflag_processed(lp); 
+                  lp = node_next(lp); return true
+               end,
+   [id_rule] = function()
+                 Np.first = lp; Np.nuc = lp; Np.last = lp;
+                 Np.id = id_box_like; set_attr_icflag_processed(lp); 
+                 lp = node_next(lp); return true
+              end,
+   [id_ins] = function() 
+                set_attr_icflag_processed(lp); lp = node_next(lp)
+                return false
+             end,
+   [id_mark] = function() 
+                 set_attr_icflag_processed(lp); lp = node_next(lp)
+                 return false
+              end,
+   [id_adjust] = function() 
+                   set_attr_icflag_processed(lp); lp = node_next(lp)
+                   return false
+                end,
+   [id_disc] = function()
+                 Np.first = lp; Np.nuc = lp; set_attr_icflag_processed(lp); 
+                 Np.last = lp; Np.id = id_disc; lp = node_next(lp); return true
+              end,
+   [id_whatsit] = function() 
+                    if lp.subtype==sid_user and lp.user_id==30111 then
+                       local lq = node_next(lp)
+                       head = node_remove(head, lp); node_free(lp); lp = lq; ihb_flag = true
+                    else
+                       set_attr_icflag_processed(lp); lp = node_next(lp)
+                    end
+                    return false
+                 end,
+   [id_math] = function()
+                 Np.first = lp; Np.nuc = lp; 
+                 set_attr_icflag_processed(lp); lp  = node_next(lp) 
+                 while lp.id~=id_math do 
+                    set_attr_icflag_processed(lp); lp  = node_next(lp) 
+                 end
+                 set_attr_icflag_processed(lp); 
+                 Np.last = lp; Np.id = id_math; lp = node_next(lp); 
+                 return true
+              end,
+   [id_glue] = function()
+                 Np.first = lp; Np.nuc = lp; set_attr_icflag_processed(lp); 
+                 Np.last = lp; Np.id = id_glue; lp = node_next(lp); return true
+              end,
+   [id_kern] = function() 
+                 Np.first = lp
+                 if lp.subtype==2 then
+                    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(); 
+                 else
+                    Np.id = id_kern; set_attr_icflag_processed(lp);
+                    Np.last = lp; lp = node_next(lp)
+                 end
+                 return true
+              end,
+   [id_penalty] = function()
+                    Bp[#Bp+1] = lp; set_attr_icflag_processed(lp); 
+                    lp = node_next(lp); return false
+                 end,
+   [13] = function()
+                 Np.first = lp; Np.nuc = lp; Np.last = lp;
+                 Np.id = id_box_like; set_attr_icflag_processed(lp); 
+                 lp = node_next(lp); return true
+              end,
+}
+
 local function calc_np()
    -- We assume lp = node_next(Np.last)
    local lpi, lpa, Nr
@@ -252,58 +353,16 @@ local function calc_np()
    Nq = Np; Np = Nr
    for k in pairs(Bp) do Bp[k] = nil end
    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
+   while lp ~= last do
+      lpa = has_attr(lp, attr_icflag) or 0
+      if lpa>=PACKED then
         if lpa == BOXBDD then
            local lq = node_next(lp)
            head = node_remove(head, lp); node_free(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); 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); node_free(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; lp  = node_next(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
+      elseif calc_np_auxtable[lp.id]() then return end
    end
-   set_attr_icflag_processed(lp); Np.last = lp; Np.id = lpi; lp = node_next(lp)
+   Np = nil; return
 end
 
 -- extract informations from Np
@@ -312,25 +371,29 @@ end
 --            "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 function set_np_xspc_jachar(x)
    local z = ltjf_font_metric_table[x.font]
+   local c = x.char
+   local cls = ltjf_find_char_class(c, z)
+   local m = ltjf_metrics[z.jfm]
+   set_attr(x, attr_jchar_class, cls)
+   Np.class = cls
+   Np.char = c
    Np.size= z.size
-   Np.met = ltjf_metrics[z.jfm]
+   Np.met = m
    Np.var = z.var
    Np.pre = ltjs_get_penalty_table('pre', c, 0, box_stack_level)
    Np.post = ltjs_get_penalty_table('post', c, 0, box_stack_level)
-   z = find_char_class('lineend', Np.met)
-   local y = Np.met.size_cache[Np.size].char_type[Np.class]
+   z = fast_find_char_class('lineend', m)
+   local y = m.size_cache[Np.size].char_type[Np.class]
    if y.kern and y.kern[z] then 
       Np.lend = y.kern[z]
    else 
       Np.lend = 0 
    end
    y = ltjs_get_penalty_table('xsp', c, 3, box_stack_level)
-   Np.xspc_before = (y>=2)
-   Np.xspc_after  = (y%2==1)
+   Np.xspc_before = (y%2==1)
+   Np.xspc_after  = (y>=2)
    Np.auto_kspc = (has_attr(x, attr_autospc)==1)
    Np.auto_xspc = (has_attr(x, attr_autoxspc)==1)
 end
@@ -365,7 +428,7 @@ end
 local function extract_np()
    local x = Np.nuc
    if Np.id ==  id_jglyph then
-      set_np_xspc_jachar(x.char, x)
+      set_np_xspc_jachar(x)
    elseif Np.id == id_glyph then
       set_np_xspc_alchar(x.char, x, ligature_head)
    elseif Np.id == id_hlist then
@@ -373,7 +436,7 @@ local function extract_np()
       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)
+              set_np_xspc_jachar(first_char)
            else
               set_np_xspc_alchar(first_char.char,first_char, ligature_head)
            end
@@ -384,7 +447,7 @@ local function extract_np()
       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)
+              set_np_xspc_jachar(first_char)
            else
               set_np_xspc_alchar(first_char.char,first_char, ligature_head)
            end
@@ -395,7 +458,7 @@ local function extract_np()
       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)
+              set_np_xspc_jachar(first_char)
            else
               set_np_xspc_alchar(first_char.char,first_char, ligature_head)
            end
@@ -411,7 +474,7 @@ end
 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)
+        set_np_xspc_jachar(last_char, ligature_after)
       else
         set_np_xspc_alchar(last_char.char,last_char, ligature_after)
       end
@@ -452,7 +515,7 @@ local function handle_penalty_normal(post, pre, g)
         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; set_attr(p, attr_icflag, KINSOKU)
+        table_insert(Bp, p); set_attr(p, attr_icflag, KINSOKU)
       end
    else for i, v in pairs(Bp) do add_penalty(v,a) end
    end
@@ -466,7 +529,7 @@ local function handle_penalty_always(post, pre, g)
         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; set_attr(p, attr_icflag, KINSOKU)
+        table_insert(Bp, p); set_attr(p, attr_icflag, KINSOKU)
       end
    else for i, v in pairs(Bp) do add_penalty(v,a) end
    end
@@ -478,7 +541,7 @@ local function handle_penalty_suppress(post, pre, g)
       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; set_attr(p, attr_icflag, KINSOKU)
+        table_insert(Bp, p); set_attr(p, attr_icflag, KINSOKU)
       end
    else for i, v in pairs(Bp) do add_penalty(v,a) end
    end
@@ -605,8 +668,8 @@ local function calc_ja_ja_glue()
       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),
+                            fast_find_char_class('diffmet',Nq.met))
+      local h = new_jfm_glue(Np, fast_find_char_class('diffmet',Np.met),
                             Np.class)
       return calc_ja_ja_aux(g,h)
    end
@@ -649,7 +712,7 @@ local function get_OA_skip()
    if not ihb_flag then
       local c
       if Nq.id == id_math then c = -1 else c = 'jcharbdd' end
-      return new_jfm_glue(Np, find_char_class(c,Np.met), Np.class)
+      return new_jfm_glue(Np, fast_find_char_class(c,Np.met), Np.class)
    else return nil
    end
 end
@@ -657,7 +720,7 @@ local function get_OB_skip()
    if not ihb_flag then
       local c
       if Np.id == id_math then c = -1 else c = 'jcharbdd' end
-      return new_jfm_glue(Nq, Nq.class, find_char_class(c,Nq.met))
+      return new_jfm_glue(Nq, Nq.class, fast_find_char_class(c,Nq.met))
    else return nil
    end
 end
@@ -755,7 +818,7 @@ local function handle_list_tail()
    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))
+        local g = new_jfm_glue(Np, Np.class, fast_find_char_class('boxbdd',Np.met))
         if g then
            set_attr(g, attr_icflag, BOXBDD)
            head = node_insert_after(head, Np.last, g)
@@ -772,9 +835,9 @@ local function handle_list_head()
       if not ihb_flag then
         local g
         if par_indented then
-           g = new_jfm_glue(Np, find_char_class('parbdd',Np.met), Np.class)
+           g = new_jfm_glue(Np, fast_find_char_class('parbdd',Np.met), Np.class)
         else
-           g = new_jfm_glue(Np, find_char_class('boxbdd',Np.met), Np.class)
+           g = new_jfm_glue(Np, fast_find_char_class('boxbdd',Np.met), Np.class)
         end
         if g then
            set_attr(g, attr_icflag, BOXBDD)
@@ -815,7 +878,7 @@ local function init_var()
       last=node.tail(head)
    else 
       -- the current list is the contents of a hbox:
-      -- insert a sentinel
+      -- insert a sentinelEG
       last=node.tail(head); local g = node_new(id_kern)
       node_insert_after(head, last, g); last = g
    end