--
--- 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 {}
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
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
end
if pid==id_kern then
local pa = get_attr_icflag(p)
- if (pa==IC_PROCESSED)or(pa==BOXBDD) then
- --if (pa==IC_PROCESSED)or(pa==BOXBDD)or(getsubtype(p)==0) then
+ if pa==IC_PROCESSED then
-- do nothing
elseif getsubtype(p)==2 then
p = node_next(node_next(p));
first_char = p; find_first_char = false
end
last_char = p; found_visible_node = true
- elseif (pid==id_rule and get_attr_icflag(p)==PACKED)
- or (pid==id_glue and get_attr_icflag(p)==BOXBDD) then
+ elseif pid==id_rule and get_attr_icflag(p)==PACKED then
-- do nothing
elseif not (pid==id_ins or pid==id_mark
or pid==id_adjust or pid==id_whatsit
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)
local lq = node_next(lp);
head = node_remove(head, lp); node_free(lp); non_ihb_flag = false
return false, lq;
+ elseif getfield(lp, 'user_id')==luatexja.userid_table.JA_AL_BDD then
+ local lq = node_next(lp);
+ head = node_remove(head, lp); node_free(lp)
+ return false, lq;
else
set_attr(lp, attr_icflag, PROCESSED)
luatexbase.call_callback("luatexja.jfmglue.whatsit_getinfo",
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
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
- -- 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
+ 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
+ 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
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
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
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)
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
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
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
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
(((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
end
do
- local IHB = luatexja.userid_table.IHB
+ local IHB = luatexja.userid_table.IHB
local BPAR = luatexja.userid_table.BPAR
local BOXB = luatexja.userid_table.BOXB
local node_prev = node.direct.getprev