X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=src%2Fltj-jfmglue.lua;h=7c5ba8661aa040079e782d9413430f119ffcd9ee;hb=eb118f3e5ea0852407b5261817700401699528b9;hp=a9d6daee2c0f456fb58b370bd5289adcb2fea316;hpb=89845b5c5116bf7fc9ebb54bdfc373b554acf5e0;p=luatex-ja%2Fluatexja.git diff --git a/src/ltj-jfmglue.lua b/src/ltj-jfmglue.lua index a9d6dae..7c5ba86 100644 --- a/src/ltj-jfmglue.lua +++ b/src/ltj-jfmglue.lua @@ -3,7 +3,7 @@ -- luatexbase.provides_module({ name = 'luatexja.jfmglue', - date = '2014/10/03', + date = '2015/05/03', description = 'Insertion process of JFM glues and kanjiskip', }) module('luatexja.jfmglue', package.seeall) @@ -66,7 +66,7 @@ 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 lang_ja = token.create('ltj@@japanese')[2] +local lang_ja = luatexja.lang_ja local sid_start_link = node.subtype('pdf_start_link') local sid_start_thread = node.subtype('pdf_start_thread') @@ -81,6 +81,8 @@ local PROCESSED = luatexja.icflag_table.PROCESSED local IC_PROCESSED = luatexja.icflag_table.IC_PROCESSED local BOXBDD = luatexja.icflag_table.BOXBDD local PROCESSED_BEGIN_FLAG = luatexja.icflag_table.PROCESSED_BEGIN_FLAG + +local attr_icflag = luatexbase.attributes['ltj@icflag'] local kanji_skip local xkanji_skip local table_current_stack @@ -89,9 +91,9 @@ local capsule_glyph local tex_dir local attr_ablshift local set_np_xspc_jachar +local set_np_xspc_jachar_hbox -local attr_dir = luatexbase.attributes['ltj@dir'] -local attr_icflag = luatexbase.attributes['ltj@icflag'] +local ltjs_orig_char_table = ltjs.orig_char_table local function get_attr_icflag(p) return (has_attr(p, attr_icflag) or 0)%PROCESSED_BEGIN_FLAG @@ -111,10 +113,10 @@ do local stop_time_measure = ltjb.stop_time_measure slow_find_char_class = function (c, m, oc) local cls = ltjf_find_char_class(oc, m) - if oc~=c and cls==0 then - return ltjf_find_char_class(-c, m), oc + if oc~=c and c and cls==0 then + return ltjf_find_char_class(c, m) else - return cls, oc + return cls end end end @@ -169,8 +171,8 @@ local head -- the head of current list local Np, Nq, Bp local widow_Bp, widow_Np -- \jcharwidowpenalty 挿入位置管理用 -local ihb_flag -- JFM グルー挿入抑止用 flag - -- on: \inhibitglue 指定時,hlist の周囲 +local non_ihb_flag -- JFM グルー挿入抑止用 flag +-- false: \inhibitglue 指定時 true: それ以外 -------------------- hlist 内の文字の検索 @@ -220,6 +222,7 @@ local function check_box(box_ptr, box_end) last_char = s; found_visible_node = true else if getfield(p, 'shift')==0 then + last_char = nil if check_box(getlist(p), nil) then found_visible_node = true end else find_first_char = false; last_char = nil @@ -250,7 +253,7 @@ function check_box_high(Nx, box_ptr, box_end) if first_char then if getid(first_char)==id_glyph then if getfield(first_char, 'lang') == lang_ja then - set_np_xspc_jachar(Nx, first_char) + set_np_xspc_jachar_hbox(Nx, first_char) else set_np_xspc_alchar(Nx, getchar(first_char),first_char, 1) end @@ -275,15 +278,10 @@ luatexbase.create_callback("luatexja.jfmglue.whatsit_after", "data", function (stat, Nq, Np) return false end) -- calc next Np +local calc_np do local traverse = Dnode.traverse -local function set_attr_icflag_processed(p) - if get_attr_icflag(p)<= ITALIC then - set_attr(p, attr_icflag, PROCESSED) - end -end - local function check_next_ickern(lp) if lp and getid(lp) == id_kern and ITALIC == get_attr_icflag(lp) then set_attr(lp, attr_icflag, IC_PROCESSED) @@ -298,9 +296,13 @@ local function calc_np_pbox(lp, last) Np.first = Np.first or lp; Np.id = id_pbox set_attr(lp, attr_icflag, get_attr_icflag(lp)); while lp ~=last and (lpa>=PACKED) and (lpa=2) and (Np.xspc%2==1) and (Nq.auto_xspc or Np.auto_xspc) then - return node_copy(xkanji_skip) - else - local g = node_copy(zero_glue) - set_attr(g, attr_icflag, XKANJI_SKIP) - return g + + get_xkanjiskip_low = function(flag, qm, bn, bp, bh) + if flag or (qm.with_kanjiskip and (bn or bp or bh)) then + if xkanjiskip_jfm_flag then + local g = node_new(id_glue); + local gx = node_new(id_glue_spec); + setfield(gx, 'stretch_order', 0); setfield(gx, 'shrink_order', 0) + local bk = qm.xkanjiskip or null_skip_table + setfield(gx, 'width', bn and bk[1] or 0) + setfield(gx, 'stretch', bp and bk[2] or 0) + setfield(gx, 'shrink', bh and bk[3] or 0) + setfield(g, 'spec', gx) + set_attr(g, attr_icflag, XKANJI_SKIP_JFM) + return g + elseif flag then + return node_copy(xkanji_skip) + else + local g = node_new(id_glue); + local gx = node_new(id_glue_spec); + setfield(gx, 'stretch_order', 0); setfield(gx, 'shrink_order', 0) + local ks = getfield(xkanji_skip, 'spec') + setfield(gx, 'width', bn and getfield(ks, 'width') or 0) + setfield(gx, 'stretch', bp and getfield(ks, 'stretch') or 0) + setfield(gx, 'shrink', bh and getfield(ks, 'shrink') or 0) + setfield(g, 'spec', gx) + set_attr(g, attr_icflag, XKANJI_SKIP_JFM) + return g + end end end - get_xkanjiskip_jfm = function (Nn) - local g + + get_xkanjiskip = function(Nn) if (Nq.xspc>=2) and (Np.xspc%2==1) and (Nq.auto_xspc or Np.auto_xspc) then - g = node_new(id_glue) - local gx = node_new(id_glue_spec); - setfield(gx, 'stretch_order', 0); setfield(gx, 'shrink_order', 0) - local bk = Nn.met.xkanjiskip or {0, 0, 0} - setfield(gx, 'width', bk[1]) - setfield(gx, 'stretch', bk[2]) - setfield(gx, 'shrink', bk[3]) - setfield(g, 'spec', gx) + return get_xkanjiskip_low(true, Nn.met, 1, 1, 1) else - g = node_copy(zero_glue) + local g = node_copy(zero_glue) + set_attr(g, attr_icflag, xkanjiskip_jfm_flag and XKANJI_SKIP_JFM or XKANJI_SKIP) + return g end - set_attr(g, attr_icflag, XKANJI_SKIP_JFM) - return g end end -------------------- 隣接した「塊」間の処理 -local function get_OA_skip() - 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 (type(Nq.char)=='string' and Nq.char or 'jcharbdd')), pm), Np.class) - else return nil +local function get_OA_skip(is_kanji) + 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 'jcharbdd'), pm), + Np.class) + local k + if is_kanji==0 then + k = (Np.auto_kspc or Nq.auto_kspc) and get_kanjiskip_low(false, pm, kn, kp, kh) + elseif is_kanji==1 then + k = ((Nq.xspc>=2) and (Np.xspc%2==1) and (Nq.auto_xspc or Np.auto_xspc)) + and get_xkanjiskip_low(false, pm, kn, kp, kh) end + return g, k end -local function get_OB_skip() - if not ihb_flag then - local qm = Nq.met - return new_jfm_glue(qm, Nq.class, - fast_find_char_class(((Np.id == id_math and -1) or'jcharbdd'), qm)) - else return nil +local function get_OB_skip(is_kanji) + 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'jcharbdd'), qm)) + local k + if is_kanji==0 then + k = (Np.auto_kspc or Nq.auto_kspc) and get_kanjiskip_low(false, qm, kn, kp, kh) + elseif is_kanji==1 then + k = ((Nq.xspc>=2) and (Np.xspc%2==1) and (Nq.auto_xspc or Np.auto_xspc)) + and get_xkanjiskip_low(false, qm, kn, kp, kh) end + return g, k end -- (anything) .. jachar local function handle_np_jachar(mode) 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(g) + local g, k + if non_ihb_flag then g, k = calc_ja_ja_glue() end -- M->K + if not g then g = get_kanjiskip() end + handle_penalty_normal(Nq.post, Np.pre, g); + real_insert(g); real_insert(k) 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(g) + local g, k + if non_ihb_flag then g, k = get_OA_skip(0) end -- O_A->K + 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 = 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) + local g, k + if non_ihb_flag then g, k = get_OA_skip(1) end -- O_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) else - local g = get_OA_skip() -- O_A + local g = non_ihb_flag and (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) @@ -927,10 +984,10 @@ end -- jachar .. (anything) local function handle_nq_jachar() if Np.pre then - local g = get_OB_skip() or get_xkanjiskip(Nq) -- O_B->X + local g = non_ihb_flag and get_OB_skip(1) or get_xkanjiskip(Nq) -- O_B->X 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 + local g =non_ihb_flag and (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) @@ -943,7 +1000,7 @@ end local function handle_np_ja_hlist() 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 + local g = non_ihb_flag and get_OB_skip(0) or get_kanjiskip() -- O_B->K handle_penalty_normal(Nq.post, 0, g); real_insert(g) elseif Nq.met then -- Nq.id==id_hlist local g = get_kanjiskip() -- K @@ -995,14 +1052,13 @@ local function handle_list_tail(mode) -- Insert \jcharwidowpenalty Bp = widow_Bp; Np = widow_Np if Np.first then - handle_penalty_normal(0, - table_current_stack[JWP] or 0) + handle_penalty_normal(0, table_current_stack[JWP] or 0) end else -- the current list is the contents of a hbox local npi, pm = Np.id, Np.met if npi == id_jglyph or (npi==id_pbox and pm) then - local g = new_jfm_glue(pm, Np.class, fast_find_char_class('boxbdd', pm)) + local g = new_jfm_glue(pm.char_type, Np.class, fast_find_char_class('boxbdd', pm)) if g then set_attr(g, attr_icflag, BOXBDD) head = insert_after(head, Np.last, g) @@ -1015,8 +1071,8 @@ end local function handle_list_head(par_indented) local npi, pm = Np.id, Np.met if npi == id_jglyph or (npi==id_pbox and pm) then - if not ihb_flag then - local g = new_jfm_glue(pm, fast_find_char_class(par_indented, pm), Np.class) + if non_ihb_flag then + local g = new_jfm_glue(pm.char_type, fast_find_char_class(par_indented, pm), Np.class) if g then set_attr(g, attr_icflag, BOXBDD) if getid(g)==id_glue and #Bp==0 then @@ -1041,41 +1097,44 @@ do local dir_tate = luatexja.dir_table.dir_tate local attr_yablshift = luatexbase.attributes['ltj@yablshift'] local attr_tablshift = luatexbase.attributes['ltj@tablshift'] + local table_pool = { + {}, {}, {first=nil}, + { auto_kspc=nil, auto_xspc=nil, char=nil, class=nil, + first=nil, id=nil, last=nil, met=nil, nuc=nil, + post=nil, pre=nil, xspc=nil, }, + { auto_kspc=nil, auto_xspc=nil, char=nil, class=nil, + first=nil, id=nil, last=nil, met=nil, nuc=nil, + post=nil, pre=nil, xspc=nil, }, + } init_var = function (mode,dir) -- 1073741823: max_dimen - Bp, widow_Bp, widow_Np = {}, {}, {first = nil} + Bp, widow_Bp, widow_Np, Np, Nq + = table_pool[1], table_pool[2], table_pool[3], table_pool[4], table_pool[5] + for i=1,5 do for j,_ in pairs(table_pool[i]) do table_pool[i][j]=nil end end table_current_stack = ltjs.table_current_stack - list_dir = ltjs.list_dir or dir_yoko + list_dir, tex_dir = (ltjs.list_dir or dir_yoko), (dir or 'TLT') local is_dir_tate = list_dir==dir_tate capsule_glyph = is_dir_tate and ltjw.capsule_glyph_tate or ltjw.capsule_glyph_yoko attr_ablshift = is_dir_tate and attr_tablshift or attr_yablshift - set_np_xspc_jachar = is_dir_tate and set_np_xspc_jachar_tate or set_np_xspc_jachar_yoko - - - tex_dir = dir or 'TLT' - kanji_skip = node_new(id_glue) - setfield(kanji_skip, 'spec', skip_table_to_spec(KSK)) - set_attr(kanji_skip, attr_icflag, KANJI_SKIP) - get_kanjiskip = (getfield(getfield(kanji_skip, 'spec'), 'width') == 1073741823) - and get_kanjiskip_jfm or get_kanjiskip_normal - - xkanji_skip = node_new(id_glue) - setfield(xkanji_skip, 'spec', skip_table_to_spec(XSK)) - set_attr(xkanji_skip, attr_icflag, XKANJI_SKIP) - get_xkanjiskip = (getfield(getfield(xkanji_skip, 'spec'), 'width') == 1073741823) - and get_xkanjiskip_jfm or get_xkanjiskip_normal - - Np = { - auto_kspc=nil, auto_xspc=nil, char=nil, class=nil, - first=nil, id=nil, last=nil, met=nil, nuc=nil, - post=nil, pre=nil, xspc=nil, - } - Nq = { - auto_kspc=nil, auto_xspc=nil, char=nil, class=nil, - first=nil, id=nil, last=nil, met=nil, nuc=nil, - post=nil, pre=nil, xspc=nil, - } + 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. + + do + kanji_skip = node_new(id_glue); set_attr(kanji_skip, attr_icflag, KANJI_SKIP) + local s = skip_table_to_spec(KSK) + setfield(kanji_skip, 'spec', s) + kanjiskip_jfm_flag = (getfield(s, 'width') == 1073741823) + end + + do + xkanji_skip = node_new(id_glue); set_attr(xkanji_skip, attr_icflag, XKANJI_SKIP) + local s = skip_table_to_spec(XSK) + setfield(xkanji_skip, 'spec', s) + xkanjiskip_jfm_flag = (getfield(s, 'width') == 1073741823) + end + if mode then -- the current list is to be line-breaked: -- hbox from \parindent is skipped. @@ -1087,18 +1146,20 @@ do Np.width = getfield(lp, 'width') end lp=node_next(lp); lpi, lps = getid(lp), getsubtype(lp) end - return lp, node_tail(head), par_indented + return lp, node_tail(head), par_indented, TEMP else - return head, nil, 'boxbdd' + return head, nil, 'boxbdd', TEMP end end end -local tex_set_attr = tex.setattribute -local function cleanup(mode) +local ensure_tex_attr = ltjb.ensure_tex_attr +local function cleanup(mode, TEMP) -- adjust attr_icflag for avoiding error - tex_set_attr('global', attr_icflag, 0) - node_free(kanji_skip); node_free(xkanji_skip) + if tex.getattribute(attr_icflag)~=0 then ensure_tex_attr(attr_icflag, 0) end + node_free(kanji_skip); + node_free(xkanji_skip); node_free(TEMP) + if mode then local h = node_next(head) if getid(h) == id_penalty and getfield(h, 'penalty') == 10000 then @@ -1116,31 +1177,28 @@ end function main(ahead, mode, dir) if not ahead then return ahead end head = ahead; - local lp, last, par_indented = init_var(mode,dir) - lp = calc_np(lp, last) + local lp, last, par_indented, TEMP = init_var(mode,dir) + lp = calc_np(last, lp) if Np then handle_list_head(par_indented) - else - return cleanup(mode) - end - lp = calc_np(lp, last) - while Np do - adjust_nq(); - local pid, pm = Np.id, Np.met - -- 挿入部 - if pid == id_jglyph then - handle_np_jachar(mode) - elseif pm then - if pid==id_hlist then handle_np_ja_hlist() - else handle_np_jachar() end - elseif Nq.met then - if Nq.id==id_hlist then handle_nq_ja_hlist() - else handle_nq_jachar() end + lp = calc_np(last,lp); while Np do + adjust_nq(); + local pid, pm = Np.id, Np.met + -- 挿入部 + if pid == id_jglyph then + handle_np_jachar(mode) + elseif pm then + if pid==id_hlist then handle_np_ja_hlist() + else handle_np_jachar() end + elseif Nq.met then + if Nq.id==id_hlist then handle_nq_ja_hlist() + else handle_nq_jachar() end + end + lp = calc_np(last,lp) end - lp = calc_np(lp, last) + handle_list_tail(mode) end - handle_list_tail(mode) - return cleanup(mode) + return cleanup(mode, TEMP) end end @@ -1173,11 +1231,6 @@ do if Np and Np.nuc then return Np elseif Np and getfield(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 @@ -1186,6 +1239,13 @@ do 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 + if Np then + if Np.met then + Nq.class = fast_find_char_class('parbdd', Np.met) + end + Nq.met = Np.met; Nq.pre = 0; Nq.post = 0; Nq.xspc = 0 + Nq.auto_xspc = false + end head = node_remove(head, y) node_free(y) end