X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=src%2Fltj-jfmglue.lua;h=531a5c75433fb9a9871e0cd4176c3d6f67073923;hb=a02274810ecc6253ecbb37dd4ccb322416fa98f9;hp=11f648bf7ab355cd193a7a340a181b25c3994bd0;hpb=cd47cbb8581fedb03c2f9b7cb1607b68c858a2a0;p=luatex-ja%2Fluatexja.git diff --git a/src/ltj-jfmglue.lua b/src/ltj-jfmglue.lua index 11f648b..531a5c7 100644 --- a/src/ltj-jfmglue.lua +++ b/src/ltj-jfmglue.lua @@ -3,7 +3,7 @@ -- luatexbase.provides_module({ name = 'luatexja.jfmglue', - date = '2015/05/03', + date = '2017/05/05', description = 'Insertion process of JFM glues and kanjiskip', }) module('luatexja.jfmglue', package.seeall) @@ -16,35 +16,40 @@ luatexja.load_module('direction'); local ltjd = luatexja.direction luatexja.load_module('setwidth'); local ltjw = luatexja.setwidth local pairs = pairs -local Dnode = node.direct or node - local nullfunc = function(n) return n end -local to_node = (Dnode ~= node) and Dnode.tonode or nullfunc -local to_direct = (Dnode ~= node) and Dnode.todirect or nullfunc - -local setfield = (Dnode ~= node) and Dnode.setfield or function(n, i, c) n[i] = c end -local getfield = (Dnode ~= node) and Dnode.getfield or function(n, i) return n[i] end -local getid = (Dnode ~= node) and Dnode.getid or function(n) return n.id end -local getfont = (Dnode ~= node) and Dnode.getfont or function(n) return n.font end -local getlist = (Dnode ~= node) and Dnode.getlist or function(n) return n.head end -local getchar = (Dnode ~= node) and Dnode.getchar or function(n) return n.char end -local getsubtype = (Dnode ~= node) and Dnode.getsubtype or function(n) return n.subtype end - -local has_attr = Dnode.has_attribute -local set_attr = Dnode.set_attribute -local insert_before = Dnode.insert_before -local insert_after = Dnode.insert_after -local node_next = (Dnode ~= node) and Dnode.getnext or node.next -local round = tex.round +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 getsubtype = node.direct.getsubtype +local if_lang_ja +do + local lang_ja = luatexja.lang_ja + local getlang = node.direct.getlang + if_lang_ja = getlang + and function (n) return getlang(n)==lang_ja end + or function (n) return getfield(n,'lang')==lang_ja end +end + +local has_attr = node.direct.has_attribute +local set_attr = node.direct.set_attribute +local insert_before = node.direct.insert_before +local insert_after = node.direct.insert_after +local node_next = node.direct.getnext 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 = Dnode.new -local node_copy = Dnode.copy -local node_remove = Dnode.remove -local node_tail = Dnode.tail -local node_free = Dnode.free -local node_end_of_math = Dnode.end_of_math +local node_new = node.direct.new +local node_copy = node.direct.copy +local node_tail = node.direct.tail +local node_free = node.direct.free +local node_remove = node.direct.remove local id_glyph = node.id('glyph') local id_hlist = node.id('hlist') @@ -60,18 +65,11 @@ local id_glue = node.id('glue') local id_kern = node.id('kern') local id_penalty = node.id('penalty') -local id_glue_spec = node.id('glue_spec') 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 lang_ja = luatexja.lang_ja - -local sid_start_link = node.subtype('pdf_start_link') -local sid_start_thread = node.subtype('pdf_start_thread') -local sid_end_link = node.subtype('pdf_end_link') -local sid_end_thread = node.subtype('pdf_end_thread') local ITALIC = luatexja.icflag_table.ITALIC local PACKED = luatexja.icflag_table.PACKED @@ -121,25 +119,10 @@ do end end -local zero_glue = node_new(id_glue) -spec_zero_glue = to_node(node_new(id_glue_spec)) - -- must be public, since mentioned from other sources -local spec_zero_glue = to_direct(spec_zero_glue) -setfield(spec_zero_glue, 'width', 0) -setfield(spec_zero_glue, 'stretch', 0) -setfield(spec_zero_glue, 'shrink', 0) -setfield(spec_zero_glue, 'stretch_order', 0) -setfield(spec_zero_glue, 'shrink_order', 0) -setfield(zero_glue, 'spec', spec_zero_glue) - -local function skip_table_to_spec(n) - local g, st = node_new(id_glue_spec), ltjs.fast_get_stack_skip(n) - setfield(g, 'width', st.width) - setfield(g, 'stretch', st.stretch) - setfield(g, 'shrink', st.shrink) - setfield(g, 'stretch_order', st.stretch_order) - setfield(g, 'shrink_order', st.shrink_order) - return g +local function skip_table_to_glue(n) + local g, st = node_new(id_glue), ltjs.fast_get_stack_skip(n) + setglue(g, st.width, st.stretch, st.shrink, st.stretch_order, st.shrink_order) + return g, (st.width==1073741823) end @@ -224,6 +207,7 @@ local function check_box(box_ptr, box_end) if getfield(p, 'shift')==0 then last_char = nil if check_box(getlist(p), nil) then found_visible_node = true end + find_first_char = false else find_first_char = false; last_char = nil end @@ -252,7 +236,7 @@ function check_box_high(Nx, box_ptr, box_end) local first_char = first_char if first_char then if getid(first_char)==id_glyph then - if getfield(first_char, 'lang') == lang_ja then + if if_lang_ja(first_char) then set_np_xspc_jachar_hbox(Nx, first_char) else set_np_xspc_alchar(Nx, getchar(first_char),first_char, 1) @@ -281,10 +265,10 @@ luatexbase.create_callback("luatexja.jfmglue.whatsit_after", "data", local calc_np do -local traverse = Dnode.traverse +local traverse = node.direct.traverse 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) + if lp and getid(lp) == id_kern and ( getsubtype(lp)==3 or ITALIC == get_attr_icflag(lp)) then + set_attr(lp, attr_icflag, IC_PROCESSED); Np.last = lp; return node_next(lp) else Np.last = Np.nuc; return lp @@ -296,9 +280,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 (lpanode_depth then - r = node_new(id_rule) + r = node_new(id_rule,3) setfield(r, 'width', 0); setfield(r, 'height', 0) setfield(r, 'depth',adj_depth); setfield(r, 'dir', tex_dir) set_attr(r, attr_icflag, PROCESSED) @@ -388,7 +380,7 @@ local function calc_np_aux_glyph_common(lp) node_free(r) elseif (ct.left_protruding or 0) == 0 then head = insert_before(head, npn, r) - Np.first = (Np.first==npn) and r or npn + Np.first = acc_flag and Np.first or ((Np.first==npn) and r or npn) elseif (ct.right_protruding or 0) == 0 then insert_after(head, npn, r); Np.last, lp = r, r else @@ -404,7 +396,15 @@ local function calc_np_aux_glyph_common(lp) return true, lp end end -local calc_np_auxtable = { +local calc_np_auxtable +do +local node_end_of_math = node.direct.end_of_math +local dir_tate = luatexja.dir_table.dir_tate +local sid_start_link = node.subtype('pdf_start_link') +local sid_start_thread = node.subtype('pdf_start_thread') +local sid_end_link = node.subtype('pdf_end_link') +local sid_end_thread = node.subtype('pdf_end_thread') +calc_np_auxtable = { [id_glyph] = calc_np_aux_glyph_common, [id_hlist] = function(lp) local op, flag @@ -431,10 +431,6 @@ local calc_np_auxtable = { Np.id = id_box_like; return true, node_next(lp) end, - skip = function(lp) - set_attr(lp, attr_icflag, PROCESSED) - return false, node_next(lp) - end, [id_whatsit] = function(lp) local lps = getsubtype(lp) if lps==sid_user then @@ -490,10 +486,15 @@ local calc_np_auxtable = { if getsubtype(lp)==2 then Np.first = Np.first or lp set_attr(lp, attr_icflag, PROCESSED); lp = node_next(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)) + end 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); - return calc_np_aux_glyph_common(lp) + return calc_np_aux_glyph_common(lp, true) else Np.first = Np.first or lp Np.id = id_kern; set_attr(lp, attr_icflag, PROCESSED) @@ -505,11 +506,14 @@ local calc_np_auxtable = { return false, node_next(lp) end, } +end calc_np_auxtable[id_rule] = calc_np_auxtable.box_like -calc_np_auxtable[13] = calc_np_auxtable.box_like -calc_np_auxtable[id_ins] = calc_np_auxtable.skip -calc_np_auxtable[id_mark] = calc_np_auxtable.skip -calc_np_auxtable[id_adjust] = calc_np_auxtable.skip +calc_np_auxtable[15] = calc_np_auxtable.box_like + +local function calc_np_aux_skip (lp) + set_attr(lp, attr_icflag, PROCESSED) + return false, node_next(lp) +end function calc_np(last, lp) local k @@ -525,7 +529,7 @@ function calc_np(last, lp) 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%PROCESSED_BEGIN_FLAG == BOXBDD then local lq = node_next(lp) @@ -534,7 +538,7 @@ function calc_np(last, lp) return calc_np_pbox(lp, last) end -- id_pbox else - k, lp = calc_np_auxtable[getid(lp)](lp) + k, lp = (calc_np_auxtable[getid(lp)] or calc_np_aux_skip)(lp) if k then return lp end end end @@ -601,12 +605,11 @@ do c = getchar(x) 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 else Nx.pre, Nx.post = 0, 0 - Nx.xspc = table_current_stack[XSP - 1] or 3 end Nx.met = nil + Nx.xspc = table_current_stack[XSP + c] or 3 Nx.auto_xspc = (has_attr(x, attr_autoxspc)==1) end local set_np_xspc_alchar = set_np_xspc_alchar @@ -617,7 +620,7 @@ do local s = Nx.last_char if s then if getid(s)==id_glyph then - if getfield(s, 'lang') == lang_ja then + if if_lang_ja(s) then set_np_xspc_jachar_hbox(Nx, s) else set_np_xspc_alchar(Nx, getchar(s), s, 2) @@ -639,8 +642,11 @@ end -------------------- 最下層の処理 +luatexbase.create_callback('luatexja.adjust_jfmglue', 'simple', nullfunc) + -- change penalties (or create a new penalty, if needed) local function handle_penalty_normal(post, pre, g) + luatexbase.call_callback('luatexja.adjust_jfmglue', head, Nq, Np, Bp) local a = (pre or 0) + (post or 0) if #Bp == 0 then if (a~=0 and not(g and getid(g)==id_kern)) then @@ -656,6 +662,7 @@ local function handle_penalty_normal(post, pre, g) end local function handle_penalty_always(post, pre, g) + luatexbase.call_callback('luatexja.adjust_jfmglue', head, Nq, Np, Bp) local a = (pre or 0) + (post or 0) if #Bp == 0 then if not (g and getid(g)==id_glue) or a~=0 then @@ -671,7 +678,7 @@ local function handle_penalty_always(post, pre, g) end local function handle_penalty_suppress(post, pre, g) - local a = (pre or 0) + (post or 0) + 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) @@ -679,7 +686,24 @@ local function handle_penalty_suppress(post, pre, g) Bp[1]=p set_attr(p, attr_icflag, KINSOKU) end - else for _, v in pairs(Bp) do add_penalty(v,a) end + else + local a = (pre or 0) + (post or 0) + for _, v in pairs(Bp) do add_penalty(v,a) end + end +end + +local function handle_penalty_jwp() + 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) + 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) + widow_Bp[1]=p; + set_attr(p, attr_icflag, KINSOKU) + end + else for _, v in pairs(widow_Bp) do add_penalty(v,a) end end end @@ -688,13 +712,13 @@ local function new_jfm_glue(mc, bc, ac) -- bc, ac: char classes local g = mc[bc][ac] if g then - if g[1] then + if g[1] then + return node_copy(g[1]), g.ratio, false, false, false + else local f = node_new(id_glue) set_attr(f, attr_icflag, g.priority) - setfield(f, 'spec', node_copy(g[2])) + setglue(f, g.width, g.stretch, g.shrink) return f, g.ratio, g.kanjiskip_natural, g.kanjiskip_stretch, g.kanjiskip_shrink - else - return node_copy(g[2]), g.ratio, false, false, false end end return false, 0 @@ -712,6 +736,7 @@ end -------------------- 和文文字間空白量の決定 local calc_ja_ja_aux do + local round = tex.round local bg_ag = 2*id_glue - id_glue local bg_ak = 2*id_glue - id_kern local bk_ag = 2*id_kern - id_glue @@ -727,22 +752,21 @@ do end if not gb then if ga then - gb = node_new(id_kern); setfield(gb, 'kern', 0) + gb = node_new(id_kern, 1); setfield(gb, 'kern', 0) else return nil end elseif not ga then - ga = node_new(id_kern); setfield(ga, 'kern', 0) + ga = node_new(id_kern, 1); setfield(ga, 'kern', 0) end local k = 2*getid(gb) - getid(ga) if k == bg_ag then - local bs, as = getfield(gb, 'spec'), getfield(ga, 'spec') -- 両方とも glue. - setfield(bs, 'width', blend_diffmet( - getfield(bs, 'width'), getfield(as, 'width'), db, da)) - setfield(bs, 'stretch', blend_diffmet( - getfield(bs, 'stretch'), getfield(as, 'stretch'), db, da)) - setfield(bs, 'shrink', -blend_diffmet( - -getfield(bs, 'shrink'), -getfield(as, 'shrink'), db, da)) + 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 @@ -752,25 +776,23 @@ do node_free(ga) return gb elseif k == bk_ag then - local as = getfield(ga, 'spec') -- gb: kern, ga: glue - setfield(as, 'width', blend_diffmet( - getfield(gb, 'kern'), getfield(as, 'width'), db, da)) - setfield(as, 'stretch', blend_diffmet( - 0, getfield(as, 'stretch'), db, da)) - setfield(as, 'shrink', -blend_diffmet( - 0, -getfield(as, 'shrink'), db, da)) + 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 else - local bs = getfield(gb, 'spec') -- gb: glue, ga: kern - setfield(bs, 'width', blend_diffmet( - getfield(bs, 'width'), getfield(ga, 'kern'), db, da)) - setfield(bs, 'stretch', blend_diffmet( - getfield(bs, 'stretch'), 0, db, da)) - setfield(bs, 'shrink', -blend_diffmet( - -getfield(bs, 'shrink'), 0, db, da)) + 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 end @@ -789,26 +811,21 @@ do if flag or (qm.with_kanjiskip and (bn or bp or bh)) then if kanjiskip_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.kanjiskip or null_skip_table - setfield(gx, 'width', bn and (bn*bk[1]) or 0) - setfield(gx, 'stretch', bp and (bp*bk[2]) or 0) - setfield(gx, 'shrink', bh and (bh*bk[3]) or 0) - setfield(g, 'spec', gx) + setglue(g, bn and (bn*bk[1]) or 0, + bp and (bp*bk[2]) or 0, + bh and (bh*bk[3]) or 0, 0, 0) 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 gx = node_new(id_glue_spec); - setfield(gx, 'stretch_order', 0); setfield(gx, 'shrink_order', 0) - local ks = getfield(kanji_skip, 'spec') - setfield(gx, 'width', bn and (bn*getfield(ks, 'width')) or 0) - setfield(gx, 'stretch', bp and (bp*getfield(ks, 'stretch')) or 0) - setfield(gx, 'shrink', bh and (bh*getfield(ks, 'shrink')) or 0) - setfield(g, 'spec', gx) + 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) set_attr(g, attr_icflag, KANJI_SKIP_JFM) return g end @@ -816,17 +833,19 @@ do end get_kanjiskip = function() - if Np.auto_kspc or Nq.auto_kspc then + if Np.auto_kspc==0 or Nq.auto_kspc==0 then + return nil + 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(true, qm, 1, 1, 1) 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) end - else - local g = node_copy(zero_glue) + else + local g = node_new(id_glue) set_attr(g, attr_icflag, kanjiskip_jfm_flag and KANJI_SKIP_JFM or KANJI_SKIP) return g end @@ -874,26 +893,21 @@ do 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) + setglue(g, bn and bk[1] or 0, + bp and bk[2] or 0, + bh and bk[3] or 0, 0, 0) 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) + 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, + 0, 0) set_attr(g, attr_icflag, XKANJI_SKIP_JFM) return g end @@ -901,10 +915,12 @@ do end get_xkanjiskip = function(Nn) - if (Nq.xspc>=2) and (Np.xspc%2==1) and (Nq.auto_xspc or Np.auto_xspc) then + if Np.auto_xspc==0 or Nq.auto_xspc==0 then + return nil + elseif (Nq.xspc>=2) and (Np.xspc%2==1) and (Nq.auto_xspc or Np.auto_xspc) then return get_xkanjiskip_low(true, Nn.met, 1, 1, 1) else - local g = node_copy(zero_glue) + local g = node_new(id_glue) set_attr(g, attr_icflag, xkanjiskip_jfm_flag and XKANJI_SKIP_JFM or XKANJI_SKIP) return g end @@ -913,18 +929,44 @@ end -------------------- 隣接した「塊」間の処理 +local function combine_spc(name) + return (Np[name] or Nq[name]) and ((Np[name]~=0) and (Nq[name]~=0)) +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) + 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) + return g, k +end + 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), + fast_find_char_class( + (((Nq.id==id_glue)or(Nq.id==id_kern)) and 'glue' 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) + k = combine_spc('auto_kspc') and get_kanjiskip_low(false, pm, kn, kp, kh) end return g, k end @@ -932,13 +974,11 @@ 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)) + fast_find_char_class( + (((Np.id==id_glue)or(Np.id==id_kern)) and 'glue' 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) + k = combine_spc('auto_kspc') and get_kanjiskip_low(false, qm, kn, kp, kh) end return g, k end @@ -959,7 +999,7 @@ local function handle_np_jachar(mode) 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_OA_skip(1) end -- O_A->X + 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) @@ -980,7 +1020,7 @@ end -- jachar .. (anything) local function handle_nq_jachar() if Np.pre then - local g = non_ihb_flag and get_OB_skip(1) or get_xkanjiskip(Nq) -- O_B->X + 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) else local g =non_ihb_flag and (get_OB_skip()) -- O_B @@ -995,7 +1035,7 @@ end -- (anything) .. (和文文字で始まる hlist) 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 + if qid==id_jglyph or ((qid==id_pbox or qid == id_pbox_w) and Nq.met) then 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 @@ -1038,19 +1078,16 @@ end -------------------- 開始・終了時の処理 do - +local node_prev = node.direct.getprev -- リスト末尾の処理 -local JWP = luatexja.stack_table_index.JWP -local function handle_list_tail(mode) - adjust_nq(); Np = Nq +local function handle_list_tail(mode, last) + adjust_nq() if mode then -- the current list is to be line-breaked. -- Insert \jcharwidowpenalty - Bp = widow_Bp; Np = widow_Np - if Np.first then - handle_penalty_normal(0, table_current_stack[JWP] or 0) - end + if widow_Np.first then handle_penalty_jwp() end else + Np=Nq -- 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 @@ -1085,6 +1122,7 @@ end -- return value: (the initial cursor lp), (last node) local init_var do + local id_local = node.id('local_par') local KANJI_SKIP = luatexja.icflag_table.KANJI_SKIP local XKANJI_SKIP = luatexja.icflag_table.XKANJI_SKIP local KSK = luatexja.stack_table_index.KSK @@ -1118,25 +1156,23 @@ do -- 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) + kanji_skip, kanjiskip_jfm_flag = skip_table_to_glue(KSK) + set_attr(kanji_skip, attr_icflag, KANJI_SKIP) 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) + 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. local lp, par_indented, lpi, lps = head, 'boxbdd', getid(head), getsubtype(head) - while lp and ((lpi==id_whatsit and lps~=sid_user) - or ((lpi==id_hlist) and (lps==3))) do + while lp and + ((lpi==id_whatsit and lps~=sid_user) + or ((lpi==id_hlist) and (lps==3)) + or (lpi==id_local)) do if (lpi==id_hlist) and (lps==3) then Np.char, par_indented = 'parbdd', 'parbdd' Np.width = getfield(lp, 'width') @@ -1151,6 +1187,7 @@ end local ensure_tex_attr = ltjb.ensure_tex_attr local function cleanup(mode, TEMP) + -- luatexja.ext_show_node_list(to_node(head), '> ', print) -- adjust attr_icflag for avoiding error if tex.getattribute(attr_icflag)~=0 then ensure_tex_attr(attr_icflag, 0) end node_free(kanji_skip); @@ -1172,12 +1209,15 @@ end -- main interface function main(ahead, mode, dir) if not ahead then return ahead end + --luatexja.ext_show_node_list(to_node(ahead ), '>B ', print) + --print() head = ahead; local lp, last, par_indented, TEMP = init_var(mode,dir) lp = calc_np(last, lp) if Np then handle_list_head(par_indented) - lp = calc_np(last,lp); while Np do + lp = calc_np(last,lp); + while Np do adjust_nq(); local pid, pm = Np.id, Np.met -- 挿入部 @@ -1192,8 +1232,10 @@ function main(ahead, mode, dir) end lp = calc_np(last,lp) end - handle_list_tail(mode) + handle_list_tail(mode, last) end + --luatexja.ext_show_node_list(to_node(ahead ), '>A ', print) + --print() return cleanup(mode, TEMP) end end @@ -1201,8 +1243,9 @@ end do local IHB = luatexja.userid_table.IHB local BPAR = luatexja.userid_table.BPAR - local node_prev = (Dnode ~= node) and Dnode.getprev or node.prev - local node_write = Dnode.write + local BOXB = luatexja.userid_table.BOXB + local node_prev = node.direct.getprev + local node_write = node.direct.write -- \inhibitglue function create_inhibitglue_node() @@ -1223,11 +1266,32 @@ do node_write(tn) end + -- Node for indicating a head/end of a box + function create_boxbdd_node() + local tn = node_new(id_whatsit, sid_user) + setfield(tn, 'user_id', BOXB) + setfield(tn, 'type', 100) + setfield(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 getfield(lp, 'user_id') == BPAR then Np.first = lp; Np.nuc = lp; Np.last = lp return Np + elseif Np and getfield(lp, 'user_id') == BOXB then + Np.first = lp; Np.nuc = lp; Np.last = lp + if Nq then + if Nq.met then + Np.class = fast_find_char_class('boxbdd', Nq.met) + end + Np.met = Nq.met; Np.pre = 0; Np.post = 0; Np.xspc = 0 + Np.auto_xspc, Np.auto_kspc = 0, 0 + end + return Np + else + return Np end end @@ -1240,7 +1304,19 @@ do 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 + Nq.auto_xspc, Nq.auto_kspc = 0, 0 + end + head = 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.first, Nq.nuc, Nq.last = x, x, x + if Np then + if Np.met then + Nq.class = fast_find_char_class('boxbdd', Np.met) + end + 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) node_free(y)