OSDN Git Service

luatexja-fontspec-26h
[luatex-ja/luatexja.git] / src / ltj-jfont.lua
index 3bd4322..5f1ddf6 100644 (file)
@@ -3,10 +3,9 @@
 --
 luatexbase.provides_module({
   name = 'luatexja.jfont',
-  date = '2017/08/09',
+  date = '2018/06/15',
   description = 'Loader for Japanese fonts',
 })
-module('luatexja.jfont', package.seeall)
 
 luatexja.load_module('base');      local ltjb = luatexja.base
 luatexja.load_module('charrange'); local ltjc = luatexja.charrange
@@ -31,12 +30,14 @@ local id_glyph = node.id('glyph')
 local id_kern = node.id('kern')
 local cat_lp = luatexbase.catcodetables['latex-package']
 local FROM_JFM     = luatexja.icflag_table.FROM_JFM
+
+luatexja.jfont = luatexja.jfont or {}
 ------------------------------------------------------------------------
 -- LOADING JFM
 ------------------------------------------------------------------------
 
-metrics={} -- this table stores all metric informations
-font_metric_table={} -- [font number] -> jfm_name, jfm_var, size
+local metrics={} -- this table stores all metric informations
+local font_metric_table={} -- [font number] -> jfm_name, jfm_var, size
 
 luatexbase.create_callback("luatexja.load_jfm", "data", function (ft, jn) return ft end)
 
@@ -54,7 +55,9 @@ local function norm_val(a)
    end
 end
 
-function define_jfm(t)
+local fastcopy=table.fastcopy
+function luatexja.jfont.define_jfm(to)
+   local t = fastcopy(to)
    local real_char -- Does current character class have the 'real' character?
    if t.dir~=jfm_dir then
       defjfm_res= nil; return
@@ -178,6 +181,8 @@ end
 
 local update_jfm_cache
 do
+   local floor = math.floor
+   local function myround(a) return floor(a+0.5) end
    local function mult_table(old,scale) -- modified from table.fastcopy
       if old then
         local new = { }
@@ -185,7 +190,7 @@ do
            if type(v) == "table" then
               new[k] = mult_table(v,scale)
            elseif type(v) == "number" then
-              new[k] = round(v*scale)
+              new[k] = myround(v*scale)
            else
               new[k] = v
            end
@@ -234,7 +239,8 @@ end
 luatexbase.create_callback("luatexja.find_char_class", "data",
                           function (arg, fmtable, char)
                              return 0
-                          end)
+                         end)
+local find_char_class
 do
    local start_time_measure = ltjb.start_time_measure
    local stop_time_measure = ltjb.stop_time_measure
@@ -287,7 +293,7 @@ do
 
 -- EXT
    local utf8 = unicode.utf8
-   function jfontdefX(g, dir, csname)
+   function luatexja.jfont.jfontdefX(g, dir, csname)
       jfm_dir, is_def_jfont = dir, true
       cstemp = csname:sub( (utf8.byte(csname,1,1) == tex.escapechar) and 2 or 1, -1)
       cstemp = cstemp:sub(1, ((cstemp:sub(-1,-1)==' ') and (cstemp:len()>=2)) and -2 or -1)
@@ -301,7 +307,7 @@ do
 -- EXT
    local identifiers = fonts.hashes.identifiers
    local provides_feature = luaotfload.aux.provides_feature
-   function jfontdefY()
+   function luatexja.jfont.jfontdefY()
       local j = load_jfont_metric(jfm_dir)
       local fn = font.id(cstemp)
       local f = font_getfont(fn)
@@ -338,6 +344,9 @@ do
          t.shared.features[vrt2_exist and 'vrt2' or 'vert'] = true
       end
 
+      texio.write_nl('term and log', 
+        'JFNT\t' .. identifiers[fn].name .. '\t' .. identifiers[fn].size .. '\t' .. fn, '')
+
       fmtable = luatexbase.call_callback("luatexja.define_jfont", fmtable, fn)
       font_metric_table[fn]=fmtable
       tex.sprint(cat_lp, global_flag, '\\protected\\expandafter\\def\\csname ',
@@ -352,12 +361,12 @@ do
    local dir_tate = luatexja.dir_table.dir_tate
    local tex_get_attr = tex.getattribute
    -- PUBLIC function
-   function get_zw()
+   function luatexja.jfont.get_zw()
       local a = font_metric_table[
         tex_get_attr((get_dir_count()==dir_tate) and attr_curtfnt or attr_curjfnt)]
       return a and a.zw or 0
    end
-   function get_zh()
+   function luatexja.jfont.get_zh()
       local a = font_metric_table[
         tex_get_attr((get_dir_count()==dir_tate) and attr_curtfnt or attr_curjfnt)]
       return a and a.zw or 0
@@ -365,11 +374,19 @@ do
 end
 
 do
+   local gmatch = string.gmatch
    -- extract jfm_file_name and jfm_var
    -- normalize position of 'jfm=' and 'jfmvar=' keys
    local function extract_metric(name)
-      local is_braced = name:match('^{(.*)}$')
-      name= is_braced or name
+      do
+         local nametemp
+        nametemp = name:match('^{(.*)}$')
+        if nametemp then name = nametemp
+         else
+           nametemp = name:match('^"(.*)"$')
+           name = nametemp or name
+         end
+      end
       jfm_file_name = ''; jfm_var = ''; jfm_ksp = true
       local tmp, index = name:sub(1, 5), 1
       if tmp == 'file:' or tmp == 'name:' or tmp == 'psft:' then
@@ -378,7 +395,7 @@ do
       local p = name:find(":", index); index = p and (p+1) or index
       while index do
         local l = name:len()+1
-        local q = name:find(";", index+1) or l
+        local q = name:find(";", index) or l
         if name:sub(index, index+3)=='jfm=' and q>index+4 then
            jfm_file_name = name:sub(index+4, q-1)
            if l~=q then
@@ -405,19 +422,20 @@ do
            .. ((l==':' or l==';') and '' or ';')
            .. 'jfm=' .. jfm_file_name
         if jfm_var~='' then
-           name = name .. 'jfmvar=' .. jfm_var
+           name = name .. ';jfmvar=' .. jfm_var
         end
       end
-      for x in string.gmatch (name, "[:;]([+%%-]?)ltjks") do
+      for x in gmatch (name, "[:;]([+%%-]?)ltjks") do
         jfm_ksp = not (x=='-')
       end
       if jfm_dir == 'tate' then
         is_vert_enabled = (not name:match('[:;]%-vert')) and (not  name:match('[:;]%-vrt2'))
-         auto_enable_vrt2 = (not name:match('vert') and not name:match('vrt2'))
+        auto_enable_vrt2 
+          = (not name:match('[:;][+%-]?vert')) and (not name:match('[:;][+%-]?vrt2'))
       else
         is_vert_enabled, auto_enable_vrt2 = nil, nil
       end
-      return is_braced and ('{' .. name .. '}') or name
+      return name
    end
 
    -- define_font callback
@@ -442,25 +460,25 @@ end
 do
    -- these function are called from ltj-latex.sty
    local fenc_list, kyenc_list, ktenc_list = {}, {}, {}
-   function add_fenc_list(enc) fenc_list[enc] = 'true ' end
-   function add_kyenc_list(enc) kyenc_list[enc] = 'true ' end
-   function add_ktenc_list(enc) ktenc_list[enc] = 'true ' end
-   function is_kyenc(enc)
+   function luatexja.jfont.add_fenc_list(enc) fenc_list[enc] = 'true ' end
+   function luatexja.jfont.add_kyenc_list(enc) kyenc_list[enc] = 'true ' end
+   function luatexja.jfont.add_ktenc_list(enc) ktenc_list[enc] = 'true ' end
+   function luatexja.jfont.is_kyenc(enc)
       tex.sprint(cat_lp, '\\let\\ifin@\\if' .. (kyenc_list[enc] or 'false '))
    end
-   function is_ktenc(enc)
+   function luatexja.jfont.is_ktenc(enc)
       tex.sprint(cat_lp, '\\let\\ifin@\\if' .. (ktenc_list[enc] or 'false '))
    end
-   function is_kenc(enc)
+   function luatexja.jfont.is_kenc(enc)
       tex.sprint(cat_lp, '\\let\\ifin@\\if'
                 .. (kyenc_list[enc] or ktenc_list[enc] or 'false '))
    end
 
    local kfam_list, Nkfam_list = {}, {}
-   function add_kfam(fam)
+   function luatexja.jfont.add_kfam(fam)
       kfam_list[fam]=true
    end
-   function search_kfam(fam, use_fd)
+   function luatexja.jfont.search_kfam(fam, use_fd)
       if kfam_list[fam] then
         tex.sprint(cat_lp, '\\let\\ifin@\\iftrue '); return
       elseif Nkfam_list[fam] then
@@ -482,20 +500,20 @@ do
       end
    end
    local ffam_list, Nffam_list = {}, {}
-   function is_ffam(fam)
+   function luatexja.jfont.is_ffam(fam)
       tex.sprint(cat_lp, '\\let\\ifin@\\if' .. (ffam_list[fam] or 'false '))
    end
-   function add_ffam(fam)
+   function luatexja.jfont.add_ffam(fam)
       ffam_list[fam]='true '
    end
-   function search_ffam_declared()
+   function luatexja.jfont.search_ffam_declared()
      local s = ''
      for i,_ in pairs(fenc_list) do
        s = s .. '\\cdp@elt{' .. i .. '}'
      end
      tex.sprint(cat_lp, s)
    end
-   function search_ffam_fd(fam)
+   function luatexja.jfont.search_ffam_fd(fam)
       if Nffam_list[fam] then
         tex.sprint(cat_lp, '\\let\\ifin@\\iffalse '); return
       else
@@ -512,14 +530,13 @@ end
 ------------------------------------------------------------------------
 -- ALTERNATE FONTS
 ------------------------------------------------------------------------
-alt_font_table = {}
-local alt_font_table = alt_font_table
+local alt_font_table = {}
 local attr_curaltfnt = {}
 local ucs_out = 0x110000
 
 ------ for TeX interface
 -- EXT
-function set_alt_font(b,e,ind,bfnt)
+function luatexja.jfont.set_alt_font(b,e,ind,bfnt)
    -- ind: 新フォント, bfnt: 基底フォント
    if b>e then b, e = e, b end
    if b*e<=0 then
@@ -553,7 +570,7 @@ function set_alt_font(b,e,ind,bfnt)
 end
 
 -- EXT
-function clear_alt_font(bfnt)
+function luatexja.jfont.clear_alt_font(bfnt)
    if alt_font_table[bfnt] then
       local t = alt_font_table[bfnt]
       for i,_ in pairs(t) do t[i]=nil; end
@@ -561,7 +578,7 @@ function clear_alt_font(bfnt)
 end
 
 ------ used in ltjp.suppress_hyphenate_ja callback
-function replace_altfont(pf, pc)
+function luatexja.jfont.replace_altfont(pf, pc)
    local a = alt_font_table[pf]
    return a and a[pc] or pf
 end
@@ -571,7 +588,7 @@ end
 local alt_font_table_latex = {}
 
 -- EXT
-function clear_alt_font_latex(bbase)
+function luatexja.jfont.clear_alt_font_latex(bbase)
    local t = alt_font_table_latex[bbase]
    if t then
       for j,v in pairs(t) do t[j] = nil end
@@ -579,7 +596,7 @@ function clear_alt_font_latex(bbase)
 end
 
 -- EXT
-function set_alt_font_latex(b,e,ind,bbase)
+function luatexja.jfont.set_alt_font_latex(b,e,ind,bbase)
    -- ind: Alt font の enc/fam/ser/shape, bbase: 基底フォントの enc/fam/ser/shape
    if b>e then b, e = e, b end
    if b*e<=0 then
@@ -621,17 +638,17 @@ do
    local alt_font_base, alt_font_base_num
    local aftl_base
    -- EXT
-   function does_alt_set(bbase)
+   function luatexja.jfont.does_alt_set(bbase)
       aftl_base = alt_font_table_latex[bbase]
       tex.sprint(cat_lp, '\\if' .. (aftl_base and 'true' or 'false'))
    end
    -- EXT
-   function print_aftl_address()
+   function luatexja.jfont.print_aftl_address()
       tex.sprint(cat_lp, ';ltjaltfont' .. tostring(aftl_base):sub(8))
    end
 
 -- EXT
-   function output_alt_font_cmd(dir, bbase)
+   function luatexja.jfont.output_alt_font_cmd(dir, bbase)
       alt_font_base = bbase
       if dir == 't' then
         alt_font_base_num = tex.getattribute(attr_curtfnt)
@@ -651,7 +668,7 @@ do
    end
 
 -- EXT
-   function pickup_alt_font_a(size_str)
+   function luatexja.jfont.pickup_alt_font_a(size_str)
       local t = alt_font_table_latex[alt_font_base]
       if t then
          for i,v in pairs(t) do
@@ -670,7 +687,7 @@ do
    end
 
 -- EXT
-   function pickup_alt_font_b(afnt_num, afnt_base)
+   function luatexja.jfont.pickup_alt_font_b(afnt_num, afnt_base)
       local t = alt_font_table[alt_font_base_num]
       local ac = font_getfont(afnt_num).characters
       if not t then t = {}; alt_font_table[alt_font_base_num] = t end
@@ -694,7 +711,7 @@ end
 -- 終了時に各種ノードを破棄
 ------------------------------------------------------------------------
 do
-   function cleanup_size_cache()
+   function luatexja.jfont.cleanup_size_cache()
       --local gs, ke = 0, 0
       for _,n in pairs(metrics) do
         for i,t in pairs(n.size_cache) do
@@ -715,8 +732,8 @@ end
 ------------------------------------------------------------------------
 -- 追加のフォント情報
 ------------------------------------------------------------------------
-font_extra_info = {}
-local font_extra_info = font_extra_info -- key: fontnumber
+local font_extra_info = {}
+luatexja.jfont.font_extra_info= font_extra_info -- key: fontnumber
 local font_extra_basename = {} -- key: basename
 
 local list_rotate_glyphs
@@ -744,7 +761,7 @@ do
            if i.order[1]== 'vert' and i.type == 'gsub_single' and i.steps then
               for _,j in pairs(i.steps) do
                  if type(j)=='table' then 
-                    if type(j,coverage)=='table' then
+                    if type(j.coverage)=='table' then
                        for i,_ in pairs(j.coverage) do rot[i]=nil end
                     end
                  end
@@ -850,12 +867,21 @@ do
    end
    prepare_fl_data = function (dest, id)
       local t = fontloader.info(id.filename)
+      if not t then return dest end
       local fl
-      if t.filename then
+      if t.fontname then
         fl = fontloader.open(id.filename)
       else
-        fl = fontloader.open(id.filename, id.fullname)
+        fl = fontloader.open(id.filename, id.fontname) -- マニュアルにはこっちで書いてあるが?
+       if not fl then
+          local index
+         for i,v in ipairs(t) do
+            if v.fontname == id.fontname then index=i; break end
+          end  
+         fl = fontloader.open(id.filename, index)
+        end
       end
+      if not fl then fontloader.close(fl); return dest end
       local ind_to_uni, unicodes = {}, {}
       for i,v in pairs(id.characters) do
          ind_to_uni[v.index] = i
@@ -931,7 +957,7 @@ do
            font_extra_basename[bname] = dat or {}
            ltjb.save_cache( v,
                             {
-                               chksum = checksum(id.filename),
+                               chksum = newsum,
                                version = cache_ver,
                                dat,
                             })
@@ -1039,6 +1065,7 @@ do
 ------------------------------------------------------------------------
 -- VERT VARIANT TABLE
 ------------------------------------------------------------------------
+  local provides_feature = luaotfload.aux.provides_feature
   local vert_form_table = {
      [0x3001]=0xFE11, [0x3002]=0xFE12, [0x3016]=0xFE17, [0x3017]=0xFE18,
      [0x2026]=0xFE19,
@@ -1049,27 +1076,34 @@ do
      [0x300C]=0xFE41, [0x300D]=0xFE42, [0x300E]=0xFE43, [0x300F]=0xFE44,
      [0xFF3B]=0xFE47, [0xFF3D]=0xFE48, 
   }
-  local function add_vform(coverage, vform, ft)
+  local function add_vform(coverage, vform, ft, add_vert)
      if type(coverage)~='table' then return end
      for i,v in pairs(vert_form_table) do
-        if (not coverage[i]) and ft.characters[v] then
+        if not coverage[i] and ft.characters[v] then
             vform[i] = v
         end
      end
+     if add_vert then -- vert feature が有効にならない場合
+       for i,v in pairs(coverage) do vform[i] = vform[i] or v end
+     end
   end
 
 luatexbase.add_to_callback(
    "luatexja.define_jfont",
    function (fmtable, fnum)
       local vform = {}; fmtable.vform = vform
-      local ft = font_getfont(fnum)
-      if ft.specification and ft.resources then
-         for _,i in pairs(ft.resources.sequences) do
-             if i.order[1]== 'vert' and i.type == 'gsub_single' and i.steps then
-                 for _,j in pairs(i.steps) do
-                    if type(j)=='table' then add_vform(j.coverage,vform, ft) end
-                 end
-             end
+      local t = font_getfont(fnum)
+      if t.specification and t.resources then
+        local add_vert  
+          = not (provides_feature(fnum, t.properties.script, t.properties.language, 'vert'))
+            and not (provides_feature(fnum, t.properties.script, t.properties.language, 'vrt2'))
+         -- 現在の language, script で vert もvrt2 も有効にできない場合,強制的に vert 適用
+        for _,i in pairs(t.resources.sequences) do
+           if i.order[1]== 'vert' and i.type == 'gsub_single' and i.steps then
+              for _,j in pairs(i.steps) do
+                 if type(j)=='table' then add_vform(j.coverage,vform, t, add_vert) end
+              end
+           end
          end
       end
       return fmtable
@@ -1128,7 +1162,7 @@ do
        end
    end
    -- EXT: italic correction
-   function append_italic()
+   function luatexja.jfont.append_italic()
       local p = to_direct(tex.nest[tex.nest.ptr].tail)
       local TEMP = node_new(id_kern)
       if p and getid(p)==id_glyph then
@@ -1155,3 +1189,8 @@ do
    end
 end
 
+luatexja.jfont.metrics = metrics
+luatexja.jfont.font_metric_table = font_metric_table
+luatexja.jfont.find_char_class = find_char_class
+
+luatexja.jfont.update_jfm_cache = update_jfm_cache