OSDN Git Service

Included mfonttest-131229-1.{tex,pdf} as mfonttest.{tex,pdf}.
[luatex-ja/luatexja.git] / src / ltj-jfont.lua
index 44165a1..1b4d04d 100644 (file)
@@ -3,8 +3,7 @@
 --
 luatexbase.provides_module({
   name = 'luatexja.jfont',
-  date = '2011/06/27',
-  version = '0.1',
+  date = '2011/05/11',
   description = 'Loader for Japanese fonts',
 })
 module('luatexja.jfont', package.seeall)
@@ -14,14 +13,20 @@ luatexja.load_module('charrange'); local ltjc = luatexja.charrange
 
 local node_new = node.new
 local has_attr = node.has_attribute
+local set_attr = node.set_attribute
 local round = tex.round
+local getfont = font.getfont
 
 local attr_icflag = luatexbase.attributes['ltj@icflag']
 local attr_curjfnt = luatexbase.attributes['ltj@curjfnt']
 local id_glyph = node.id('glyph')
 local id_kern = node.id('kern')
+local id_glue_spec = node.id('glue_spec')
+local id_glue = node.id('glue')
 local cat_lp = luatexbase.catcodetables['latex-package']
-local ITALIC = 1
+local ITALIC       = luatexja.icflag_table.ITALIC
+local FROM_JFM     = luatexja.icflag_table.FROM_JFM
+
 ------------------------------------------------------------------------
 -- LOADING JFM
 ------------------------------------------------------------------------
@@ -57,7 +62,12 @@ function define_jfm(t)
               elseif type(w) == 'string' and utf.len(w)==1 then
                  real_char = true; w = utf.byte(w)
               elseif type(w) == 'string' and utf.len(w)==2 and utf.sub(w,2) == '*' then
-                 real_char = true; w = -utf.byte(utf.sub(w,1,1))
+                 real_char = true; w = utf.byte(utf.sub(w,1,1))
+                  if not t.chars[-w] then 
+                     t.chars[-w] = i
+                  else 
+                     defjfm_res= nil; return
+                  end
               end
               if not t.chars[w] then
                  t.chars[w] = i
@@ -65,6 +75,9 @@ function define_jfm(t)
                  defjfm_res= nil; return
               end
            end
+            if type(v.align)~='string' then 
+               v.align = 'left' -- left
+            end
            if real_char then
               if not (type(v.width)=='number' or v.width~='prop') then
                  defjfm_res= nil; return
@@ -84,9 +97,6 @@ function define_jfm(t)
                  if type(v.down)~='number' then 
                     v.down = 0.0
                  end
-                 if type(v.align)=='nil' then
-                    v.align = 'left'
-                 end
               end
            end
            v.chars = nil
@@ -96,6 +106,13 @@ function define_jfm(t)
         for j in pairs(v.glue) do
            if v.kern[j] then defjfm_res= nil; return end
         end
+        for j,x in pairs(v.kern) do
+           if type(x)=='number' then 
+               v.kern[j] = {x, 0}
+            elseif type(x)=='table' then 
+               v.kern[j] = {x[1], x[2] or 0}
+            end
+        end
         t.char_type[i] = v
         t[i] = nil
       end
@@ -113,8 +130,8 @@ local function mult_table(old,scale) -- modified from table.fastcopy
             new[k] = mult_table(v,scale)
          elseif type(v) == "number" then
             new[k] = round(v*scale)
-         else
-            new[k] = v
+          else
+             new[k] = v
          end
        end
        return new
@@ -123,13 +140,29 @@ end
 
 local function update_jfm_cache(j,sz)
    if metrics[j].size_cache[sz] then return end
-   metrics[j].size_cache[sz] = {}
-   metrics[j].size_cache[sz].chars = metrics[j].chars
-   metrics[j].size_cache[sz].char_type = mult_table(metrics[j].char_type, sz)
-   metrics[j].size_cache[sz].kanjiskip = mult_table(metrics[j].kanjiskip, sz)
-   metrics[j].size_cache[sz].xkanjiskip = mult_table(metrics[j].xkanjiskip,sz)
-   metrics[j].size_cache[sz].zw = round(metrics[j].zw*sz)
-   metrics[j].size_cache[sz].zh = round(metrics[j].zh*sz)
+   local t = {}
+   metrics[j].size_cache[sz] = t
+   t.chars = metrics[j].chars
+   t.char_type = mult_table(metrics[j].char_type, sz)
+   for i,v in pairs(t.char_type) do
+      if type(i) == 'number' then -- char_type
+        for k,w in pairs(v.glue) do
+           local g, h = node.new(id_glue), node_new(id_glue_spec)
+            v.glue[k] = {g, (w[5] and w[5]/sz or 0)}
+            h.width, h.stretch, h.shrink = w[1], w[2], w[3]
+            h.stretch_order, h.shrink_order = 0, 0
+            g.subtype = 0; g.spec = h; set_attr(g, attr_icflag, FROM_JFM + 
+                                                (w[4] and w[4]/sz or 0)); 
+        end
+        for k,w in pairs(v.kern) do
+           w[2] = w[2]/sz
+        end
+      end
+   end
+   t.kanjiskip = mult_table(metrics[j].kanjiskip, sz)
+   t.xkanjiskip = mult_table(metrics[j].xkanjiskip,sz)
+   t.zw = round(metrics[j].zw*sz)
+   t.zh = round(metrics[j].zh*sz)
 end
 
 luatexbase.create_callback("luatexja.find_char_class", "data", 
@@ -140,7 +173,7 @@ luatexbase.create_callback("luatexja.find_char_class", "data",
 function find_char_class(c,m)
 -- c: character code, m: 
    if not m then return 0 end
-   return m.size_cache.chars[c] or 
+   return m.chars[c] or 
       luatexbase.call_callback("luatexja.find_char_class", 0, m, c)
 end
 
@@ -185,7 +218,7 @@ luatexbase.create_callback("luatexja.define_jfont", "data", function (ft, fn) re
 function jfontdefY() -- for horizontal font
    local j = load_jfont_metric()
    local fn = font.id(cstemp)
-   local f = font.fonts[fn]
+   local f = getfont(fn)
    if not j then 
       ltjb.package_error('luatexja',
                         "bad JFM `" .. jfm_file_name .. "'",
@@ -196,8 +229,13 @@ function jfontdefY() -- for horizontal font
      return 
    end
    update_jfm_cache(j, f.size)
+   local sz = metrics[j].size_cache[f.size]
    local fmtable = { jfm = j, size = f.size, var = jfm_var, 
-                    size_cache = metrics[j].size_cache[f.size] }
+                    zw = sz.zw, zh = sz.zh, 
+                    chars = sz.chars, char_type = sz.char_type,
+                    kanjiskip = sz.kanjiskip, xkanjiskip = sz.xkanjiskip, 
+                   }
+      
    fmtable = luatexbase.call_callback("luatexja.define_jfont", fmtable, fn)
    font_metric_table[fn]=fmtable
    tex.sprint(cat_lp, luatexja.is_global .. '\\protected\\expandafter\\def\\csname ' 
@@ -208,7 +246,7 @@ end
 function load_zw()
    local a = font_metric_table[tex.attribute[attr_curjfnt]]
    if a then
-      tex.setdimen('ltj@zw', a.size_cache.zw)
+      tex.setdimen('ltj@zw', a.zw)
    else 
       tex.setdimen('ltj@zw',0)
    end
@@ -217,7 +255,7 @@ end
 function load_zh()
    local a = font_metric_table[tex.attribute[attr_curjfnt]]
    if a then
-      tex.setdimen('ltj@zh', a.size_cache.zh)
+      tex.setdimen('ltj@zh', a.zh)
    else 
       tex.setdimen('ltj@zh',0)
    end
@@ -251,17 +289,17 @@ local function extract_metric(name)
 end
 
 -- replace fonts.define.read()
-local ljft_dr_orig = fonts.define.read
-function fonts.define.read(name, size, id)
+function font_callback(name, size, id, fallback)
    extract_metric(name)
    -- In the present imple., we don't remove "jfm=..." from name.
-   return ljft_dr_orig(name, size, id)
+   return fallback(name, size, id)
 end
 
 ------------------------------------------------------------------------
 -- MISC
 ------------------------------------------------------------------------
 
+local is_ucs_in_japanese_char = ltjc.is_ucs_in_japanese_char
 -- EXT: italic correction
 function append_italic()
    local p = tex.nest[tex.nest.ptr].tail
@@ -269,13 +307,18 @@ function append_italic()
       local f = p.font
       local g = node_new(id_kern)
       g.subtype = 1; node.set_attribute(g, attr_icflag, ITALIC)
-      if ltjc.is_ucs_in_japanese_char(p) then
+      if is_ucs_in_japanese_char(p) then
         f = has_attr(p, attr_curjfnt)
         local j = font_metric_table[f]
-        local c = find_char_class(p.char, j)
-        g.kern = j.size_cache.char_type[c].italic
+        g.kern = j.char_type[find_char_class(p.char, j)].italic
       else
-        g.kern = font.fonts[f].characters[p.char].italic
+        local h = getfont(f)
+        if h then
+           g.kern = h.characters[p.char].italic
+        else
+           tex.attribute[attr_icflag] = -(0x7FFFFFFF)
+           return node.free(g)
+        end
       end
       node.write(g)
       tex.attribute[attr_icflag] = -(0x7FFFFFFF)