OSDN Git Service

Updated documents
[luatex-ja/luatexja.git] / src / ltj-jfmglue.lua
index f94b028..d3f9d99 100644 (file)
@@ -1,9 +1,9 @@
 --
--- luatexja/ltj-jfmglue.lua
+-- ltj-jfmglue.lua
 --
 luatexbase.provides_module({
   name = 'luatexja.jfmglue',
-  date = '2019/07/26',
+  date = '2020/01/23',
   description = 'Insertion process of JFM glues, [x]kanjiskip and others',
 })
 luatexja.jfmglue = luatexja.jfmglue or {}
@@ -12,7 +12,8 @@ luatexja.load_module('base');      local ltjb = luatexja.base
 luatexja.load_module('stack');     local ltjs = luatexja.stack
 luatexja.load_module('jfont');     local ltjf = luatexja.jfont
 luatexja.load_module('direction'); local ltjd = luatexja.direction
-luatexja.load_module('setwidth');      local ltjw = luatexja.setwidth
+luatexja.load_module('setwidth');  local ltjw = luatexja.setwidth
+luatexja.load_module('lotf_aux');  local ltju = luatexja.lotf_aux
 local pairs = pairs
 
 --local to_node = node.direct.tonode
@@ -30,9 +31,10 @@ local if_lang_ja
 do
     local lang_ja = luatexja.lang_ja
     local getlang = node.direct.getlang
+    -- glyph with font number 0 (\nullfont) is always considered an ALchar node
     if_lang_ja = getlang 
-      and function (n) return getlang(n)==lang_ja end
-      or  function (n) return getfield(n,'lang')==lang_ja end
+      and function (n) return (getlang(n)==lang_ja)and(getfont(n)~=0) end
+      or  function (n) return (getfield(n,'lang')==lang_ja)and(getfont(n)~=0) end
 end
   
 local has_attr = node.direct.has_attribute
@@ -312,13 +314,11 @@ do -- 002 ---------------------------------------
    local getwhd = node.direct.getwhd
    local attr_jchar_class = luatexbase.attributes['ltj@charclass']
    local attr_jchar_code = luatexbase.attributes['ltj@charcode']
-   local identifiers = fonts.hashes.identifiers
+   local font_getfont = font.getfont
    local function calc_np_notdef(lp)
-      local ident = identifiers[getfont(lp)]
-      if not ident.descriptions[getchar(lp)] then
+      if not font_getfont(getfont(lp)).characters[getchar(lp)] then
         local ln = node_next(lp)
-        if (ident.shared and ident.shared.features and ident.shared.features.notdef)
-           and ln and getid(ln)==id_glyph then 
+        if ltju.specified_feature(getfont(lp), 'notdef') and ln and getid(ln)==id_glyph then 
            set_attr(lp, attr_icflag, PROCESSED)
            set_attr(ln, attr_jchar_code, has_attr(lp, attr_jchar_code) or getchar(lp))
            set_attr(ln, attr_jchar_class, has_attr(lp, attr_jchar_class) or 0)
@@ -557,6 +557,8 @@ function calc_np(last, lp)
    Np.post, Np.pre, Np.xspc = nil, nil, nil
    Np.first, Np.id, Np.last, Np.met, Np.class= nil, nil, nil, nil
    Np.auto_kspc, Np.auto_xspc, Np.char, Np.nuc = nil, nil, nil, nil
+   -- auto_kspc, auto_xspc: normally true/false, 
+   -- but the number 0 when Np is ''the beginning of the box/paragraph''.
    for k in pairs(Np) do Np[k] = nil end
 
    for k = 1,#Bp do Bp[k] = nil end
@@ -782,56 +784,50 @@ do
    local function blend_diffmet(b, a, rb, ra)
       return round(luatexja.jfmglue.diffmet_rule((1-rb)*b+rb*a, (1-ra)*b+ra*a))
    end
+   local blend_diffmet_inf
+   do
+      local abs, log, log264, floor = math.abs, math.log, math.log(2)*64, math.floor
+      blend_diffmet_inf = function (b, a, bo, ao, rb, ra)
+         local nb, na = (bo and b*2.0^(64*bo) or 0), (ao and a*2.0^(64*ao) or 0)
+         local r = luatexja.jfmglue.diffmet_rule((1-rb)*nb+rb*na, (1-ra)*nb+ra*na)
+         local ro = (r~=0) and floor(log(abs(r))/log264+0.0625) or 0
+         return round(r/2.^(64*ro)), ro
+      end
+   end
+   local getglue = luatexja.getglue
    calc_ja_ja_aux = function (gb, ga, db, da)
       if luatexja.jfmglue.diffmet_rule ~= math.two_pleft and diffmet_rule ~= math.two_pright
           and luatexja.jfmglue.diffmet_rule ~= math.two_paverage then
         db, da = 0, 1
       end
       if not gb then
-        if ga then
-           gb = node_new(id_kern, 1); setfield(gb, 'kern', 0)
+        if ga then gb = node_new(id_kern, 1); setfield(gb, 'kern', 0)
         else return nil end
       elseif not ga then
         ga = node_new(id_kern, 1); setfield(ga, 'kern', 0)
       end
-
-      local k = 2*getid(gb) - getid(ga)
-      if k == bg_ag then
-        -- 両方とも glue.
-        setglue(gb, blend_diffmet(
-                       getfield(gb, 'width'), getfield(ga, 'width'), db, da),
-                    blend_diffmet(
-                       getfield(gb, 'stretch'), getfield(ga, 'stretch'), db, da),
-                    -blend_diffmet(
-                    -getfield(gb, 'shrink'), -getfield(ga, 'shrink'), db, da))
-        node_free(ga)
-        return gb
-      elseif k == bk_ak then
-        -- 両方とも kern.
-        setfield(gb, 'kern', blend_diffmet(
-                    getfield(gb, 'kern'), getfield(ga, 'kern'), db, da))
-        node_free(ga)
-        return gb
-      elseif k == bk_ag then
-        -- gb: kern, ga: glue
-        setglue(ga, blend_diffmet(
-                       getfield(gb, 'kern'), getfield(ga, 'width'), db, da),
-                    blend_diffmet(
-                       0, getfield(ga, 'stretch'), db, da),
-                    -blend_diffmet(
-                       0, -getfield(ga, 'shrink'), db, da))
-        node_free(gb)
-        return ga, 0, 0, 0
+      local gbw, gaw, gbst, gast, gbsto, gasto, gbsh, gash, gbsho, gasho
+      if getid(gb)==id_glue then
+         gbw, gbst, gbsh, gbsto, gbsho = getglue(gb)
+      else
+        gbw = getfield(gb, 'kern')
+      end
+      if getid(ga)==id_glue then
+         gaw, gast, gash, gasto, gasho = getglue(ga)
+      else
+        gaw = getfield(ga, 'kern')
+      end
+      if not (gbst or gast) then -- 両方とも kern
+        setfield(gb, 'kern', blend_diffmet(gbw, gaw, db, da))
+        node_free(ga); return gb
       else
-        -- gb: glue, ga: kern
-        setglue(gb, blend_diffmet(
-                       getfield(gb, 'width'), getfield(ga, 'kern'), db, da),
-                    blend_diffmet(
-                       getfield(gb, 'stretch'), 0, db, da),
-                    -blend_diffmet(
-                       -getfield(gb, 'shrink'), 0, db, da))
-        node_free(ga)
-        return gb
+         local gr = gb
+         if not gbst then gr = ga; node_free(gb) else node_free(ga) end
+         gbw = blend_diffmet(gbw or 0, gaw or 0, db, da) -- 結果の自然長
+         gbst, gbsto = blend_diffmet_inf(gbst, gast, gbsto, gasto, db, da) -- 伸び
+         gbsh, gbsho = blend_diffmet_inf(-(gbsh or 0), -(gash or 0), gbsho, gasho, db, da) -- -(縮み)
+        setglue(gr, gbw, gbst, -gbsh, gbsto, gbsho)
+        return gr
       end
    end
 end
@@ -846,7 +842,10 @@ do
    local KANJI_SKIP_JFM   = luatexja.icflag_table.KANJI_SKIP_JFM
 
    get_kanjiskip_low = function(flag, qm, bn, bp, bh)
-      if flag or (qm.with_kanjiskip and (bn or bp or bh)) then
+   -- flag = false: kanjiskip そのもの(パラメータ or JFM)
+   --               ノード kanji_skip のコピーで良い場合は nil が帰る
+   -- flag = true: JFM グルーに付随する kanjiskip 自然長/伸び/縮み分
+      if qm.with_kanjiskip and (bn or bp or bh) then
         if kanjiskip_jfm_flag then
            local g = node_new(id_glue);
            local bk = qm.kanjiskip or null_skip_table
@@ -856,14 +855,14 @@ do
            set_attr(g, attr_icflag, KANJI_SKIP_JFM)
            return g
         elseif flag then
-           return node_copy(kanji_skip)
-        else
-           local g = node_new(id_glue);
+           local g = node_new(id_glue)
+            local st = bp and (bp*getfield(kanji_skip, 'stretch')) or 0
+            local sh = bh and (bh*getfield(kanji_skip, 'shrink')) or 0
            setglue(g,
               bn and (bn*getfield(kanji_skip, 'width')) or 0,
-              bp and (bp*getfield(kanji_skip, 'stretch')) or 0,
-              bh and (bh*getfield(kanji_skip, 'shrink')) or 0,
-              0, 0)
+              st, sh, 
+              (st==0) and 0 or getfield(kanji_skip, 'stretch_order'),
+              (sh==0) and 0 or getfield(kanji_skip, 'shrink_order'))
            set_attr(g, attr_icflag, KANJI_SKIP_JFM)
            return g
         end
@@ -876,11 +875,17 @@ do
       elseif Np.auto_kspc or Nq.auto_kspc then
         local pm, qm = Np.met, Nq.met
         if (pm.char_type==qm.char_type) and (qm.var==pm.var) then
-            return get_kanjiskip_low(true, qm, 1, 1, 1)
+            return get_kanjiskip_low(false, qm, 1, 1, 1) or node_copy(kanji_skip)
         else
-           local gb = get_kanjiskip_low(true, qm, 1, 1, 1)
-           local ga = get_kanjiskip_low(true, pm, 1, 1, 1)
-           return calc_ja_ja_aux(gb, ga, 0, 1)
+           local gb = get_kanjiskip_low(false, qm, 1, 1, 1)
+           if gb then
+               return calc_ja_ja_aux(gb, 
+                 get_kanjiskip_low(false, pm, 1, 1, 1) or node_copy(kanji_skip), 0, 1) 
+           else
+               local ga = get_kanjiskip_low(false, pm, 1, 1, 1)
+               return (ga and calc_ja_ja_aux(node_copy(kanji_skip), ga, 0, 1))
+                       or node_copy(kanji_skip)
+           end
         end
       else   
         local g = node_new(id_glue)
@@ -894,7 +899,7 @@ do
       local qmc, pmc = qm.char_type, pm.char_type
       if (qmc==pmc) and (qm.var==pm.var) then
         local g, _, kn, kp, kh = new_jfm_glue(qmc, Nq.class, Np.class)
-        return g, (Np.auto_kspc or Nq.auto_kspc) and get_kanjiskip_low(false, qm, kn, kp, kh)
+        return g, (Np.auto_kspc or Nq.auto_kspc) and get_kanjiskip_low(true, qm, kn, kp, kh)
       else
         local npn, nqn = Np.nuc, Nq.nuc
         local gb, db, bn, bp, bh 
@@ -908,11 +913,11 @@ do
                                                 Np.class)
         local g = calc_ja_ja_aux(gb, ga, db, da)
         local k
-        if (pmc==qmc) and (qm.var==pm.var) then
-           gb = get_kanjiskip_low(false, qm, bn, bp, bh)
-           ga = get_kanjiskip_low(false, pm, an, ap, ah)
-           k = calc_ja_ja_aux(gb, ga, db, da)
-        end
+        --if (pmc==qmc) and (qm.var==pm.var) then
+         gb = get_kanjiskip_low(true, qm, bn, bp, bh)
+        ga = get_kanjiskip_low(true, pm, an, ap, ah)
+        k = calc_ja_ja_aux(gb, ga, db, da)
+        --end
         return g, k
       end
    end
@@ -946,7 +951,8 @@ do
               bn and (bn*getfield(xkanji_skip, 'width')) or 0,
               bp and (bp*getfield(xkanji_skip, 'stretch')) or 0,
               bh and (bh*getfield(xkanji_skip, 'shrink')) or 0,
-              0, 0)
+              bp and getfield(xkanji_skip, 'stretch_order') or 0,
+              bh and getfield(xkanji_skip, 'shrink_order') or 0)
            set_attr(g, attr_icflag, XKANJI_SKIP_JFM)
            return g
         end
@@ -1005,7 +1011,7 @@ local function get_OA_skip(is_kanji)
       Np.class)
    local k
    if is_kanji==0 then
-      k = combine_spc('auto_kspc') and get_kanjiskip_low(false, pm, kn, kp, kh)
+      k = combine_spc('auto_kspc') and get_kanjiskip_low(true, pm, kn, kp, kh)
    end
    return g, k
 end
@@ -1017,7 +1023,7 @@ local function get_OB_skip(is_kanji)
         (((Np.id==id_glue)or(Np.id==id_kern)) and 'glue' or 'jcharbdd'), qm))
    local k
    if is_kanji==0 then
-      k = combine_spc('auto_kspc') and get_kanjiskip_low(false, qm, kn, kp, kh)
+      k = combine_spc('auto_kspc') and get_kanjiskip_low(true, qm, kn, kp, kh)
    end
    return g, k
 end