--
--- luatexja/jfmglue.lua
+-- luatexja/ltj-jfmglue.lua
--
luatexbase.provides_module({
name = 'luatexja.jfmglue',
- date = '2012/07/19',
- version = '0.5',
+ date = '2013/12/05',
description = 'Insertion process of JFM glues and kanjiskip',
})
module('luatexja.jfmglue', package.seeall)
local insert_before = node.insert_before
local node_next = node.next
local round = tex.round
-local ltjs_fast_get_penalty_table = ltjs.fast_get_penalty_table
local ltjf_font_metric_table = ltjf.font_metric_table
local ltjf_find_char_class = ltjf.find_char_class
local node_new = node.new
local id_penalty = node.id('penalty')
local id_glue_spec = node.id('glue_spec')
-local id_jglyph = node.id('glyph') + 256 -- Japanese character
-local id_box_like = node.id('hlist') + 256 -- vbox, shifted hbox
-local id_pbox = node.id('hlist') + 512 -- already processed nodes (by \unhbox)
-local id_pbox_w = node.id('hlist') + 513 -- cluster which consists of a whatsit
+local id_jglyph = 512 -- Japanese character
+local id_box_like = 256 -- vbox, shifted hbox
+local id_pbox = 257 -- already processed nodes (by \unhbox)
+local id_pbox_w = 258 -- cluster which consists of a whatsit
local sid_user = node.subtype('user_defined')
local sid_start_link = node.subtype('pdf_start_link')
local PROCESSED_BEGIN_FLAG = luatexja.icflag_table.PROCESSED_BEGIN_FLAG
local kanji_skip
local xkanji_skip
+local table_current_stack
local attr_curjfnt = luatexbase.attributes['ltj@curjfnt']
local attr_icflag = luatexbase.attributes['ltj@icflag']
-local max_dimen = 1073741823
local function get_attr_icflag(p)
return (has_attr(p, attr_icflag) or 0)%PROCESSED_BEGIN_FLAG
-- This function is called only for acquiring `special' characters.
local function fast_find_char_class(c,m)
- return m.size_cache.chars[c] or 0
+ return m.chars[c] or 0
end
-- 文字クラスの決定
local function slow_find_char_class(c, m, oc)
local xc = c or oc
local cls = ltjf_find_char_class(oc, m)
- if xc ~= oc and cls==0 then cls, xc = ltjf_find_char_class(-xc, m) end
+ if xc ~= oc and cls==0 then cls = ltjf_find_char_class(-xc, m) end
return cls, xc
end
local function check_box(box_ptr, box_end)
local p = box_ptr; local found_visible_node = false
if not p then
- find_first_char = false; first_char = nil; last_char = nil
+ find_first_char = false; last_char = nil
return true
end
while p and p~=box_end do
first_char = p; find_first_char = false
end
last_char = p; found_visible_node = true; p=node_next(p)
- if (not p) or p==box_end then return found_visible_node end
+ if (not p) or p==box_end then
+ return found_visible_node
+ end
until p.id~=id_glyph
pid = p.id -- p must be non-nil
end
if check_box(box_ptr, box_end) then
local first_char = first_char
if first_char then
- if first_char.id==glyph_node then
+ if first_char.id==id_glyph then
if first_char.font == (has_attr(first_char, attr_curjfnt) or -1) then
set_np_xspc_jachar(Nx, first_char)
else
local calc_np_auxtable = {
- [id_glyph] = function (lp)
+ [id_glyph] = function (lp)
Np.first, Np.nuc = (Np.first or lp), lp;
Np.id = (lp.font == (has_attr(lp, attr_curjfnt) or -1)) and id_jglyph or id_glyph
--set_attr_icflag_processed(lp) treated in ltj-setwidth.lua
end,
[id_hlist] = function(lp)
Np.first = Np.first or lp; Np.last = lp; Np.nuc = lp;
- set_attr_icflag_processed(lp)
+ set_attr(lp, attr_icflag, PROCESSED)
+ --set_attr_icflag_processed(lp)
Np.id = (lp.shift~=0) and id_box_like or id_hlist
return true, node_next(lp)
end,
box_like = function(lp)
Np.first = Np.first or lp; Np.nuc = lp; Np.last = lp;
- Np.id = id_box_like; set_attr_icflag_processed(lp);
+ Np.id = id_box_like; set_attr(lp, attr_icflag, PROCESSED)
+ -- set_attr_icflag_processed(lp);
return true, node_next(lp);
end,
skip = function(lp)
- set_attr_icflag_processed(lp); return false, node_next(lp)
+ set_attr(lp, attr_icflag, PROCESSED)
+ -- set_attr_icflag_processed(lp);
+ return false, node_next(lp)
end,
[id_whatsit] = function(lp)
if lp.subtype==sid_user then
- if lp.user_id==30111 then
+ if lp.user_id==luatexja.userid_table.IHB then
local lq = node_next(lp);
head = node.remove(head, lp); node.free(lp); ihb_flag = true
return false, lq;
else
- set_attr_icflag_processed(lp)
+ set_attr(lp, attr_icflag, PROCESSED)
+ -- set_attr_icflag_processed(lp)
luatexbase.call_callback("luatexja.jfmglue.whatsit_getinfo",
Np, lp, Nq)
if Np.nuc then
elseif lp.subtype == sid_end_link or lp.subtype == sid_end_thread then
Np.first, Nq.last = nil, lp;
end
- set_attr_icflag_processed(lp); return false, node_next(lp)
+ set_attr(lp, attr_icflag, PROCESSED)
+ -- set_attr_icflag_processed(lp);
+ return false, node_next(lp)
end
end,
[id_math] = function(lp)
Np.first, Np.nuc = (Np.first or lp), lp;
- set_attr_icflag_processed(lp); lp = node_next(lp)
- while lp.id~=id_math do
- set_attr_icflag_processed(lp); lp = node_next(lp)
- end
- set_attr_icflag_processed(lp);
+ set_attr(lp, attr_icflag, PROCESSED) -- set_attr_icflag_processed(lp);
+ lp = node.end_of_math(lp)
+ set_attr(lp, attr_icflag, PROCESSED) -- set_attr_icflag_processed(lp);
Np.last, Np.id = lp, id_math;
return true, node_next(lp);
end,
discglue = function(lp)
Np.first, Np.nuc, Np.last = (Np.first or lp), lp, lp;
- Np.id = lp.id; set_attr_icflag_processed(lp); return true, node_next(lp)
+ Np.id = lp.id; set_attr(lp, attr_icflag, PROCESSED) -- set_attr_icflag_processed(lp);
+ return true, node_next(lp)
end,
[id_kern] = function(lp)
Np.first = Np.first or lp
if lp.subtype==2 then
- set_attr_icflag_processed(lp); lp = node_next(lp)
- set_attr_icflag_processed(lp); lp = node_next(lp)
- set_attr_icflag_processed(lp); lp = node_next(lp)
- set_attr_icflag_processed(lp); Np.nuc = lp
+ set_attr(lp, attr_icflag, PROCESSED); lp = node_next(lp)
+ set_attr(lp, attr_icflag, PROCESSED); lp = node_next(lp)
+ set_attr(lp, attr_icflag, PROCESSED); lp = node_next(lp)
+ set_attr(lp, attr_icflag, PROCESSED); Np.nuc = lp
Np.id = (lp.font == (has_attr(lp, attr_curjfnt) or -1)) and id_jglyph or id_glyph
return true, check_next_ickern(node_next(lp));
else
- Np.id = id_kern; set_attr_icflag_processed(lp);
+ Np.id = id_kern; set_attr(lp, attr_icflag, PROCESSED); -- set_attr_icflag_processed(lp);
Np.last = lp; return true, node_next(lp)
end
end,
[id_penalty] = function(lp)
- Bp[#Bp+1] = lp; set_attr_icflag_processed(lp);
+ Bp[#Bp+1] = lp; set_attr(lp, attr_icflag, PROCESSED); -- set_attr_icflag_processed(lp);
return false, node_next(lp)
end,
}
function calc_np(lp, last)
local k
-- We assume lp = node_next(Np.last)
- Np, Nq, ihb_flag = Nq, Np, false
+ Np, Nq, ihb_flag = Nq, Np, nil
-- We clear `predefined' entries of Np before pairs() loop,
-- because using only pairs() loop is slower.
Np.post, Np.pre, Np.xspc = nil, nil, nil
for k = 1,#Bp do Bp[k] = nil end
while lp ~= last do
local lpa = has_attr(lp, attr_icflag) or 0
- -- unbox 由来ノードの検出
+ -- unbox 由来ノードの検出
if lpa>=PACKED then
- if lpa == BOXBDD then
+ if lpa%PROCESSED_BEGIN_FLAG == BOXBDD then
local lq = node_next(lp)
head = node.remove(head, lp); node.free(lp); lp = lq
else return calc_np_pbox(lp, last)
-- "Np is an alphabetic character" if Np.pre~=nil,
-- "Np is not a character" otherwise.
do
+ local PRE = luatexja.stack_table_index.PRE
+ local POST = luatexja.stack_table_index.POST
+ local KCAT = luatexja.stack_table_index.KCAT
+ local XSP = luatexja.stack_table_index.XSP
-- 和文文字のデータを取得
local attr_jchar_class = luatexbase.attributes['ltj@charclass']
local cls, c = slow_find_char_class(has_attr(x, attr_orig_char), m, x.char)
Nx.class = cls; set_attr(x, attr_jchar_class, cls)
Nx.met, Nx.char = m, c
- local t = ltjs.fast_get_penalty_table_parent(c)
- Nx.pre = t.pre or 0
- Nx.post = t.post or 0
- Nx.xspc = t.xsp or 3
- Nx.kcat = t.kcat or 0
+ Nx.pre = table_current_stack[PRE + c] or 0
+ 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)
end
local set_np_xspc_jachar = set_np_xspc_jachar
function set_np_xspc_alchar(Nx, c,x, lig)
if c~=-1 then
local xc, xs = x.components, x.subtype
- if lig == ligature_head then
+ if lig == 1 then
while xc and xs and xs%4>=2 do
x = xc; xc, xs = x.components, x.subtype
end
end
c = x.char
end
- local t = ltjs.fast_get_penalty_table_parent(c)
- Nx.pre = t.pre or 0
- Nx.post = t.post or 0
- Nx.xspc = t.xsp or 3
- Nx.char = 'jcharbdd'
+ Nx.pre = table_current_stack[PRE + c] or 0
+ Nx.post = table_current_stack[POST + c] or 0
+ Nx.xspc = table_current_stack[XSP + c] or 3
+ Nx.char = 'jcharbdd'
else
Nx.pre, Nx.post, Nx.char = 0, 0, -1
- Nx.xspc = ltjs_fast_get_penalty_table('xsp', -1) or 3
+ Nx.xspc = table_current_stack[XSP - 1] or 3
end
Nx.met = nil
Nx.auto_xspc = (has_attr(x, attr_autoxspc)==1)
function after_hlist(Nx)
local s = Nx.last_char
if s then
- if s.id==glyph_node then
+ if s.id==id_glyph then
if s.font == (has_attr(s, attr_curjfnt) or -1) then
set_np_xspc_jachar(Nx, s)
else
-- 和文文字間の JFM glue を node 化
local function new_jfm_glue(m, bc, ac)
-- bc, ac: char classes
- local z = m.size_cache.char_type[bc]
+ local z = m.char_type[bc]
local g, d = z.glue[ac], 0
if g then
g,d = node_copy(g[1]), g[2];
end
-- Nq.last (kern w) .... (glue/kern g) Np.first
-local function real_insert(w, g)
+local function real_insert(g)
if g then
head = insert_before(head, Np.first, g)
Np.first = g
local gx = node_new(id_glue_spec);
gx.stretch_order, gx.shrink_order = 0, 0
local pm, qm = Np.met, Nq.met
- local bk = qm.size_cache.kanjiskip or {0, 0, 0}
- if (pm.size_cache==qm.size_cache) and (qm.var==pm.var) then
+ local bk = qm.kanjiskip or {0, 0, 0}
+ if (pm.char_type==qm.char_type) and (qm.var==pm.var) then
gx.width = bk[1]; gx.stretch = bk[2]; gx.shrink = bk[3]
else
- local ak = pm.size_cache.kanjiskip or {0, 0, 0}
+ local ak = pm.kanjiskip or {0, 0, 0}
gx.width = round(diffmet_rule(bk[1], ak[1]))
gx.stretch = round(diffmet_rule(bk[2], ak[2]))
gx.shrink = -round(diffmet_rule(-bk[3], -ak[3]))
if ihb_flag then return nil
else
local qm, pm = Nq.met, Np.met
- if (qm.size_cache==pm.size_cache) and (qm.var==pm.var) then
+ if (qm.char_type==pm.char_type) and (qm.var==pm.var) then
return new_jfm_glue(qm, Nq.class, Np.class)
else
local npn, nqn = Np.nuc, Nq.nuc
g = node_new(id_glue); --copy_attr(g, Nn.nuc)
local gx = node_new(id_glue_spec);
gx.stretch_order, gx.shrink_order = 0, 0
- local bk = Nn.met.size_cache.xkanjiskip or {0, 0, 0}
+ local bk = Nn.met.xkanjiskip or {0, 0, 0}
gx.width = bk[1]; gx.stretch = bk[2]; gx.shrink = bk[3]
g.spec = gx
else
if not ihb_flag then
local pm = Np.met
return new_jfm_glue(pm,
- fast_find_char_class(((Nq.id == id_math and -1) or 'jcharbdd'), pm), Np.class)
+ fast_find_char_class(((Nq.id == id_math and -1) or (type(Nq.char)=='string' and Nq.char or 'jcharbdd')), pm), Np.class)
else return nil
end
end
local qid = Nq.id
if qid==id_jglyph or ((qid==id_pbox or qid==id_pbox_w) and Nq.met) then
local g = calc_ja_ja_glue() or get_kanjiskip() -- M->K
- handle_penalty_normal(Nq.post, Np.pre, g); real_insert(0, g)
+ handle_penalty_normal(Nq.post, Np.pre, g); real_insert(g)
elseif Nq.met then -- qid==id_hlist
local g = get_OA_skip() or get_kanjiskip() -- O_A->K
- handle_penalty_normal(0, Np.pre, g); real_insert(0, g)
+ handle_penalty_normal(0, Np.pre, g); real_insert(g)
elseif Nq.pre then
- local g = get_OA_skip() or get_xkanjiskip(Np) -- O_A->X
- if qid==id_hlist then Nq.post = 0 end
- handle_penalty_normal(Nq.post, Np.pre, g); real_insert(0, g)
+ local g = get_OA_skip() or get_xkanjiskip(Np) -- O_A->X
+ handle_penalty_normal((qid==id_hlist and 0 or Nq.post), Np.pre, g); real_insert(g)
else
local g = get_OA_skip() -- O_A
if qid==id_glue then handle_penalty_normal(0, Np.pre, g)
elseif qid==id_kern then handle_penalty_suppress(0, Np.pre, g)
else handle_penalty_always(0, Np.pre, g)
end
- real_insert(0, g)
+ real_insert(g)
end
if mode and Np.kcat%2~=1 then
widow_Np.first, widow_Bp, Bp = Np.first, Bp, widow_Bp
-- jachar .. (anything)
local function handle_nq_jachar()
if Np.pre then
- if Np.id==id_hlist then Np.pre = 0 end
local g = get_OB_skip() or get_xkanjiskip(Nq) -- O_B->X
- handle_penalty_normal(Nq.post, Np.pre, g); real_insert(0, g)
+ handle_penalty_normal(Nq.post, (Np.id==id_hlist and 0 or Np.pre), g); real_insert(g)
else
local g = get_OB_skip() -- O_B
if Np.id==id_glue then handle_penalty_normal(Nq.post, 0, g)
elseif Np.id==id_kern then handle_penalty_suppress(Nq.post, 0, g)
else handle_penalty_always(Nq.post, 0, g)
end
- real_insert(0, g)
+ real_insert(g)
end
end
local qid = Nq.id
if qid==id_jglyph or ((qid==id_pbox or Nq.id == id_pbox_w) and Nq.met) then
local g = get_OB_skip() or get_kanjiskip() -- O_B->K
- handle_penalty_normal(Nq.post, 0, g); real_insert(0, g)
+ handle_penalty_normal(Nq.post, 0, g); real_insert(g)
elseif Nq.met then -- Nq.id==id_hlist
local g = get_kanjiskip() -- K
- handle_penalty_suppress(0, 0, g); real_insert(0, g)
+ handle_penalty_suppress(0, 0, g); real_insert(g)
elseif Nq.pre then
local g = get_xkanjiskip(Np) -- X
- handle_penalty_suppress(0, 0, g); real_insert(0, g)
+ handle_penalty_suppress(0, 0, g); real_insert(g)
end
end
local function handle_nq_ja_hlist()
if Np.pre then
local g = get_xkanjiskip(Nq) -- X
- handle_penalty_suppress(0, 0, g); real_insert(0, g)
+ handle_penalty_suppress(0, 0, g); real_insert(g)
end
end
+
-- Nq が前側のクラスタとなることによる修正
-local function adjust_nq()
- if Nq.id==id_glyph then after_alchar(Nq)
- elseif Nq.id==id_hlist or Nq.id==id_pbox or Nq.id==id_disc then after_hlist(Nq)
- elseif Nq.id == id_pbox_w then
- luatexbase.call_callback("luatexja.jfmglue.whatsit_after",
- false, Nq, Np)
+do
+ local adjust_nq_aux = {
+ [id_glyph] = function()
+ local x = Nq.nuc
+ return set_np_xspc_alchar(Nq, x.char,x, 2)
+ end, -- after_alchar(Nq)
+ [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,
+ }
+
+ function adjust_nq()
+ local x = adjust_nq_aux[Nq.id]
+ if x then x() end
end
end
+
-------------------- 開始・終了時の処理
-- リスト末尾の処理
+local JWP = luatexja.stack_table_index.JWP
local function handle_list_tail(mode)
adjust_nq(); Np = Nq
if mode then
Bp = widow_Bp; Np = widow_Np
if Np.first then
handle_penalty_normal(0,
- ltjs_fast_get_penalty_table('jwp', 0) or 0)
+ table_current_stack[JWP] or 0)
end
else
-- the current list is the contents of a hbox
-- initialize
-- return value: (the initial cursor lp), (last node)
local function init_var(mode)
+ -- 1073741823: max_dimen
Bp, widow_Bp, widow_Np = {}, {}, {first = nil}
-
+ table_current_stack = ltjs.table_current_stack
+
kanji_skip = node_new(id_glue)
kanji_skip.spec = skip_table_to_spec('kanjiskip')
set_attr(kanji_skip, attr_icflag, KANJI_SKIP)
- get_kanjiskip = (kanji_skip.spec.width == max_dimen)
+ get_kanjiskip = (kanji_skip.spec.width == 1073741823)
and get_kanjiskip_jfm or get_kanjiskip_normal
xkanji_skip = node_new(id_glue)
xkanji_skip.spec = skip_table_to_spec('xkanjiskip')
set_attr(xkanji_skip, attr_icflag, XKANJI_SKIP)
- get_xkanjiskip = (xkanji_skip.spec.width == max_dimen)
+ get_xkanjiskip = (xkanji_skip.spec.width == 1073741823)
and get_xkanjiskip_jfm or get_xkanjiskip_normal
Np = {
end
lp = calc_np(lp, last)
while Np do
- extract_np(); adjust_nq()
+ extract_np();
+ adjust_nq();
local pid, pm = Np.id, Np.met
-- 挿入部
if pid == id_jglyph then
return cleanup(mode, last)
end
--- \inhibitglue
-
-function create_inhibitglue_node()
- local tn = node_new(id_whatsit, sid_user)
- tn.user_id=30111; tn.type=100; tn.value=1
- node.write(tn)
-end
-
--- Node for indicating beginning of a paragraph
--- (for ltjsclasses)
-function create_beginpar_node()
- local tn = node_new(id_whatsit, sid_user)
- tn.user_id=30114; tn.type=100; tn.value=1
- node.write(tn)
-end
-
do
+ local IHB = luatexja.userid_table.IHB
+ local BPAR = luatexja.userid_table.BPAR
+
+ -- \inhibitglue
+ function create_inhibitglue_node()
+ local tn = node_new(id_whatsit, sid_user)
+ tn.user_id=IHB; tn.type=100; tn.value=1
+ node.write(tn)
+ end
-local function whatsit_callback(Np, lp, Nq)
- if Np and Np.nuc then return Np
- elseif Np and lp.user_id == 30114 then
- Np.first = lp; Np.nuc = lp; Np.last = lp
- Np.char = 'parbdd'
- Np.met = nil
- Np.pre = 0; Np.post = 0
- Np.xspc = 0
- Np.auto_xspc = false
- return Np
+ -- Node for indicating beginning of a paragraph
+ -- (for ltjsclasses)
+ function create_beginpar_node()
+ local tn = node_new(id_whatsit, sid_user)
+ tn.user_id=BPAR; tn.type=100; tn.value=1
+ node.write(tn)
end
-end
+ local function whatsit_callback(Np, lp, Nq)
+ if Np and Np.nuc then return Np
+ elseif Np and lp.user_id == BPAR then
+ Np.first = lp; Np.nuc = lp; Np.last = lp
+ Np.char = 'parbdd'
+ Np.met = nil
+ Np.pre = 0; Np.post = 0
+ Np.xspc = 0
+ Np.auto_xspc = false
+ return Np
+ end
+ end
-local function whatsit_after_callback(s, Nq, Np)
- if not s and Nq.nuc.user_id == 30114 then
- local x, y = node.prev(Nq.nuc), Nq.nuc
- Nq.first, Nq.nuc, Nq.last = x, x, x
- head = node.remove(head, y)
+ local function whatsit_after_callback(s, Nq, Np)
+ if not s and Nq.nuc.user_id == BPAR then
+ local x, y = node.prev(Nq.nuc), Nq.nuc
+ Nq.first, Nq.nuc, Nq.last = x, x, x
+ head = node.remove(head, y)
+ end
+ return s
end
- return s
-end
-luatexbase.add_to_callback("luatexja.jfmglue.whatsit_getinfo", whatsit_callback,
- "luatexja.beginpar.np_info", 1)
-luatexbase.add_to_callback("luatexja.jfmglue.whatsit_after", whatsit_after_callback,
- "luatexja.beginpar.np_info_after", 1)
+ luatexbase.add_to_callback("luatexja.jfmglue.whatsit_getinfo", whatsit_callback,
+ "luatexja.beginpar.np_info", 1)
+ luatexbase.add_to_callback("luatexja.jfmglue.whatsit_after", whatsit_after_callback,
+ "luatexja.beginpar.np_info_after", 1)
-end
\ No newline at end of file
+end