OSDN Git Service

Support Japanese characters in math mode (no documents)
authorHironori Kitagawa <h_kitagawa2001@yahoo.co.jp>
Mon, 15 Aug 2011 01:22:12 +0000 (10:22 +0900)
committerHironori Kitagawa <h_kitagawa2001@yahoo.co.jp>
Sun, 21 Aug 2011 00:35:45 +0000 (09:35 +0900)
src/luatexja-core.lua
src/luatexja-core.sty
src/luatexja/jfmglue.lua
src/luatexja/math.lua [new file with mode: 0644]
src/luatexja/setwidth.lua
src/luatexja/stack.lua

index a5c63bb..8fdd9a3 100644 (file)
@@ -5,6 +5,7 @@ require('luatexja.charrange'); local ltjc = luatexja.charrange
 require('luatexja.jfont');     local ltjf = luatexja.jfont
 require('luatexja.inputbuf');  local ltji = luatexja.inputbuf
 require('luatexja.jfmglue');   local ltjj = luatexja.jfmglue
+require('luatexja.math');      local ltjm = luatexja.math
 require('luatexja.pretreat');  local ltjp = luatexja.pretreat
 require('luatexja.stack');     local ltjs = luatexja.stack
 require('luatexja.setwidth');  local ltjw = luatexja.setwidth
@@ -224,6 +225,9 @@ function debug_show_node_X(p,print_fn)
    elseif pt=='hlist' then
       s = base .. '(' .. print_scaled(p.height) .. '+' 
          .. print_scaled(p.depth) .. ')x' .. print_scaled(p.width)
+      if p.shift~=0 then
+        s = s .. ', shifted ' .. print_scaled(p.shift)
+      end
       if p.glue_sign >= 1 then 
         s = s .. ' glue set '
         if p.glue_sign == 2 then s = s .. '-' end
@@ -283,6 +287,27 @@ function debug_show_node_X(p,print_fn)
         s = s .. node.subtype(p.subtype)
       end
       print_fn(s)
+   --  ここから数式用 node
+   elseif pt=='noad' then
+      s = base ; print_fn(s)
+      if p.nucleus then
+        debug_depth = k .. 'N'; debug_show_node_X(p.nucleus, print_fn); 
+      end
+      if p.sup then
+        debug_depth = k .. '^'; debug_show_node_X(p.sup, print_fn); 
+      end
+      if p.sub then
+        debug_depth = k .. '_'; debug_show_node_X(p.sub, print_fn); 
+      end
+      debug_depth = k;
+   elseif pt=='math_char' then
+      s = base .. ' fam: ' .. p.fam .. ' , char = ' .. utf.char(p.char)
+      print_fn(s)
+   elseif pt=='sub_box' then
+      print_fn(base)
+      if p.head then
+        debug_depth = k .. '.'; debug_show_node_X(p.head, print_fn); 
+      end
    else
       print_fn(base)
    end
index 3d13c0e..a857aad 100644 (file)
 
 %%%%%%%% Attributes for Japanese typesetting.
 \newluatexattribute\ltj@curjfnt   % index for ``current Japanese font''
+\newluatexattribute\jfam          % index for current jfam
 \newluatexattribute\ltj@charclass % 
 \newluatexattribute\ltj@yablshift % attribute for \yabaselineshift
 \newluatexattribute\ltj@ykblshift % attribute for \ykbaselineshift
   \directlua{luatexja.stack.set_stack_table(ltj.isglobal, \asluastring{#3},
     \ltj@safe@num@or\ltj@defnum{#1},\ltj@safe@num@or\ltj@defnum{#2},#4,#5)}}
 
+% jatextfont = {<char_code>, <font_cs>}
+\define@key[ltj]{japaram}{jatextfont}{%
+  \expandafter\ltj@@set@stackfont#1:{mjtext}}
+\define@key[ltj]{japaram}{jascriptfont}{%
+  \expandafter\ltj@@set@stackfont#1:{mjscr}}
+\define@key[ltj]{japaram}{jascriptscriptfont}{%
+  \expandafter\ltj@@set@stackfont#1:{mjss}}
+\def\ltj@@set@stackfont#1,#2:#3{%
+  {\ltj@curjfnt=-1 #2\global\ltj@tempcnta=\ltj@curjfnt}%
+  \ifnum\ltj@tempcnta=-1
+    \@PackageError{luatexja-core}
+    {\string#2 is not a control sequence that represents \MessageBreak
+     a Japanese font}{}%
+  \else
+    \directlua{luatexja.stack.set_stack_font(ltj.isglobal, \asluastring{#3},
+    \ltj@safe@num@or\ltj@defnum{#1}, \the\ltj@tempcnta)}
+  \fi}
+
 % yalbaselineshift = <dimen>
 % yjabaselineshift = <dimen>
 \define@key[ltj]{japaram}{yalbaselineshift}{%
     \directlua{ltj.ext_print_global()}\ltj@autoxspc=0
   \fi}
 
+% [x]]kanjiskip = <dimen>
 \define@key[ltj]{japaram}{kanjiskip}{%              % SKIP
   \directlua{luatexja.stack.set_stack_skip(ltj.isglobal, 'kanjiskip', \ltj@safe@glue{#1})}}
 \define@key[ltj]{japaram}{xkanjiskip}{%             % SKIP
   \directlua{luatexja.stack.set_stack_skip(ltj.isglobal, 'xkanjiskip', \ltj@safe@glue{#1})}}
+
+% jcharwidowpenalty = <count>
 \define@key[ltj]{japaram}{jcharwidowpenalty}{%      %COUNT
   \ltj@@set@stack0,#1:{jwp}{-10000}{10000}}
 
index 1cb9db7..598d94e 100644 (file)
@@ -269,7 +269,7 @@ local function calc_np()
         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
+           Np.nuc = lp; lp  = node_next(lp) 
            while lp.id~=id_math do 
               set_attr_icflag_processed(lp); lp  = node_next(lp) 
            end; break
@@ -824,5 +824,3 @@ function create_inhibitglue_node()
    local g=node_new(id_whatsit, sid_user)
    g.user_id=30111; g.type=100; g.value=1; node.write(g)
 end
-
--- TODO: 二重挿入の回避
diff --git a/src/luatexja/math.lua b/src/luatexja/math.lua
new file mode 100644 (file)
index 0000000..930699a
--- /dev/null
@@ -0,0 +1,125 @@
+--
+-- luatexja/math.lua
+--
+luatexbase.provides_module({
+  name = 'luatexja.math',
+  date = '2011/08/14',
+  version = '0.1',
+  description = 'Handling routines for Japanese characters in math mode',
+})
+module('luatexja.math', package.seeall)
+
+require('luatexja.base');      local ltjb = luatexja.base
+require('luatexja.charrange'); local ltjc = luatexja.charrange
+require('luatexja.jfont');     local ltjf = luatexja.jfont
+require('luatexja.stack');     local ltjs = luatexja.stack
+require('luatexja.setwidth');  local ltjw = luatexja.setwidth
+
+local node_new = node.new
+local node_next = node.next
+local node_free = node.free
+local has_attr = node.has_attribute
+local set_attr = node.set_attribute
+
+local attr_jchar_class = luatexbase.attributes['ltj@charclass']
+local attr_icflag = luatexbase.attributes['ltj@icflag']
+local attr_curjfnt = luatexbase.attributes['ltj@curjfnt']
+local attr_jfam = luatexbase.attributes['jfam']
+
+local id_glyph = node.id('glyph')
+local id_hlist = node.id('hlist')
+local id_vlist = node.id('vlist')
+local id_mchar = node.id('math_char')
+local id_sub_box = node.id('sub_box')
+local id_radical = node.id('radical')
+local id_choice  = node.id('choice')
+local id_accent  = node.id('accent')
+local id_style   = node.id('style')
+local id_frac    = node.id('fraction')
+local id_simple  = node.id('noad')
+local id_sub_mlist = node.id('sub_mlist')
+
+local PROCESSED = 8
+
+local conv_jchar_to_hbox_A
+
+-- sty : 0 (display or text), 1 (script), >=2 (scriptscript)
+local function conv_jchar_to_hbox(head, sty)
+   local p = head
+   local bhead = head
+   while p do
+      if p.id == id_simple or p.id == id_accent then
+        p.nucleus = conv_jchar_to_hbox_A(p.nucleus, sty)
+        p.sub = conv_jchar_to_hbox_A(p.sub, sty + 1)
+        p.sup = conv_jchar_to_hbox_A(p.sup, sty + 1)
+      elseif p.id == id_choice then
+        p.text = conv_jchar_to_hbox(p.text, 0)
+        p.script = conv_jchar_to_hbox(p.script, 1)
+        p.scriptscript = conv_jchar_to_hbox(p.scriptscript, 2)
+      elseif p.id == id_frac then
+        p.num = conv_jchar_to_hbox_A(p.num, sty + 1)
+        p.denom = conv_jchar_to_hbox_A(p.denom, sty + 1)
+      elseif p.id == id_radical then
+        p.nucleus = conv_jchar_to_hbox_A(p.nucleus, sty)
+        p.sub = conv_jchar_to_hbox_A(p.sub, sty + 1)
+        p.sup = conv_jchar_to_hbox_A(p.sup, sty + 1)
+        if p.degree then
+           p.degree = conv_jchar_to_hbox_A(p.degree, sty + 1)
+        end
+      elseif p.id == id_style then
+        if p.style == "display'" or  p.style == 'display'
+           or  p.style == "text'" or  p.style == 'text' then
+           sty = 0
+        elseif  p.style == "script'" or  p.style == 'script' then
+           sty = 1
+        else sty = 2
+        end
+       end
+       p = node.next(p)
+   end 
+   return head
+end 
+
+conv_jchar_to_hbox_A = 
+function (p, sty)
+   print ("  Pa: ",p);
+   if not p then return nil
+   elseif p.id == id_sub_mlist then
+      if p.head then
+        p.head = conv_jchar_to_hbox(p.head, sty)
+      end
+   elseif p.id == id_mchar then
+      local fam = has_attr(p, attr_jfam) or -1
+      if ltjc.is_ucs_in_japanese_char(p) and fam>=0 then
+        local mode = 'mjss'
+        if sty == 0 then mode = 'mjtext'
+        elseif sty == 1 then mode = 'mjscr'
+        end
+        local f = ltjs.get_penalty_table(mode, fam, -1, tex.getcount('ltj@@stack'))
+        if f ~= -1 then
+           local q = node_new(id_sub_box)
+           local r = node_new(id_glyph); r.next = nil
+           r.char = p.char; r.font = f; r.subtype = 256
+           set_attr(r, attr_icflag, PROCESSED)
+           local class = ltjf.find_char_class(p.char, ltjf.font_metric_table[f].jfm)
+           set_attr(r, attr_jchar_class, class)
+           ltjw.met_tb = ltjf.font_metric_table[f]
+           ltjw.char_data = ltjf.metrics[ltjw.met_tb.jfm].char_type[class]
+           ltjw.head = r; ltjw.capsule_glyph(r, tex.mathdir , true);
+           q.head = ltjw.head; node_free(p); p=q;
+        end
+      end
+   end
+   return p
+end
+
+luatexbase.add_to_callback('mlist_to_hlist', 
+   function (n, display_type, penalties)
+      ltj.ext_show_node_list(n, '  ', print)
+      local head = conv_jchar_to_hbox(n, 0);
+      head = node.mlist_to_hlist(head, display_type, penalties)
+      print("--------");
+      ltj.ext_show_node_list(head, '  ', print)
+      print("--------");
+      return head
+   end,'ltj.mlist_to_hlist', 1)
\ No newline at end of file
index a1c528e..0fb33a5 100644 (file)
@@ -37,16 +37,17 @@ local attr_icflag = luatexbase.attributes['ltj@icflag']
 
 local PACKED = 2
 
-local met_tb = {}
-local char_data = {}
-local head
+met_tb = {}
+char_data = {}
+head = nil
 
 -- return true if and only if p is a Japanese character node
 local function is_japanese_glyph_node(p)
    return p.font==has_attr(p, attr_curjfnt)
 end
 
-local function capsule_glyph(p, dir)
+-- mode: true iff p will be always encapsuled by a hbox
+function capsule_glyph(p, dir, mode)
    local h, box, q, fwidth, fheight, fdepth
    p.xoffset= p.xoffset - round(met_tb.size*char_data.left)
    if char_data.width ~= 'prop' then
@@ -54,7 +55,7 @@ local function capsule_glyph(p, dir)
    else fwidth = p.width end
    fheight = round(met_tb.size*char_data.height)
    fdepth = round(met_tb.size*char_data.depth)
-   if p.width ~= fwidth or p.height ~= fheight or p.depth ~= fdepth then
+   if mode or p.width ~= fwidth or p.height ~= fheight or p.depth ~= fdepth then
       local y_shift = - p.yoffset + (has_attr(p,attr_yablshift) or 0)
       p.yoffset = -round(met_tb.size*char_data.down)
       head, q = node.remove(head, p)
@@ -98,7 +99,7 @@ function set_ja_width(ahead, dir)
         if is_japanese_glyph_node(p) then
            met_tb = ltjf.font_metric_table[p.font]
            char_data = ltjf.metrics[met_tb.jfm].char_type[has_attr(p, attr_jchar_class)]
-           p = capsule_glyph(p, dir)
+           p = capsule_glyph(p, dir, false)
         else 
            p.yoffset = p.yoffset - (has_attr(p,attr_yablshift) or 0); p = node_next(p)
         end
index 263706b..7bb2614 100644 (file)
@@ -63,6 +63,27 @@ function set_stack_table(g,m,c,p,lb,ub)
   end
 end
 
+-- EXT
+function set_stack_font(g,m,c,p)
+   local i = get_stack_level()
+   if c<0 or c>255 then 
+      ltjb.package_error('luatexja',
+                        "invalid family number (".. p .. ")",
+                        {"The family number should in the range 0 .. 255.",
+                         "I'm going to use 0 instead of that illegal family number."})
+      c=0
+   elseif not charprop_stack_table[i][c] then 
+      charprop_stack_table[i][c] = {} 
+   end
+   charprop_stack_table[i][c][m] = p
+  if g=='global' then
+     for j,v in pairs(charprop_stack_table) do 
+       if not charprop_stack_table[j][c] then charprop_stack_table[j][c] = {} end
+       charprop_stack_table[j][c][m] = p
+     end
+  end
+end
+
 -- EXT: store \ltj@tempskipa
 function set_stack_skip(g,c,sp)
   local i = get_stack_level()