OSDN Git Service

Rewrite the process of JFM glue and \[x]kanjiskip (INCOMPLETE)
authorHironori Kitagawa <h_kitagawa2001@yahoo.co.jp>
Sun, 8 May 2011 12:49:00 +0000 (21:49 +0900)
committerHironori Kitagawa <h_kitagawa2001@yahoo.co.jp>
Sun, 8 May 2011 12:49:00 +0000 (21:49 +0900)
src/luatexja-core-aux.lua [deleted file]
src/luatexja-core.lua
src/luatexja-core.sty
src/luatexja-jfmglue.lua [new file with mode: 0644]
src/luatexja-jfont.lua
src/luatexja-kinsoku.tex
src/luatexja-plain.tex
src/luatexja-xkanji.lua
test/test04-jfm.log [new file with mode: 0644]
test/test04-jfm.pdf
test/test04-jfm.tex

diff --git a/src/luatexja-core-aux.lua b/src/luatexja-core-aux.lua
deleted file mode 100644 (file)
index 4a9eeaa..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-
--- gb: 前側の和文文字 b 由来の glue/kern (maybe nil)
--- ga: 後側の和文文字 a 由来の glue/kern (maybe nil)
--- 両者から,b と a の間に入る glue/kern を計算する
-
-function ltj.calc_between_two_jchar_aux_large(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   = math.max(gb.spec.width,ga.spec.width)
-        gb.spec.stretch = math.max(gb.spec.stretch,ga.spec.shrink)
-        gb.spec.shrink  = math.min(gb.spec.shrink,ga.spec.shrink)
-        return gb
-      elseif k == 'kernkern' then
-        -- 両方とも kern.
-        gb.kern = math.max(gb.kern,ga.kern)
-        return gb
-      elseif k == 'kernglue' then 
-        -- gb: kern, ga: glue
-        ga.spec.width   = math.max(gb.kern,ga.spec.width)
-        ga.spec.stretch = math.max(ga.spec.stretch,0)
-        ga.spec.shrink  = math.min(ga.spec.shrink,0)
-        return ga
-      else
-        -- gb: glue, ga: kern
-        gb.spec.width   = math.max(ga.kern,gb.spec.width)
-        gb.spec.stretch = math.max(gb.spec.stretch,0)
-        gb.spec.shrink  = math.min(gb.spec.shrink,0)
-        return gb
-      end
-   end
-end
-function ltj.calc_between_two_jchar_aux_small(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   = math.min(gb.spec.width,ga.spec.width)
-        gb.spec.stretch = math.min(gb.spec.stretch,ga.spec.shrink)
-        gb.spec.shrink  = math.max(gb.spec.shrink,ga.spec.shrink)
-        return gb
-      elseif k == 'kernkern' then
-        -- 両方とも kern.
-        gb.kern = math.min(gb.kern,ga.kern)
-        return gb
-      elseif k == 'kernglue' then 
-        -- gb: kern, ga: glue
-        ga.spec.width   = math.min(gb.kern,ga.spec.width)
-        ga.spec.stretch = math.min(ga.spec.stretch,0)
-        ga.spec.shrink  = math.max(ga.spec.shrink,0)
-        return ga
-      else
-        -- gb: glue, ga: kern
-        gb.spec.width   = math.min(ga.kern,gb.spec.width)
-        gb.spec.stretch = math.min(gb.spec.stretch,0)
-        gb.spec.shrink  = math.max(gb.spec.shrink,0)
-        return gb
-      end
-   end
-end
-function ltj.calc_between_two_jchar_aux_average(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   = tex.round((gb.spec.width+ga.spec.width)/2)
-        gb.spec.stretch = tex.round((gb.spec.stretch+ga.spec.shrink)/2)
-        gb.spec.shrink  = tex.round((gb.spec.shrink+ga.spec.shrink)/2)
-        return gb
-      elseif k == 'kernkern' then
-        -- 両方とも kern.平均をとる
-        gb.kern = tex.round((gb.kern+ga.kern)/2)
-        return gb
-      elseif k == 'kernglue' then 
-        -- gb: kern, ga: glue
-        ga.spec.width   = tex.round((gb.kern+ga.spec.width)/2)
-        ga.spec.stretch = tex.round(ga.spec.stretch/2)
-        ga.spec.shrink  = tex.round(ga.spec.shrink/2)
-        return ga
-      else
-        -- gb: glue, ga: kern
-        gb.spec.width   = tex.round((ga.kern+gb.spec.width)/2)
-        gb.spec.stretch = tex.round(gb.spec.stretch/2)
-        gb.spec.shrink  = tex.round(gb.spec.shrink/2)
-        return gb
-      end
-   end
-end
-function ltj.calc_between_two_jchar_aux_both(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 
-        gb.spec.width   = tex.round((gb.spec.width+ga.spec.width))
-        gb.spec.stretch = tex.round((gb.spec.stretch+ga.spec.shrink))
-        gb.spec.shrink  = tex.round((gb.spec.shrink+ga.spec.shrink))
-        return gb
-      elseif k == 'kernkern' then
-        gb.kern = tex.round((gb.kern+ga.kern))
-        return gb
-      elseif k == 'kernglue' then 
-        -- gb: kern, ga: glue
-        ga.spec.width   = tex.round((gb.kern+ga.spec.width))
-        return ga
-      else
-        -- gb: glue, ga: kern
-        gb.spec.width   = tex.round((ga.kern+gb.spec.width))
-        return gb
-      end
-   end
-end
-
-ltj.calc_between_two_jchar_aux=ltj.calc_between_two_jchar_aux_average
index de83c2e..ca6391c 100644 (file)
@@ -35,6 +35,13 @@ local rgjc_char_to_range     = ltj.int_char_to_range
 local rgjc_is_ucs_in_japanese_char = ltj.int_is_ucs_in_japanese_char
 local ljfm_find_char_class = ltj.int_find_char_class
 
+
+local ITALIC = 1
+local TEMPORARY = 2
+local FROM_JFM = 3
+local KINSOKU = 4
+local LINE_END = 5
+
 ------------------------------------------------------------------------
 -- naming:
 --    ltj.ext_... : called from \directlua{}
@@ -95,6 +102,8 @@ local function is_japanese_glyph_node(p)
    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
 
 ------------------------------------------------------------------------
 -- CODE FOR STACK TABLE FOR CHARACTER PROPERTIES (prefix: cstb)
@@ -126,7 +135,7 @@ function ltj.ext_set_stack_table(g,m,c,p,lb,ub)
            {"I'm going to use 0 instead of that illegal code value."})
      p=0
   elseif c<-1 or c>0x10FFFF then
-     ltj.error('Invalid character code (' .. 
+     ltj.error('Invalid character code (' .. c
               .. '), should in the range -1.."10FFFF.',{})
      return 
   elseif not charprop_stack_table[i][c] then 
@@ -146,6 +155,7 @@ local function cstb_get_penalty_table(m,c)
   if i then i=i[m] end
   return i or 0
 end
+ltj.int_get_penalty_table = cstb_get_penalty_table
 
 local function cstb_get_inhibit_xsp_table(c)
   local i = charprop_stack_table[tex.getcount('ltj@@stack')][c]
@@ -171,17 +181,17 @@ function ltj.ext_get_parameter_unary(k)
    elseif k == 'jcharwidowpenalty' then
       tex.write(tex.getcount('jcharwidowpenalty'))
    elseif k == 'autospacing' then
-      tex.write(tostring(ltj.auto_spacing))
+      tex.write(tex.getattribute('ltj@autospc'))
    elseif k == 'autoxspacing' then
-      tex.write(tostring(ltj.auto_xspacing))
+      tex.write(tex.getattribute('ltj@autoxspc'))
    elseif k == 'differentjfm' then
-      if ltj.calc_between_two_jchar_aux==ltj.calc_between_two_jchar_aux_large then
+      if ltj.ja_diffmet_rule == math.max then
         tex.write('large')
-      elseif ltj.calc_between_two_jchar_aux==ltj.calc_between_two_jchar_aux_small then
+      elseif ltj.ja_diffmet_rule == math.min then
         tex.write('small')
-      elseif ltj.calc_between_two_jchar_aux==ltj.calc_between_two_jchar_aux_average then
+      elseif ltj.ja_diffmet_rule == math.two_average then
         tex.write('average')
-      elseif ltj.calc_between_two_jchar_aux==ltj.calc_between_two_jchar_aux_both then
+      elseif ltj.ja_diffmet_rule == math.two_add then
         tex.write('both')
       else -- This can't happen.
         tex.write('???')
@@ -260,7 +270,7 @@ local function main1_suppress_hyphenate_ja(head)
       end
    end
    lang.hyphenate(head)
-   return head -- 共通化のため値を返す
+   return head -- 互換性のために値を返す
 end
 
 -- CALLBACKS
@@ -279,266 +289,6 @@ luatexbase.add_to_callback('hyphenate',
 
 
 ------------------------------------------------------------------------
--- MAIN PROCESS STEP 2: insert glue/kerns from JFM (prefix: main2)
-------------------------------------------------------------------------
-
--- EXT: for \inhibitglue
-function ltj.ext_create_inhibitglue_node()
-   local g=node_new(id_whatsit, node.subtype('user_defined'))
-   g.user_id=30111; g.type=number; g.value=1; node.write(g)
-end
-
-
-local function main2_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, nil, nil
-   end
-end
-
-local function main2_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
-
--- return value: g (glue/kern from JFM), w (width of 'lineend' kern)
-local function main2_calc(qs,qm,qv,q,p,last,ihb_flag)
-   -- q, p: node (possibly null)
-   local ps, pm, pv, g, h
-   local w = 0
-   if (not p) or p==last then
-      -- q is the last node
-      if not qm then
-        return nil, 0
-      elseif not ihb_flag then 
-        g=main2_new_jfm_glue(qs,qm,
-                           has_attr(q,attr_jchar_class),
-                               ljfm_find_char_class('boxbdd',qm))
-      end
-   elseif qs==0 then
-      -- p is the first node etc.
-      ps, pm, pv = main2_find_size_metric(p)
-      if not pm then
-        return nil, 0
-      elseif not ihb_flag then 
-        g=main2_new_jfm_glue(ps,pm,
-                               ljfm_find_char_class('boxbdd',pm),
-                               has_attr(p,attr_jchar_class))
-      end
-   else -- p and q are not nil
-      ps, pm, pv = main2_find_size_metric(p)
-      if ihb_flag or ((not pm) and (not qm)) then 
-        g = nil
-      elseif (qs==ps) and (qm==pm) and (qv==pv) then 
-        -- Both p and q are Japanese glyph nodes, and same metric and size
-        g = main2_new_jfm_glue(ps,pm,
-                               has_attr(q,attr_jchar_class),
-                               has_attr(p,attr_jchar_class))
-      elseif not qm then
-        -- q is not a Japanese glyph node
-        g = main2_new_jfm_glue(ps,pm,
-                               ljfm_find_char_class('jcharbdd',pm),
-                               has_attr(p,attr_jchar_class))
-      elseif not pm then
-        -- p is not a Japanese glyph node
-        g = main2_new_jfm_glue(qs,qm,
-                               has_attr(q,attr_jchar_class),
-                               ljfm_find_char_class('jcharbdd',qm))
-      else
-        g = main2_new_jfm_glue(qs,qm,
-                               has_attr(q,attr_jchar_class),
-                               ljfm_find_char_class('diffmet',qm))
-        h = main2_new_jfm_glue(ps,pm,
-                               ljfm_find_char_class('diffmet',pm),
-                               has_attr(p,attr_jchar_class))
-        g = ltj.calc_between_two_jchar_aux(g,h)
-      end
-   end
-   if g then node.set_attribute(g, attr_icflag, 3) end
-   if qm then
-      local x = ljfm_find_char_class('lineend', qm)
-      if x~=0  then
-        qv = ltj.metrics[qm].char_type[has_attr(q,attr_jchar_class)]
-        if qv.kern and qv.kern[x] then 
-           w = round(qs*qv.kern[x])
-        end
-      end
-   end
-
-   return g, w
-end
-
-local function main2_between_two_char(head,q,p,p_bp,ihb_flag,last)
-   local qs = 0; local g, w
-   local qm = nil, qv
-   if q then
-      qs, qm, qv = main2_find_size_metric(q)
-   end
-   g, w = main2_calc(qs, qm, qv, q, p, last, ihb_flag)
-   if w~=0 and (not p_bp) then
-      p_bp = node_new(id_penalty); p_bp.penalty = 0
-      head = node_insert_before(head, p, p_bp)
-   end
-   if g then
-      if g.id==id_kern then 
-        g.kern = round(g.kern - w)
-      else
-        g.spec.width = round(g.spec.width - w)
-      end
-      head = node_insert_before(head, p, g)
-   elseif w~=0 then
-      g = node_new(id_kern); g.kern = -w; g.subtype = 1
-      node.set_attribute(g,attr_icflag,2)
-      head = node_insert_before(head, p, g)
-      -- this g might be replaced by \[x]kanjiskip in step 3.
-   end
-   if w~=0 then
-      g = node_new(id_kern); g.kern = w; g.subtype = 0
-      head = node_insert_before(head, p_bp, g)
-   end
-return head, p_bp
-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 main2_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
-
--- next three functions deal with inserting penalty by kinsoku.
-local function main2_add_penalty_before(head,p,p_bp,pen)
-   if p_bp then
-      p_bp.penalty = p_bp.penalty + pen
-   else -- we must create a new penalty node
-      local g = node_new(id_penalty); g.penalty = pen
-      local q = node_prev(p)
-      if q then
-        if has_attr(q, attr_icflag) ~= 3 then
-           q = p
-        end
-        return node_insert_before(head, q, g)
-      end
-   end
-   return head
-end
-
-local function main2_add_kinsoku_penalty(head,p,p_bp)
-   local c = p.char
-   local e = cstb_get_penalty_table('pre',c)
-   if e~=0 then
-      head = main2_add_penalty_before(head, p, p_bp, e)
-   end
-   e = cstb_get_penalty_table('post',c)
-   if e~=0 then
-      local q = node_next(p)
-      if q and q.id==id_penalty then
-        q.penalty = q.penalty + e
-        return false
-      else 
-        q = node_new(id_penalty); q.penalty = e
-        node_insert_after(head,p,q)
-        return true
-      end
-   end
-end
-
-local function main2_add_widow_penalty(head,widow_node,widow_bp)
-   if not widow_node then 
-      return head
-   else
-      return main2_add_penalty_before(head, widow_node,
-                 widow_bp, tex.getcount('jcharwidowpenalty'))
-   end
-end
-
-local depth=""
-
--- Insert jfm glue: main routine
--- mode = true iff insert_jfm_glue is called from pre_linebreak_filter
-local function main2_insert_jfm_glue(head, mode)
-   local p = head
-   local p_bp = nil -- p と直前の文字の間の penalty node
-   local q = nil  -- the previous node of p
-   local widow_node = nil -- 最後の「句読点扱いでない」和文文字
-   local widow_bp = nil -- \jcharwidowpenalty 挿入位置
-   local last -- the sentinel 
-   local ihb_flag = false -- is \inhibitglue specified?
-   local g
-   -- initialization
-   if not p then return head 
-   elseif mode then
-      while p and main2_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); g = node_new('kern')
-      node_insert_after(head,last,g); last = g
-   end
-   -- main loop
-   while q~=last do
-      if p.id==id_whatsit and p.subtype==node.subtype('user_defined')
-         and p.user_id==30111 then
-        g = p; p = node_next(p)
-        ihb_flag = true; head, p = node.remove(head, g)
-      else
-        head, p_bp = main2_between_two_char(head, q, p, p_bp, ihb_flag, last)
-        q=p; ihb_flag=false
-        if is_japanese_glyph_node(p) then
-           if cstb_get_penalty_table('kcat',p.char)%2~=1 then
-              widow_node = p; widow_bp = p_bp
-           end
-           if main2_add_kinsoku_penalty(head, p, p_bp) then
-              p_bp = node_next(p); p = p_bp
-           else p_bp = nil
-           end
-        else p_bp = nil
-        end
-        p=node_next(p)
-      end
-   end
-   if mode then
-      -- Insert \jcharwidowpenalty
-      head = main2_add_widow_penalty(head, widow_node, widow_bp)
-      -- cleanup
-      p = node_prev(last)
-      if p and p.id==id_kern and has_attr(p,attr_icflag)==2 then
-        head = node.remove(head, p)
-      end
-   else
-      head = node.remove(head, last)
-   end
-   return head
-end
-
-
-------------------------------------------------------------------------
 -- MAIN PROCESS STEP 4: width of japanese chars (prefix: main4)
 ------------------------------------------------------------------------
 
@@ -610,8 +360,9 @@ end
 -- mode = true iff main_process is called from pre_linebreak_filter
 local function main_process(head, mode)
    local p = head
-   p = main2_insert_jfm_glue(p,mode)
-   p = ltj.int_insert_kanji_skip(p)
+   p = ltj.int_insert_jfm_glue(p,mode)
+   p = ltj.int_insert_kanji_skip(p) 
+   -- off because we write the code of step 2
    p = main4_set_ja_width(p)
    return p
 end
@@ -630,10 +381,11 @@ end
 function debug_show_node_list_X(p,print_fn)
    debug_depth=debug_depth.. '.'
    local k = debug_depth
+   local s
    while p do
       local pt=node_type(p.id)
       if pt == 'glyph' then
-        print_fn(debug_depth.. ' glyph  ', p.subtype, utf.char(p.char), p.font)
+        print_fn(debug_depth.. ' GLYPH  ', p.subtype, utf.char(p.char), p.font)
       elseif pt=='hlist' then
         print_fn(debug_depth.. ' hlist  ', p.subtype, '(' .. print_scaled(p.height)
            .. '+' .. print_scaled(p.depth)
@@ -643,11 +395,33 @@ function debug_show_node_list_X(p,print_fn)
       elseif pt == 'whatsit' then
         print_fn(debug_depth.. ' whatsit', p.subtype)
       elseif pt == 'glue' then
-        print_fn(debug_depth.. ' glue   ', p.subtype, print_spec(p.spec))
+        s = debug_depth.. ' glue   ' ..  p.subtype 
+           .. ' ' ..  print_spec(p.spec)
+        if has_attr(p, attr_icflag)==2 then
+           s = s .. ' (might be replaced)'
+        elseif has_attr(p, attr_icflag)==3 then
+           s = s .. ' (from JFM)'
+        end
+        print_fn(s)
       elseif pt == 'kern' then
-        print_fn(debug_depth.. ' kern   ', p.subtype, print_scaled(p.kern) .. 'pt')
+        s = debug_depth.. ' kern   ' ..  p.subtype
+           .. ' ' .. print_scaled(p.kern) .. 'pt'
+        if has_attr(p, attr_icflag)==ITALIC then
+           s = s .. ' (italic correction)'
+        elseif has_attr(p, attr_icflag)==TEMPORARY then
+           s = s .. ' (might be replaced)'
+        elseif has_attr(p, attr_icflag)==FROM_JFM then
+           s = s .. ' (from JFM)'
+        elseif has_attr(p, attr_icflag)==LINE_END then
+           s = s .. " (from 'lineend' in JFM)"
+        end
+        print_fn(s)
       elseif pt == 'penalty' then
-        print_fn(debug_depth.. ' penalty', p.penalty)
+        s = debug_depth.. ' penalty ' ..  tostring(p.penalty)
+        if has_attr(p, attr_icflag)==KINSOKU then
+           s = s .. ' (for kinsoku)'
+        end
+        print_fn(s)
       else
         print_fn(debug_depth.. ' ' .. node.type(p.id), p.subtype)
       end
@@ -656,7 +430,6 @@ function debug_show_node_list_X(p,print_fn)
 end
 
 
-
 -- callbacks
 luatexbase.add_to_callback('pre_linebreak_filter', 
    function (head,groupcode)
index ac8724c..5c9d43e 100644 (file)
@@ -31,6 +31,8 @@
 \newluatexattribute\ltj@charclass % 
 \newluatexattribute\ltj@yablshift % attribute for \yabaselineshift
 \newluatexattribute\ltj@ykblshift % attribute for \ykbaselineshift
+\newluatexattribute\ltj@autospc   % attribute for autospacing
+\newluatexattribute\ltj@autoxspc  % attribute for autoxspacing
 \newluatexattribute\ltj@icflag    % attribute for italic correction
 \newlanguage\ltj@japanese
 
@@ -49,8 +51,8 @@
     % 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')
-  ltj.loadlua('luatexja-core-aux.lua')
 }
 
 
 % autospacing = <bool> (default: true)
 \define@boolkey[ltj]{japaram}{autospacing}[true]{%
   \ifltj@japaram@autospacing
-    \directlua{ltj.auto_spacing=true}%
+    \directlua{ltj.ext_print_global()}\ltj@autospc=1
   \else
-    \directlua{ltj.auto_spacing=false}%
-  \fi
-  }
+    \directlua{ltj.ext_print_global()}\ltj@autospc=0
+  \fi}
 
 % autoxspacing = <bool> (default: true)
 \define@boolkey[ltj]{japaram}{autoxspacing}[true]{%
   \ifltj@japaram@autoxspacing
-    \directlua{ltj.auto_xspacing=true}%
+    \directlua{ltj.ext_print_global()}\ltj@autoxspc=1
   \else
-    \directlua{ltj.auto_xspacing=false}%
-  \fi
-  }
+    \directlua{ltj.ext_print_global()}\ltj@autoxspc=0
+  \fi}
 
 \define@key[ltj]{japaram}{kanjiskip}{%              % SKIP
   \directlua{ltj.ext_print_global()}\kanjiskip=#1 }
 \define@choicekey*+[ltj]{japaram}{differentjfm}[\ltj@temp\ltj@tempr]%
   {large,small,average,both}{%
   \ifcase\ltj@tempr
-    \directlua{ltj.calc_between_two_jchar_aux=ltj.calc_between_two_jchar_aux_large}\or
-    \directlua{ltj.calc_between_two_jchar_aux=ltj.calc_between_two_jchar_aux_small}\or
-    \directlua{ltj.calc_between_two_jchar_aux=ltj.calc_between_two_jchar_aux_average}\or
-    \directlua{ltj.calc_between_two_jchar_aux=ltj.calc_between_two_jchar_aux_both}%
+    \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}
   \fi
 }{\@PackageWarning{luatexja}{ignored invalid argument '#1' for 'differentjfm'}}
   % large, small, average, both
diff --git a/src/luatexja-jfmglue.lua b/src/luatexja-jfmglue.lua
new file mode 100644 (file)
index 0000000..86fb2ea
--- /dev/null
@@ -0,0 +1,412 @@
+------------------------------------------------------------------------
+-- MAIN PROCESS STEP 2: insert glue/kerns from JFM (prefix: none)
+------------------------------------------------------------------------
+
+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 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 cstb_get_penalty_table = ltj.int_get_penalty_table
+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 p
+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=number; 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
+        node.set_attribute(g, attr_icflag, FROM_JFM)
+        head = node_insert_before(head, p, g)
+      end
+      q_post = cstb_get_penalty_table('post',p.char); chain = true
+   elseif p.id==id_glyph then
+      q_post = cstb_get_penalty_table('post',p.char)
+   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
+        node.set_attribute(g, attr_icflag, TEMPORARY)
+        -- this g might be replaced by \[x]kanjiskip in step 3.
+      else 
+        node.set_attribute(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)
+      node.set_attribute(h, attr_icflag, LINE_END)
+      h.kern = w; h.subtype = 0; node_insert_before(head, p, h)
+   elseif g then
+      node.set_attribute(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; node.set_attribute(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; node.set_attribute(h, attr_icflag, KINSOKU)
+        node_insert_before(head, p, h)
+      end
+      node.set_attribute(g, attr_icflag, FROM_JFM)
+      node_insert_before(head, p, g)
+   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
+
+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
+
+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, cstb_get_penalty_table('pre', p.char))
+      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, cstb_get_penalty_table('pre', p.char))
+      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, cstb_get_penalty_table('post',p.char)
+   if cstb_get_penalty_table('kcat',p.char)%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, cstb_get_penalty_table('pre',p.char))
+      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
+      real_insert(g, w, q_post, false)
+   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
+           node.set_attribute(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 = tex.getcount('jcharwidowpenalty')
+   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 82db6f6..185c369 100644 (file)
@@ -8,6 +8,7 @@ local attr_curjfnt = luatexbase.attributes['ltj@curjfnt']
 local id_glyph = node.id('glyph')
 local id_kern = node.id('kern')
 
+local ITALIC = 1
 ------------------------------------------------------------------------
 -- LOADING JFM (prefix: ljfm)
 ------------------------------------------------------------------------
@@ -38,6 +39,8 @@ function ltj.define_jfm(t)
                  if #v.chars ~= 1 then defjfm_res= nil; return end
               elseif type(w) == 'number' then
                  real_char = true
+              elseif type(w) == 'string' and utf.len(w)==1 then
+                 real_char = true; w = utf.byte(w)
               end
               if not t.chars[w] then
                  t.chars[w] = i
@@ -54,7 +57,7 @@ function ltj.define_jfm(t)
            end
            v.chars = nil
         end
-        if v.kern then
+        if v.kern and v.glue then
            for j,w in pairs(v.glue) do
               if v.kern[j] then defjfm_res= nil; return end
            end
@@ -245,10 +248,9 @@ function ltj.ext_append_italic()
    if p and p.id==id_glyph then
       local f = p.font
       local g = node_new(id_kern)
-      g.subtype = 1; node.set_attribute(g, attr_icflag, 1)
+      g.subtype = 1; node.set_attribute(g, attr_icflag, ITALIC)
       if rgjc_is_ucs_in_japanese_char(p) then
         f = has_attr(p, attr_curjfnt)
-        print(f, p.char)
         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)
index 52672e4..a7c7083 100644 (file)
 \ltjsetparameter{alxspmode={``,preonly}}
 \ltjsetparameter{alxspmode={`',postonly}}
 \ltjsetparameter{alxspmode={`;,postonly}}
-\ltjsetparameter{alxspmode={47,postonly}}
+\ltjsetparameter{alxspmode={44,postonly}}
 \ltjsetparameter{alxspmode={`.,postonly}}
 %  for 8bit Latin
 \ltjsetparameter{alxspmode={"80,allow}}
index 2c70ab0..ddade14 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%"
index 671daa0..0c9abe3 100644 (file)
@@ -6,10 +6,12 @@ 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 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')
@@ -24,14 +26,19 @@ 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
 local xkanji_skip
-local no_skip = 0
-local after_schar = 1
-local after_wchar = 2
-local insert_skip = no_skip
 
 -- (glyph_node nr) ... (node nq) <GLUE> ,,, (node np)
 local np, nq, nrc
@@ -39,6 +46,7 @@ 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 cstb_get_inhibit_xsp_table = ltj.int_get_inhibit_xsp_table
 
@@ -47,16 +55,23 @@ local function is_japanese_glyph_node(p)
    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
+
 -- the following 2 functions are the lowest part.
 -- cx: the Kanji code of np
-local function insert_ascii_kanji_xkskip(head,q,cx)
+local function insert_ascii_kanji_xkskip(q, cx)
    if cstb_get_inhibit_xsp_table(cx)<=1 then return end
    local g = node_new(id_glue)
    g.subtype = 0; g.spec = node.copy(xkanji_skip)
    node_insert_after(head, q, g)
 end
 
-local function insert_kanji_ascii_xkskip(head,q,p)
+local function insert_kanji_ascii_xkskip(q, p)
    local g=true
    local c = p.char
    while p.components and p.subtype 
@@ -88,20 +103,71 @@ local function set_insert_skip_after_achar(p)
   end
 end
 
+local function get_kanji_skip_from_jfm(p)
+   local px = { ltj.font_metric_table[p.font].size, 
+               ltj.font_metric_table[p.font].jfm }
+   local i = ltj.metrics[px[2]].kanjiskip
+   print(p.font, px[1], px[2], ltj.metrics[px[2]].dir, i)
+   if i then
+      return { round(i[1]*px[1]), round(i[2]*px[1]), round(i[3]*px[1]) }
+   else return nil
+   end
+end
+
+local function insert_kanji_skip()
+   print('a', utf.char(np.char))
+   local g = node_new(id_glue); g.subtype=0
+   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 = nil -- incomplete
+      local ak = get_kanji_skip_from_jfm(np)
+      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()-- ???
+      end
+      g.spec = gx
+   else
+      g.spec=node.copy(kanji_skip)
+   end
+   local h = node_prev(np)
+   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_insert_before(head, np, g)
+      else
+        h.spec.width = g.spec.width + h.spec.width
+        h.spec.stretch = g.spec.stretch + h.spec.stretch
+        h.spec.shrink = g.spec.shrink + h.spec.shrink
+      end
+   else
+      node_insert_before(head, np, g)
+   end
+   print('b', utf.char(np.char))
+end
+
 -- When p is a glyph_node ...
-local function insks_around_char(head)
+local function insks_around_char()
    if is_japanese_glyph_node(np) then
       if insert_skip==after_wchar then
-        local g = node_new(id_glue)
-        g.subtype=0; g.spec=node.copy(kanji_skip)
-        node_insert_before(head, np, g)
+        insert_kanji_skip()
       elseif insert_skip==after_schar then
-        insert_ascii_kanji_xkskip(head, nq, np.char)
+        insert_ascii_kanji_xkskip(nq, np.char)
       end
       insert_skip=after_wchar; nrc = np.char
    else
       if insert_skip==after_wchar then
-        insert_kanji_ascii_xkskip(head, nq, np)
+        insert_kanji_ascii_xkskip(nq, np)
       end
       set_insert_skip_after_achar(np)
    end
@@ -152,7 +218,7 @@ local function check_box(box_ptr)
 end 
 
 -- When np is a hlist_node ...
-local function insks_around_hbox(head)
+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
@@ -160,16 +226,14 @@ local function insks_around_hbox(head)
         if is_japanese_glyph_node(first_char) then
            nrc = first_char.char
            if insert_skip==after_schar then 
-              insert_ascii_kanji_xkskip(head, nq, first_char.char)
+              insert_ascii_kanji_xkskip(nq, first_char.char)
            elseif insert_skip==after_wchar then
-              local g = node_new(id_glue)
-              g.subtype = 0; g.spec = node.copy(kanji_skip)
-              node_insert_before(head, np, g)
+              insert_kanji_skip()
            end
            insert_skip = after_wchar
         elseif first_char then
            if insert_skip==after_wchar then
-              insert_kanji_ascii_xkskip(head, nq, first_char)
+              insert_kanji_ascii_xkskip(nq, first_char)
            end
            set_insert_skip_after_achar(first_char)
         end
@@ -193,18 +257,18 @@ local function insks_around_hbox(head)
 end
 
 -- When np is a penalty ...
-local function insks_around_penalty(head)
+local function insks_around_penalty()
    nq = np
 end
 
 -- When np is a kern ...
 -- 
-local function insks_around_kern(head)
+local function insks_around_kern()
    if np.subtype==1 then -- \kern or \/
       local i = has_attr(np, attr_icflag)
-      if not i then -- \kern
+      if not i or i==FROM_JFM then -- \kern
         insert_skip = no_skip
-      elseif i==1 then
+      elseif i==ITALIC or i==LINE_END or i==TEMPORARY then
         nq = np
       end
    elseif np.subtype==2 then 
@@ -214,44 +278,35 @@ local function insks_around_kern(head)
 end
 
 -- When np is a math_node ...
-local function insks_around_math(head)
+local function insks_around_math()
    local g = { char = -1 }
    if (np.subtype==0) and (insert_skip==after_wchar) then
-      insert_kanji_ascii_xkskip(head, nq, g)
+      insert_kanji_ascii_xkskip(nq, g)
       insert_skip = no_skip
    else
       nq = np; set_insert_skip_after_achar(g)
    end
 end
 
-function ltj.int_insert_kanji_skip(head)
-   if ltj.auto_spacing then
-      kanji_skip=tex.skip['kanjiskip']
-   else
-      kanji_skip=node_new(id_glue_spec)
-      kanji_skip.width=0;  kanji_skip.stretch=0; kanji_skip.shrink=0
-   end
-   if ltj.auto_xspacing then
-      xkanji_skip=tex.skip['xkanjiskip']
-   else
-      xkanji_skip=node_new(id_glue_spec)
-      xkanji_skip.width=0;  xkanji_skip.stretch=0; xkanji_skip.shrink=0
-   end
+function ltj.int_insert_kanji_skip(ahead)
+   kanji_skip=tex.skip['kanjiskip']
+   xkanji_skip=tex.skip['xkanjiskip']
+   head = ahead
    np = head; nq = nil; insert_skip = no_skip
    while np do
       if np.id==id_glyph then
         repeat 
-           insks_around_char(head); np=node_next(np)
+           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(head)
+           insks_around_hbox()
         elseif np.id==id_penalty then
-           insks_around_penalty(head)
+           insks_around_penalty()
         elseif np.id==id_kern then
-           insks_around_kern(head)
+           insks_around_kern()
         elseif np.id==id_math then
-           insks_around_math(head)
+           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
@@ -264,4 +319,4 @@ function ltj.int_insert_kanji_skip(head)
       end
    end
    return head
-end
+end
\ No newline at end of file
diff --git a/test/test04-jfm.log b/test/test04-jfm.log
new file mode 100644 (file)
index 0000000..450e5e3
--- /dev/null
@@ -0,0 +1,284 @@
+This is LuaTeX, Version beta-0.71.0-2011050715  (format=luatex 2011.5.7)  8 MAY 2011 21:45
+ restricted \write18 enabled.
+**test04-jfm.tex
+(./test04-jfm.tex
+(/opt/texlive/p2010/../texmf-local/tex/generic/luatexja/luatexja-core.sty
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/luaotfload.sty
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase.sty
+Package: luatexbase 2010/10/06 v0.3 Module utilities for LuaTeX
+(/opt/texlive/p2010/texmf-dist/tex/generic/oberdiek/ifluatex.sty
+Package: ifluatex 2010/03/01 v1.3 Provides the ifluatex switch (HO)
+Package ifluatex Info: LuaTeX detected.
+)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-compat.sty
+Package: luatexbase-compat 2010/10/10 v0.3 Compatibility tools for LuaTeX
+(/opt/texlive/p2010/texmf-dist/tex/generic/oberdiek/ifluatex.sty
+Package ifluatex Info: The package is already loaded.
+))
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-loader.sty
+Package: luatexbase-loader 2010/10/10 v0.3 Lua module loader for LuaTeX
+(/opt/texlive/p2010/texmf-dist/tex/generic/oberdiek/ifluatex.sty
+Package ifluatex Info: The package is already loaded.
+)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-compat.sty)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase.loader.lua))
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-regs.sty
+Package: luatexbase-regs 2010/10/10 v0.3 Registers allocation for LuaTeX
+(/opt/texlive/p2010/texmf-dist/tex/generic/oberdiek/ifluatex.sty
+Package ifluatex Info: The package is already loaded.
+))
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-attr.sty
+Package: luatexbase-attr 2010/10/10 v0.3 Attributes allocation for LuaTeX
+(/opt/texlive/p2010/texmf-dist/tex/generic/oberdiek/ifluatex.sty
+Package ifluatex Info: The package is already loaded.
+)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-compat.sty)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-loader.sty)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/attr.lua))
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-cctb.sty
+Package: luatexbase-cctb 2010/10/10 v0.3 Catcodetable allocation for LuaTeX
+(/opt/texlive/p2010/texmf-dist/tex/generic/oberdiek/ifluatex.sty
+Package ifluatex Info: The package is already loaded.
+)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-loader.sty)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/cctb.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-compat.sty)
+\lltxb@catcodetable@alloc=\count277
+\@tempcnta=\count278
+\@tempcntb=\count279
+\CatcodeTableIniTeX=\luatexcatcodetable1
+\CatcodeTableString=\luatexcatcodetable2
+\CatcodeTableOther=\luatexcatcodetable3
+\CatcodeTableLaTeX=\luatexcatcodetable4
+\CatcodeTableLaTeXAtLetter=\luatexcatcodetable5
+\CatcodeTableExpl=\luatexcatcodetable6
+)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-mcb.sty
+Package: luatexbase-mcb 2010/10/10 v0.3 Callback management for LuaTeX
+(/opt/texlive/p2010/texmf-dist/tex/generic/oberdiek/ifluatex.sty
+Package ifluatex Info: The package is already loaded.
+)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-modutils.sty
+Package: luatexbase-modutils 2010/10/10 v0.3 Module utilities for LuaTeX
+(/opt/texlive/p2010/texmf-dist/tex/generic/oberdiek/ifluatex.sty
+Package ifluatex Info: The package is already loaded.
+)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-loader.sty)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/modutils.lua))
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/mcb.lua)
+Lua module: luatexbase-mcb 2010/05/12 0.2 register several functions in a callb
+ack
+)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-modutils.sty))
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs.lua)
+Lua module: lualibs 2011/01/20 0.96 Lua additional functions.
+
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-string.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-lpeg.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-boolean.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-number.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-math.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-table.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-aux.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-io.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-os.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-file.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-md5.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-dir.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-unicode.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-utils.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-dimen.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-url.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-set.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/luaotfload.lua)
+Lua module: luaotfload 2011/02/16 1.24 OpenType layout system.
+
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-luat-dum.lua.(using cache: /home/h7k/.texlive2010/texmf-var/luatex-cache/gen
+eric)
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-luat-ovr.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-data-con.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-ini.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-node-dum.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-node-inj.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-tfm.lua.
+luatexbase.attributes["otfl@state"] = 1
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-cid.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-ott.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-map.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-otf.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-otd.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-oti.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-otb.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-otn.lua.
+luatexbase.attributes["otfl@markbase"] = 2
+luatexbase.attributes["otfl@markmark"] = 3
+luatexbase.attributes["otfl@markdone"] = 4
+luatexbase.attributes["otfl@cursbase"] = 5
+luatexbase.attributes["otfl@curscurs"] = 6
+luatexbase.attributes["otfl@cursdone"] = 7
+luatexbase.attributes["otfl@kernpair"] = 8
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-ota.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-otc.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-def.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-xtx.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-dum.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-nms.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-clr.lua.
+Module luatexbase-mcb info: creating 'luaotfload.patch_font' type 4
+Module luatexbase-mcb info: inserting 'luaotfload.pre_linebreak_filter'
+(luatexbase-mcb)            at position 1 in 'pre_linebreak_filter'
+Module luatexbase-mcb info: inserting 'luaotfload.hpack_filter'
+(luatexbase-mcb)            at position 1 in 'hpack_filter'
+Module luatexbase-mcb info: resetting callback 'define_font'
+Module luatexbase-mcb info: inserting 'luaotfload.define_font'
+(luatexbase-mcb)            at position 1 in 'define_font'
+Module luatexbase-mcb info: inserting 'luaotfload.find_vf_file'
+(luatexbase-mcb)            at position 1 in 'find_vf_file'
+) (/opt/texlive/p2010/texmf-dist/tex/generic/oberdiek/ltxcmds.sty
+Package: ltxcmds 2010/04/26 v1.7 LaTeX kernel commands for general use (HO)
+)
+(/opt/texlive/p2010/texmf-dist/tex/generic/xkeyval/xkeyval.tex
+\XKV@toks=\toks13
+\XKV@tempa@toks=\toks14
+\XKV@depth=\count280
+
+2008/08/13 v2.6a key=value parser (HA)
+(/opt/texlive/p2010/texmf-dist/tex/generic/xkeyval/xkvtxhdr.tex
+2005/02/22 v1.1 xkeyval TeX header (HA))
+(/opt/texlive/p2010/texmf-dist/tex/generic/xkeyval/keyval.tex))
+(/opt/texlive/p2010/texmf-dist/tex/generic/oberdiek/infwarerr.sty
+Package: infwarerr 2010/04/08 v1.3 Providing info/warning/message (HO)
+)
+\ltj@tempcnta=\count281
+\ltj@tempcntb=\count282
+\ltj@tempcntc=\count283
+\ltj@tempdima=\dimen256
+\ltj@autospc=\count284
+\ltj@autoxspc=\count285
+\jcharwidowpenalty=\count286
+\kanjiskip=\skip256
+\xkanjiskip=\skip257
+\zw=\dimen257
+\zh=\dimen258
+\jQ=\dimen259
+\jH=\dimen260
+\ltj@curjfnt=\luatexattribute9
+\ltj@charclass=\luatexattribute10
+\ltj@yablshift=\luatexattribute11
+\ltj@ykblshift=\luatexattribute12
+\ltj@autospc=\luatexattribute13
+\ltj@autoxspc=\luatexattribute14
+\ltj@icflag=\luatexattribute15
+\ltj@japanese=\language87
+
+(/opt/texlive/p2010/../texmf-local/tex/generic/luatexja/luatexja-rmlgbm.lua)
+(/opt/texlive/p2010/../texmf-local/tex/generic/luatexja/luatexja-rmlgbm-data.lu
+a)
+(/opt/texlive/p2010/../texmf-local/tex/generic/luatexja/luatexja-jfont.lua)
+(/opt/texlive/p2010/../texmf-local/tex/generic/luatexja/luatexja-core.lua)
+Module luatexbase-mcb info: inserting 'ltj.process_input_buffer'
+(luatexbase-mcb)            at position 1 in 'process_input_buffer'
+Module luatexbase-mcb info: inserting 'ltj.hpack_filter_pre'
+(luatexbase-mcb)            at position 1 in 'hpack_filter'
+Module luatexbase-mcb info: inserting 'ltj.hyphenate'
+(luatexbase-mcb)            at position 1 in 'hyphenate'
+Module luatexbase-mcb info: inserting 'ltj.pre_linebreak_filter'
+(luatexbase-mcb)            at position 2 in 'pre_linebreak_filter'
+Module luatexbase-mcb info: inserting 'ltj.hpack_filter'
+(luatexbase-mcb)            at position 2 in 'hpack_filter'
+(/opt/texlive/p2010/../texmf-local/tex/generic/luatexja/luatexja-jfmglue.lua)
+(/opt/texlive/p2010/../texmf-local/tex/generic/luatexja/luatexja-xkanji.lua)
+\ltj@kcat0=\luatexattribute16
+\ltj@kcat1=\luatexattribute17
+\ltj@kcat2=\luatexattribute18
+\ltj@kcat3=\luatexattribute19
+\ltj@kcat4=\luatexattribute20
+\ltj@kcat5=\luatexattribute21
+\ltj@kcat6=\luatexattribute22
+\ltj@@stack=\count287
+\ltj@@group@level=\count288
+
+plain format: loading luatexja-plain.tex
+(/opt/texlive/p2010/../texmf-local/tex/generic/luatexja/luatexja-plain.tex
+(/opt/texlive/p2010/../texmf-local/tex/generic/luatexja/jfm-ujis.lua)
+(/opt/texlive/p2010/../texmf-local/tex/generic/luatexja/luatexja-kinsoku.tex)))
+(load: /home/h7k/.texlive2010/texmf-var/luatex-cache/generic/fonts/otf/temp-ipa
+m.lua)(load: /home/h7k/.texlive2010/texmf-var/luatex-cache/generic/fonts/otf/te
+mp-kozminpr6n-regular.lua)(load: /home/h7k/.texlive2010/texmf-var/luatex-cache/
+generic/fonts/otf/temp-ipamp.lua)
+(./jfm-bad.lua)
+! LuaTeX-ja error: bad JFM 'bad'.
+\ltj@@jfont ->\directlua {ltj.ext_jfontdefY()}
+                                              
+<to be read again> 
+                   }
+l.19 }
+      
+The JFM file you specified is not valid JFM file.
+Defining Japanese font is cancelled.
+
+(load: /home/h7k/.texlive2010/texmf-var/luatex-cache/generic/fonts/otf/temp-ipa
+exg.lua)
+! LuaTeX-ja error: Invalid character code (-1), should in the range 0.."10FFFF.
+.
+\ltj@@getparam@two ...('#1', \the \ltj@tempcnta )}
+                                                  
+l.52 \ltjgetparameter{chartorange}{-1}
+                                        % must be error "
+I'm going to use 0 instead of that illegal character code.
+
+[1{/opt/texlive/p2010/texmf-var/fonts/map/pdftex/updmap/pdftex.map
+LuaTeX warning (file /opt/texlive/p2010/texmf-var/fonts/map/pdftex/updmap/pdfte
+x.map): fontmap entry for `bchb8r' already exists, duplicates ignored
+
+LuaTeX warning (file /opt/texlive/p2010/texmf-var/fonts/map/pdftex/updmap/pdfte
+x.map): fontmap entry for `bchbi8r' already exists, duplicates ignored
+
+LuaTeX warning (file /opt/texlive/p2010/texmf-var/fonts/map/pdftex/updmap/pdfte
+x.map): fontmap entry for `bchbo8r' already exists, duplicates ignored
+
+LuaTeX warning (file /opt/texlive/p2010/texmf-var/fonts/map/pdftex/updmap/pdfte
+x.map): fontmap entry for `bchr8r' already exists, duplicates ignored
+
+LuaTeX warning (file /opt/texlive/p2010/texmf-var/fonts/map/pdftex/updmap/pdfte
+x.map): fontmap entry for `bchri8r' already exists, duplicates ignored
+
+LuaTeX warning (file /opt/texlive/p2010/texmf-var/fonts/map/pdftex/updmap/pdfte
+x.map): fontmap entry for `bchro8r' already exists, duplicates ignored
+}]
+(./jfm-test.lua) [2] [3] [4] [5] )</opt/texlive/p2010/texmf/fonts/truetype/test
+/ipaexg.ttf></opt/texlive/p2010/texmf/fonts/truetype/test/ipamp.ttf></opt/texli
+ve/p2010/texmf/fonts/opentype/test/kozuka/KozMinPr6N-Regular.otf></opt/texlive/
+p2010/texmf/fonts/truetype/test/ipam.ttf></opt/texlive/p2010/texmf-dist/fonts/t
+ype1/public/amsfonts/cm/cmbx10.pfb></opt/texlive/p2010/texmf-dist/fonts/type1/p
+ublic/amsfonts/cm/cmr10.pfb></opt/texlive/p2010/texmf-dist/fonts/type1/public/a
+msfonts/cm/cmti10.pfb></opt/texlive/p2010/texmf-dist/fonts/type1/public/amsfont
+s/cm/cmtt10.pfb>
+Output written on test04-jfm.pdf (5 pages, 463601 bytes).
+PDF statistics: 74 PDF objects out of 1000 (max. 8388607)
+ 48 compressed objects within 1 object stream
+ 0 named destinations out of 1000 (max. 131072)
+ 1 words of extra memory for PDF output out of 10000 (max. 10000000)
+
index d944332..ede188e 100644 (file)
Binary files a/test/test04-jfm.pdf and b/test/test04-jfm.pdf differ
index c4bf0c4..6d34690 100644 (file)
 \ltjsetparameter{jacharrange={218}}
 和文扱いにもどる
 
-↓「あ」「い」「え」「お」以外はプロポーショナル組(IPA P明朝)
-
-\jfont\rmlh={file:ipamp.ttf:jfm=hang} at 10pt
-\rmlh プロポーショナルのテスト!あいうえおさ,かき・くけこ
-
-
 
 \vfill\eject
-\head{‘lineend’検証}
-\jfont\rmlh={psft:Ryumin-Light:jfm=hang} at 10pt
+\noindent{\bf\gt  以下はJFMグルー挿入検証}
+\jfont\rmlh={psft:Ryumin-Light:jfm=test} at 10pt
 \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}}
 
-\setbox0=\hbox{\rmlh あえあいえ}
-\dumplist0
+\head{JA--JA (penなし)}
 
-\medskip
-\ltjsetparameter{postbreakpenalty={`あ,100}}
-\ltjsetparameter{postbreakpenalty={`い,100}}
-\ltjsetparameter{postbreakpenalty={`う,100}}
-\ltjsetparameter{postbreakpenalty={`え,100}}
-\setbox0=\hbox{\rmlh あえあいえ}
-\dumplist0
+\setbox0=\hbox{\rmlh あア}\dumplist0
+
+\setbox0=\hbox{\rmlh あイ}\dumplist0
+
+\setbox0=\hbox{\rmlh あウ}\dumplist0
+
+\setbox0=\hbox{\rmlh いア}\dumplist0
+
+\setbox0=\hbox{\rmlh いイ}\dumplist0
+
+\setbox0=\hbox{\rmlh いウ}\dumplist0
+
+\head{JA--EN (penなし)}
+
+\setbox0=\hbox{\rmlh あa}\dumplist0
+
+\setbox0=\hbox{\rmlh いa}\dumplist0
+
+\setbox0=\hbox{\rmlh うa}\dumplist0
+
+\setbox0=\hbox{\rmlh えa}\dumplist0
+
+\setbox0=\hbox{\rmlh おa}\dumplist0
+
+\head{EN--JA (penなし)}
+
+\setbox0=\hbox{\rmlh aあ}\dumplist0
+
+\setbox0=\hbox{\rmlh aい}\dumplist0
+
+\setbox0=\hbox{\rmlh aう}\dumplist0
+
+\head{JA--明kern (penなし)}
+
+\setbox0=\hbox{\rmlh あ\kern3pt}\dumplist0
+
+\setbox0=\hbox{\rmlh い\kern3pt}\dumplist0
+
+\setbox0=\hbox{\rmlh う\kern3pt}\dumplist0
+
+\head{明kern--JA (penなし)}
+
+\setbox0=\hbox{\rmlh \kern3ptあ}\dumplist0
+
+\setbox0=\hbox{\rmlh \kern3ptい}\dumplist0
+
+\setbox0=\hbox{\rmlh \kern3ptう}\dumplist0
+
+\head{italic correction}
+
+\setbox0=\hbox{\it f\/(\/あ}\dumplist0
+
+
+{\vfill\eject%
+
+\ltjsetparameter{prebreakpenalty={`(,123}}
+\ltjsetparameter{postbreakpenalty={`あ,123}}
+\ltjsetparameter{postbreakpenalty={`い,123}}
+\ltjsetparameter{postbreakpenalty={`う,123}}
+\ltjsetparameter{postbreakpenalty={`え,123}}
+\ltjsetparameter{postbreakpenalty={`お,123}}
+\ltjsetparameter{postbreakpenalty={`a,321}}
+\head{JA--JA (penあり)}
+
+\setbox0=\hbox{\rmlh あア}\dumplist0
+
+\setbox0=\hbox{\rmlh あイ}\dumplist0
+
+\setbox0=\hbox{\rmlh あウ}\dumplist0
+
+\setbox0=\hbox{\rmlh いア}\dumplist0
+
+\setbox0=\hbox{\rmlh いイ}\dumplist0
+
+\setbox0=\hbox{\rmlh いウ}\dumplist0
+
+\head{JA--EN (penあり)}
+
+\setbox0=\hbox{\rmlh あa}\dumplist0
+
+\setbox0=\hbox{\rmlh いa}\dumplist0
+
+\setbox0=\hbox{\rmlh うa}\dumplist0
+
+\setbox0=\hbox{\rmlh えa}\dumplist0
+
+\setbox0=\hbox{\rmlh おa}\dumplist0
+
+\head{EN--JA (penあり)}
+
+\setbox0=\hbox{\rmlh aあ}\dumplist0
+
+\setbox0=\hbox{\rmlh aい}\dumplist0
+
+\setbox0=\hbox{\rmlh aう}\dumplist0
 
 \head{italic correction}
 
-\setbox0=\hbox{x{\rmlh お\/}({\rmlh お\/}あ}
-\dumplist0
+\setbox0=\hbox{\it f\/(\/あ}\dumplist0
 
-\setbox0=\hbox{x{\it f\/}({\it g\/}あ}
-\dumplist0
+}
+
+\vfill\eject
+\kanjiskip=\maxdimen
+\setbox0=\hbox{\rmlh ンン}\dumplist0
 
 \end