--
luatexbase.provides_module({
name = 'luatexja.jfmglue',
- date = '2020-12-20',
+ date = '2022-08-18',
description = 'Insertion process of JFM glues, [x]kanjiskip and others',
})
luatexja.jfmglue = luatexja.jfmglue or {}
--local to_node = node.direct.tonode
--local to_direct = node.direct.todirect
-local setfield = node.direct.setfield
-local setglue = luatexja.setglue
local getfield = node.direct.getfield
local getid = node.direct.getid
local getfont = node.direct.getfont
local getlist = node.direct.getlist
local getchar = node.direct.getchar
+local getglue = luatexja.getglue
local getsubtype = node.direct.getsubtype
+local getshift = node.direct.getshift
+local getwidth = node.direct.getwidth
+local getdepth = node.direct.getdepth
+local getpenalty = node.direct.getpenalty
+local setfield = node.direct.setfield
+local setglue = luatexja.setglue
+local setshift = node.direct.setshift
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)and(getfont(n)~=0) end
- or function (n) return (getfield(n,'lang')==lang_ja)and(getfont(n)~=0) end
+ if_lang_ja = function (n) return (getlang(n)==lang_ja)and(getfont(n)~=0) end
end
+local setpenalty = node.direct.setpenalty
+local setkern = node.direct.setkern
local has_attr = node.direct.has_attribute
local set_attr = node.direct.set_attribute
local ltjd_make_dir_whatsit = ltjd.make_dir_whatsit
local ltjf_font_metric_table = ltjf.font_metric_table
local ltjf_find_char_class = ltjf.find_char_class
-local node_new = node.direct.new
+local node_new = luatexja.dnode_new
local node_copy = node.direct.copy
local node_tail = node.direct.tail
-local node_free = node.direct.free
+local node_free = node.direct.flush_node or node.direct.free
local node_remove = node.direct.remove
+local node_inherit_attr = luatexja.node_inherit_attr
local id_glyph = node.id 'glyph'
local id_hlist = node.id 'hlist'
local PROCESSED = luatexja.icflag_table.PROCESSED
local IC_PROCESSED = luatexja.icflag_table.IC_PROCESSED
local BOXBDD = luatexja.icflag_table.BOXBDD
+local SPECIAL_JAGLUE = luatexja.icflag_table.SPECIAL_JAGLUE
local PROCESSED_BEGIN_FLAG = luatexja.icflag_table.PROCESSED_BEGIN_FLAG
local attr_icflag = luatexbase.attributes['ltj@icflag']
-- penalty 値の計算
local add_penalty
do
-local setpenalty = node.direct.setpenalty or function(n, a) setfield(n,'penalty',a) end
-local getpenalty = node.direct.getpenalty or function(n) return getfield(n,'penalty') end
function add_penalty(p,e)
local pp = getpenalty(p)
if (pp>-10000) and (pp<10000) then
if find_first_char then first_char = s; find_first_char = false end
last_char = s; found_visible_node = true
else
- if getfield(p, 'shift')==0 then
+ if getshift(p)==0 then
last_char = nil
if check_box(getlist(p), nil) then found_visible_node = true end
find_first_char = false
local attr_jchar_class = luatexbase.attributes['ltj@charclass']
local attr_jchar_code = luatexbase.attributes['ltj@charcode']
local font_getfont = font.getfont
+ local setwhd = node.direct.setwhd
+ local setdir = node.direct.setdir
local function calc_np_notdef(lp)
if not font_getfont(getfont(lp)).characters[getchar(lp)] then
local ln = node_next(lp)
local first_glyph, last_glyph = lp
set_attr(lp, attr_icflag, PROCESSED); Np.last = lp
local y_adjust = has_attr(lp,attr_ablshift) or 0
- local node_depth = getfield(lp, 'depth') + min(y_adjust, 0)
- local adj_depth = (y_adjust>0) and (getfield(lp, 'depth') + y_adjust) or 0
+ local node_depth = getdepth(lp) + min(y_adjust, 0)
+ local adj_depth = (y_adjust>0) and (getdepth(lp) + y_adjust) or 0
setfield(lp, 'yoffset', getfield(lp, 'yoffset') - y_adjust); lp = node_next(lp)
local lx=lp
while lx do
local lai = get_attr_icflag(lx)
- if lx==last or lai>=PACKED then
- lp=lx; break
+ if lx==last or lai>=PACKED then break
else
local lid = getid(lx)
if lid==id_glyph and not if_lang_ja(lx) then
-- 欧文文字
last_glyph = lx; set_attr(lx, attr_icflag, PROCESSED); Np.last = lx
y_adjust = has_attr(lx,attr_ablshift) or 0
- node_depth = max(getfield(lx, 'depth') + min(y_adjust, 0), node_depth)
- adj_depth = (y_adjust>0) and max(getfield(lx, 'depth') + y_adjust, adj_depth) or adj_depth
+ node_depth = max(getdepth(lx) + min(y_adjust, 0), node_depth)
+ adj_depth = (y_adjust>0) and max(getdepth(lx) + y_adjust, adj_depth) or adj_depth
setfield(lx, 'yoffset', getfield(lx, 'yoffset') - y_adjust); lx = node_next(lx)
elseif lid==id_kern then
local ls = getsubtype(lx)
if getid(lx)==id_glyph then
setfield(lx, 'yoffset', getfield(lx, 'yoffset') - (has_attr(lx,attr_ablshift) or 0))
else -- アクセントは上下にシフトされている
- setfield(lx, 'shift', getfield(lx, 'shift') + (has_attr(lx,attr_ablshift) or 0))
+ setshift(lx, getshift(lx) + (has_attr(lx,attr_ablshift) or 0))
end
- lx = node_next(node_next(lx))
+ set_attr(lx, attr_icflag, PROCESSED)
+ lx = node_next(lx); set_attr(lx, attr_icflag, PROCESSED)
+ lx = node_next(lx); set_attr(lx, attr_icflag, PROCESSED)
elseif ls==0 then
Np.last = lx; lx = node_next(lx)
elseif (ls==3) or (lai==ITALIC) then
Np.last = lx; set_attr(lx, attr_icflag, IC_PROCESSED); lx = node_next(lx)
- else
- lp=lx; break
+ else break
end
- else
- lp=lx; break
+ else break
end
end
end
+ lp=lx
local r
if adj_depth>node_depth then
- r = node_new(id_rule,3)
- setfield(r, 'width', 0); setfield(r, 'height', 0)
- setfield(r, 'depth',adj_depth); setfield(r, 'dir', tex_dir)
+ r = node_new(id_rule,3,first_glyph)
+ setwhd(r, 0, 0, adj_depth); setdir(r, tex_dir)
set_attr(r, attr_icflag, PROCESSED)
end
if last_glyph then
head, lp, op, flag = ltjd_make_dir_whatsit(head, lp, list_dir, 'jfm hlist')
set_attr(op, attr_icflag, PROCESSED)
Np.first = Np.first or op; Np.last = op; Np.nuc = op;
- if (flag or getfield(op, 'shift')~=0) then
+ if (flag or getshift(op)~=0) then
Np.id = id_box_like
else
Np.id = id_hlist
if lps==sid_user then
if getfield(lp, 'user_id')==luatexja.userid_table.IHB then
local lq = node_next(lp);
- head = node_remove(head, lp); node_free(lp); non_ihb_flag = false
+ head = node_remove(head, lp); node_free(lp); non_ihb_flag = getfield(lp, 'value')~=1
return false, lq;
elseif getfield(lp, 'user_id')==luatexja.userid_table.JA_AL_BDD then
local lq = node_next(lp);
end,
[id_glue] = function(lp)
Np.first, Np.nuc, Np.last = (Np.first or lp), lp, lp;
- Np.id = getid(lp); set_attr(lp, attr_icflag, PROCESSED)
+ Np.id = getid(lp);
+ local f = luatexbase.call_callback("luatexja.jfmglue.special_jaglue", lp)
+ if f then
+ set_attr(lp, attr_icflag, PROCESSED)
+ end
return true, node_next(lp)
end,
[id_disc] = function(lp)
if getid(lp)==id_glyph then -- アクセント本体
setfield(lp, 'yoffset', getfield(lp, 'yoffset') - (has_attr(lp,attr_ablshift) or 0))
else -- アクセントは上下にシフトされている
- setfield(lp, 'shift', getfield(lp, 'shift') + (has_attr(lp,attr_ablshift) or 0))
+ setshift(lp, getshift(lp) + (has_attr(lp,attr_ablshift) or 0))
end
set_attr(lp, attr_icflag, PROCESSED); lp = node_next(lp)
set_attr(lp, attr_icflag, PROCESSED); lp = node_next(lp)
while lp ~= last do
local lpa = has_attr(lp, attr_icflag) or 0
-- unbox 由来ノードの検出
- if lpa>=PACKED then
+ if (lpa>=PACKED) and (lpa%PROCESSED_BEGIN_FLAG<=BOXBDD) then
if lpa%PROCESSED_BEGIN_FLAG == BOXBDD then
local lq = node_next(lp)
head = node_remove(head, lp); node_free(lp); lp = lq
Nx.post = table_current_stack[POST + c] or 0
Nx.xspc = table_current_stack[XSP + c] or 3
Nx.kcat = table_current_stack[KCAT + c] or 0
- Nx.auto_kspc, Nx.auto_xspc = (has_attr(x, attr_autospc)==1), (has_attr(x, attr_autoxspc)==1)
+ Nx.auto_kspc, Nx.auto_xspc
+ = not has_attr(x, attr_autospc, 0), not has_attr(x, attr_autoxspc, 0)
return m, mc, cls
end
function set_np_xspc_jachar_hbox(Nx, x)
Nx.post = table_current_stack[POST + c] or 0
Nx.xspc = table_current_stack[XSP + c] or 3
Nx.kcat = table_current_stack[KCAT + c] or 0
- Nx.auto_kspc, Nx.auto_xspc = (has_attr(x, attr_autospc)==1), (has_attr(x, attr_autoxspc)==1)
+ Nx.auto_kspc, Nx.auto_xspc
+ = not has_attr(x, attr_autospc, 0), not has_attr(x, attr_autoxspc, 0)
end
-- 欧文文字のデータを取得
end
Nx.met = nil
Nx.xspc = table_current_stack[XSP + c] or 3
- Nx.auto_xspc = (has_attr(x, attr_autoxspc)==1)
+ Nx.auto_xspc = not has_attr(x, attr_autoxspc, 0)
end
local set_np_xspc_alchar = set_np_xspc_alchar
-- change the information for the next loop
local a = (pre or 0) + (post or 0)
if #Bp == 0 then
if (a~=0 and not(g and getid(g)==id_kern)) then
- local p = node_new(id_penalty)
+ local p = node_new(id_penalty, nil, Nq.nuc, Np.nuc)
if a<-10000 then a = -10000 elseif a>10000 then a = 10000 end
- setfield(p, 'penalty', a); head = insert_before(head, Np.first, p)
+ setpenalty(p, a); head = insert_before(head, Np.first, p)
Bp[1]=p; set_attr(p, attr_icflag, KINSOKU)
end
else for _, v in pairs(Bp) do add_penalty(v,a) end
local a = (pre or 0) + (post or 0)
if #Bp == 0 then
if not (g and getid(g)==id_glue) or a~=0 then
- local p = node_new(id_penalty)
+ local p = node_new(id_penalty, nil, Nq.nuc, Np.nuc)
if a<-10000 then a = -10000 elseif a>10000 then a = 10000 end
- setfield(p, 'penalty', a); head = insert_before(head, Np.first, p)
+ setpenalty(p, a); head = insert_before(head, Np.first, p)
Bp[1]=p; set_attr(p, attr_icflag, KINSOKU)
end
else for _, v in pairs(Bp) do add_penalty(v,a) end
luatexbase.call_callback('luatexja.adjust_jfmglue', head, Nq, Np, Bp)
if #Bp == 0 then
if g and getid(g)==id_glue then
- local p = node_new(id_penalty)
- setfield(p, 'penalty', 10000); head = insert_before(head, Np.first, p)
+ local p = node_new(id_penalty, nil, Nq.nuc, Np.nuc)
+ setpenalty(p, 10000); head = insert_before(head, Np.first, p)
Bp[1]=p; set_attr(p, attr_icflag, KINSOKU)
end
else
local a = table_current_stack[luatexja.stack_table_index.JWP]
if #widow_Bp == 0 then
if a~=0 then
- local p = node_new(id_penalty)
+ local p = node_new(id_penalty, widow_Np.nuc)
if a<-10000 then a = -10000 elseif a>10000 then a = 10000 end
- setfield(p, 'penalty', a); head = insert_before(head, widow_Np.first, p)
+ setpenalty(p, a); head = insert_before(head, widow_Np.first, p)
widow_Bp[1]=p; set_attr(p, attr_icflag, KINSOKU)
end
else for _, v in pairs(widow_Bp) do add_penalty(v,a) end
local g = mc[bc][ac]
if g then
if g[1] then
- return node_copy(g[1]), g.ratio, false, false, false
+ local k = node_new(id_kern, 1); setkern(k, g[1])
+ set_attr(k, attr_icflag, FROM_JFM)
+ return k, g.ratio, false, false, false
else
- local f = node_new(id_glue)
- set_attr(f, attr_icflag, g.priority)
- setglue(f, g.width, g.stretch, g.shrink)
- return f, g.ratio, g.kanjiskip_natural, g.kanjiskip_stretch, g.kanjiskip_shrink
+ local f = node_new(id_glue)
+ set_attr(f, attr_icflag, g.priority)
+ setglue(f, g.width, g.stretch, g.shrink)
+ return f, g.ratio, g.kanjiskip_natural, g.kanjiskip_stretch, g.kanjiskip_shrink
end
end
return false, 0
-- Nq.last (kern w) .... (glue/kern g) Np.first
local function real_insert(g)
if g then
- head = insert_before(head, Np.first, g)
- Np.first = g
+ head, Np.first = insert_before(head, Np.first, node_inherit_attr(g, Nq.nuc, Np.nuc))
local ngk = Np.gk
if not ngk then Np.gk = g
elseif type(ngk)=="table" then ngk[#ngk+1]=g
local bg_ak = 2*id_glue - id_kern
local bk_ag = 2*id_kern - id_glue
local bk_ak = 2*id_kern - id_kern
+ local getkern = node.direct.getkern
local function blend_diffmet(b, a, rb, ra)
return round(luatexja.jfmglue.diffmet_rule((1-rb)*b+rb*a, (1-ra)*b+ra*a))
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); setkern(gb, 0)
else return nil end
elseif not ga then
- ga = node_new(id_kern, 1); setfield(ga, 'kern', 0)
+ ga = node_new(id_kern, 1); setkern(ga, 0)
end
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')
+ gbw = getkern(gb)
end
if getid(ga)==id_glue then
gaw, gast, gash, gasto, gasho = getglue(ga)
else
- gaw = getfield(ga, 'kern')
+ gaw = getkern(ga)
end
if not (gbst or gast) then -- 両方とも kern
- setfield(gb, 'kern', blend_diffmet(gbw, gaw, db, da))
+ setkern(gb, blend_diffmet(gbw, gaw, db, da))
node_free(ga); return gb
else
local gr = gb
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,
+ bn and (bn*getwidth(kanji_skip)) or 0,
st, sh,
(st==0) and 0 or getfield(kanji_skip, 'stretch_order'),
(sh==0) and 0 or getfield(kanji_skip, 'shrink_order'))
elseif flag then
return node_copy(xkanji_skip)
else
- local g = node_new(id_glue);
+ local g = node_new(id_glue)
+ local w, st, sh, sto, sho = getglue(xkanji_skip)
setglue(g,
- 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,
- bp and getfield(xkanji_skip, 'stretch_order') or 0,
- bh and getfield(xkanji_skip, 'shrink_order') or 0)
+ bn and (bn*w) or 0,
+ bp and (bp*st) or 0,
+ bh and (bh*sh) or 0,
+ bp and sto or 0,
+ bh and sho or 0)
set_attr(g, attr_icflag, XKANJI_SKIP_JFM)
return g
end
-- NA, NB: alchar or math
local function get_NA_skip()
local pm = Np.met
- local g, _, kn, kp, kh = new_jfm_glue(
- pm.char_type,
- fast_find_char_class(
- (Nq.id == id_math and -1 or (Nq.xspc>=2 and 'alchar' or 'nox_alchar')), pm),
- Np.class)
- local k = ((Nq.xspc>=2) and (Np.xspc%2==1) and combine_spc 'auto_xspc')
- and get_xkanjiskip_low(false, pm, kn, kp, kh)
+ local qclass = fast_find_char_class(
+ (Nq.id == id_math and -1 or (Nq.xspc>=2 and 'alchar' or 'nox_alchar')), pm)
+ local g, _, kn, kp, kh = new_jfm_glue(pm.char_type, qclass, Np.class)
+ local k = g and (Nq.xspc>=2) and (Np.xspc%2==1) and combine_spc 'auto_xspc'
+ and get_kanjiskip_low(true, pm, kn, kp, kh)
return g, k
end
local function get_NB_skip()
local qm = Nq.met
- local g, _, kn, kp, kh = new_jfm_glue(
- qm.char_type, Nq.class,
- fast_find_char_class(
- (Np.id == id_math and -1 or (Np.xspc%2==1 and 'alchar' or 'nox_alchar')), qm)
- )
- local k = ((Nq.xspc>=2) and (Np.xspc%2==1) and combine_spc 'auto_xspc')
- and get_xkanjiskip_low(false, qm, kn, kp, kh)
+ local pclass = fast_find_char_class(
+ (Np.id == id_math and -1 or (Np.xspc%2==1 and 'alchar' or 'nox_alchar')), qm)
+ local g, _, kn, kp, kh = new_jfm_glue(qm.char_type, Nq.class, pclass)
+ local k = g and (Nq.xspc>=2) and (Np.xspc%2==1) and combine_spc 'auto_xspc'
+ and get_kanjiskip_low(true, qm, kn, kp, kh)
return g, k
end
if not g then g = get_kanjiskip() end
handle_penalty_normal(0, Np.pre, g); real_insert(g); real_insert(k)
elseif Nq.pre then
- local g, k
- if non_ihb_flag then g, k = get_NA_skip() end -- N_A->X
+ local g, k; if non_ihb_flag then g, k = get_NA_skip() end -- N_A->X
if not g then g = get_xkanjiskip(Np) end
handle_penalty_normal((qid==id_hlist and 0 or Nq.post), Np.pre, g);
real_insert(g); real_insert(k)
-- jachar .. (anything)
local function handle_nq_jachar()
if Np.pre then
- local g = non_ihb_flag and get_NB_skip() or get_xkanjiskip(Nq) -- N_B->X
- handle_penalty_normal(Nq.post, (Np.id==id_hlist and 0 or Np.pre), g); real_insert(g)
+ local g, k; if non_ihb_flag then g, k = get_NB_skip()end -- N_B->X
+ if not g then g = get_xkanjiskip(Nq) end
+ handle_penalty_normal(Nq.post, (Np.id==id_hlist and 0 or Np.pre), g);
+ real_insert(g); real_insert(k)
else
local g =non_ihb_flag and (get_OB_skip()) -- O_B
if Np.id==id_glue then handle_penalty_normal(Nq.post, 0, g)
do
local adjust_nq_aux = {
[id_glyph] = function() after_alchar(Nq) end, -- after_alchar(Nq)
- [id_hlist] = function() after_hlist(Nq) end,
+ [id_hlist] = function() after_hlist(Nq) end,
[id_pbox] = function() after_hlist(Nq) end,
[id_disc] = function() after_hlist(Nq) end,
- [id_pbox_w] = function()
- luatexbase.call_callback("luatexja.jfmglue.whatsit_after",
- false, Nq, Np)
- end,
+ [id_glue] = function()
+ luatexbase.call_callback("luatexja.jfmglue.special_jaglue_after", Nq.nuc)
+ end,
+ [id_pbox_w]= function()
+ local hh = luatexbase.call_callback("luatexja.jfmglue.whatsit_after", false, Nq, Np, head)
+ -- hh: new head of false (nott processed)
+ if hh then head = hh end
+ end,
}
adjust_nq = function()
if g then
set_attr(g, attr_icflag, BOXBDD)
if getid(g)==id_glue and #Bp==0 then
- local h = node_new(id_penalty)
- setfield(h, 'penalty', 10000); set_attr(h, attr_icflag, BOXBDD)
+ local h = node_new(id_penalty, nil, Np.nuc)
+ setpenalty(h, 10000); set_attr(h, attr_icflag, BOXBDD)
end
head = insert_before(head, Np.first, g)
end
attr_ablshift = is_dir_tate and attr_tablshift or attr_yablshift
local TEMP = node_new(id_glue)
-- TEMP is a dummy node, which will be freed at the end of the callback.
- -- ithout this node, set_attr(kanji_skip, ...) somehow creates an "orphaned" attribute list.
-
+ -- Without this node, set_attr(kanji_skip, ...) somehow creates an "orphaned" attribute list.
do
kanji_skip, kanjiskip_jfm_flag = skip_table_to_glue(KSK)
set_attr(kanji_skip, attr_icflag, KANJI_SKIP)
end
-
do
xkanji_skip, xkanjiskip_jfm_flag = skip_table_to_glue(XSK)
set_attr(xkanji_skip, attr_icflag, XKANJI_SKIP)
end
-
if mode then
-- the current list is to be line-breaked:
-- hbox from \parindent is skipped.
or (lpi==id_local)) do
if (lpi==id_hlist) and (lps==3) then
Np.char, par_indented = 'parbdd', 'parbdd'
- Np.width = getfield(lp, 'width')
+ Np.width = getwidth(lp)
end
lp=node_next(lp); lpi, lps = getid(lp), getsubtype(lp) end
return lp, node_tail(head), par_indented, TEMP
local node_prev = node.direct.getprev
local node_write = node.direct.write
- -- \inhibitglue
- function luatexja.jfmglue.create_inhibitglue_node()
+ -- \inhibitglue, \disinhibitglue
+ local function ihb_node(v)
local tn = node_new(id_whatsit, sid_user)
setfield(tn, 'user_id', IHB)
setfield(tn, 'type', 100)
- setfield(tn, 'value', 1)
+ setfield(tn, 'value', v)
node_write(tn)
end
+ function luatexja.jfmglue.create_inhibitglue_node()
+ ihb_node(1)
+ end
+ function luatexja.jfmglue.create_disinhibitglue_node()
+ ihb_node(0)
+ end
-- Node for indicating beginning of a paragraph
-- (for ltjsclasses)
end
end
- local function whatsit_after_callback(s, Nq, Np)
+ local function whatsit_after_callback(s, Nq, Np, head)
if not s and getfield(Nq.nuc, 'user_id') == BPAR then
local x, y = node_prev(Nq.nuc), Nq.nuc
Nq.first, Nq.nuc, Nq.last = x, x, x
Nq.met = Np.met; Nq.pre = 0; Nq.post = 0; Nq.xspc = 0
Nq.auto_xspc, Nq.auto_kspc = 0, 0
end
- head = node_remove(head, y)
+ s = node_remove(head, y)
node_free(y)
elseif not s and getfield(Nq.nuc, 'user_id') == BOXB then
local x, y = node_prev(Nq.nuc), Nq.nuc
Nq.met = Np.met; Nq.pre = 0; Nq.post = 0; Nq.xspc = 0
Nq.auto_xspc, Nq.auto_kspc = 0, 0
end
- head = node_remove(head, y)
+ s = node_remove(head, y)
node_free(y)
end
return s
end
do
+ local node_prev = node.direct.getprev
local node_write = node.direct.write
local XKANJI_SKIP = luatexja.icflag_table.XKANJI_SKIP
local XKANJI_SKIP_JFM = luatexja.icflag_table.XKANJI_SKIP_JFM
- local XSK = luatexja.stack_table_index.XSK
local KANJI_SKIP = luatexja.icflag_table.KANJI_SKIP
local KANJI_SKIP_JFM = luatexja.icflag_table.KANJI_SKIP_JFM
+ local XSK = luatexja.stack_table_index.XSK
local KSK = luatexja.stack_table_index.KSK
- local get_dir_count = ltjd.get_dir_count
- local dir_tate = luatexja.dir_table.dir_tate
- local attr_curjfnt = luatexbase.attributes['ltj@curjfnt']
- local attr_curtfnt = luatexbase.attributes['ltj@curtfnt']
+ local attr_yablshift = luatexbase.attributes['ltj@yablshift']
+ local attr_tablshift = luatexbase.attributes['ltj@tablshift']
+ local getcount, abs, scan_keyword = tex.getcount, math.abs, token.scan_keyword
+ local tex_nest = tex.nest
+ local tex_getattr = tex.getattribute
+ local get_current_jfont
+ do
+ local attr_curjfnt = luatexbase.attributes['ltj@curjfnt']
+ local attr_curtfnt = luatexbase.attributes['ltj@curtfnt']
+ local dir_tate = luatexja.dir_table.dir_tate
+ local get_dir_count = ltjd.get_dir_count
+ function get_current_jfont()
+ return tex_getattr((get_dir_count()==dir_tate) and attr_curtfnt or attr_curjfnt)
+ end
+ end
-- \insertxkanjiskip
- function luatexja.jfmglue.insert_xk_skip()
- local st = ltjs.get_stack_skip(XSK, tex.getcount('ltj@@stack'))
- if st.width==1073741823 then
- local j = ltjf_font_metric_table[
- tex.getattribute((get_dir_count()==dir_tate) and attr_curtfnt or attr_curjfnt)
- ]
- if j.xkanjiskip then
- local g, bk = node_new(id_glue), j.xkanjiskip
- setglue(g, bk[1] or 0, bk[2] or 0, bk[3] or 0, 0, 0)
- set_attr(g, attr_icflag, XKANJI_SKIP_JFM); node_write(g)
- return
+ -- SPECIAL_JAGLUE のノード:
+ -- * (X)KANJI_SKIP(_JFM): その場で値が決まっている
+ -- * PROCESSED_BEGIN_FLAG + (X)KANJI_SKIP: 段落終了時に決める
+ local function insert_k_skip_common(ind, name, ica, icb)
+ if abs(tex_nest[tex_nest.ptr].mode) ~= ltjs.hmode then return end
+ local g = node_new(id_glue); set_attr(g, attr_icflag, SPECIAL_JAGLUE)
+ local is_late = scan_keyword("late")
+ if not is_late then
+ local st = ltjs.get_stack_skip(ind, getcount('ltj@@stack'))
+ if st.width==1073741823 then
+ local bk = ltjf_font_metric_table[get_current_jfont()][name]
+ if bk then
+ setglue(g, bk[1] or 0, bk[2] or 0, bk[3] or 0, 0, 0)
+ end
+ set_attr(g, attr_yablshift, icb); node_write(g); return
end
+ setglue(g, st.width, st.stretch, st.shrink, st.stretch_order, st.shrink_order)
+ set_attr(g, attr_yablshift, ica)
+ else
+ set_attr(g, attr_yablshift, PROCESSED_BEGIN_FLAG + ica)
+ set_attr(g, attr_tablshift, get_current_jfont())
end
- local g = node_new(id_glue)
- setglue(g, st.width, st.stretch, st.shrink, st.stretch_order, st.shrink_order)
- set_attr(g, attr_icflag, XKANJI_SKIP); node_write(g)
+ node_write(g)
+ end
+ function luatexja.jfmglue.insert_xk_skip()
+ insert_k_skip_common(XSK, "xkanjiskip", XKANJI_SKIP, XKANJI_SKIP_JFM)
end
- -- \insertkanjiskip
function luatexja.jfmglue.insert_k_skip()
- local st = ltjs.get_stack_skip(KSK, tex.getcount('ltj@@stack'))
- if st.width==1073741823 then
- local j = ltjf_font_metric_table[
- tex.getattribute((get_dir_count()==dir_tate) and attr_curtfnt or attr_curjfnt)
- ]
- if j.kanjiskip then
- local g, bk = node_new(id_glue), j.kanjiskip
- setglue(g, bk[1] or 0, bk[2] or 0, bk[3] or 0, 0, 0)
- set_attr(g, attr_icflag, KANJI_SKIP_JFM); node_write(g)
- return
+ insert_k_skip_common(KSK, "kanjiskip", KANJI_SKIP, KANJI_SKIP_JFM)
+ end
+ -- callback
+ local function special_jaglue(lx)
+ local lxi = get_attr_icflag(lx)
+ if lxi==SPECIAL_JAGLUE then
+ non_ihb_flag = false; return false
+ else
+ return lx
+ end
+ end
+ local function special_jaglue_after_inner(lx, lxi, lxi_jfm, kn, bk)
+ local w, st, sh, sto, sho = getglue(kn)
+ if w~=1073741823 then
+ setglue(lx, w, st, sh, sto, sho); set_attr(lx, attr_icflag, lxi)
+ else
+ local m = ltjf_font_metric_table[has_attr(lx, attr_tablshift)]
+ setglue(lx, bk[1], bk[2], bk[3], 0, 0)
+ set_attr(lx, attr_icflag, lxi_jfm)
+ end
+ end
+ local function special_jaglue_after(lx)
+ if get_attr_icflag(lx)==SPECIAL_JAGLUE then
+ lxi=has_attr(lx, attr_yablshift)
+ if lxi>=PROCESSED_BEGIN_FLAG then
+ lxi = lxi%PROCESSED_BEGIN_FLAG
+ if lxi == KANJI_SKIP then
+ special_jaglue_after_inner(lx, lxi, KANJI_SKIP_JFM, kanji_skip,
+ ltjf_font_metric_table[has_attr(lx, attr_tablshift)].kanjiskip or null_skip_table)
+ else -- lxi == XKANJI_SKIP
+ special_jaglue_after_inner(lx, lxi, XKANJI_SKIP_JFM, xkanji_skip,
+ ltjf_font_metric_table[has_attr(lx, attr_tablshift)].xkanjiskip or null_skip_table)
+ end
+ else
+ set_attr(lx, attr_icflag, lxi)
+ end
+ Np.first = lx
+ if node_prev(lx) then
+ local lxp = node_prev(lx)
+ if lxp and getid(lxp)==id_penalty and get_attr_icflag(lxp)==KINSOKU then
+ Bp[#Bp+1]=lxp
+ end
end
+ non_ihb_flag = false; return false
end
- local g = node_new(id_glue)
- setglue(g, st.width, st.stretch, st.shrink, st.stretch_order, st.shrink_order)
- set_attr(g, attr_icflag, KANJI_SKIP); node_write(g)
+ return true
end
+ luatexbase.create_callback("luatexja.jfmglue.special_jaglue", "list",
+ special_jaglue)
+ luatexbase.create_callback("luatexja.jfmglue.special_jaglue_after", "list",
+ special_jaglue_after)
end