From baf744225e4e3043762f7d44911b695009f4f46d Mon Sep 17 00:00:00 2001 From: Hironori Kitagawa Date: Tue, 21 Jan 2014 13:11:25 +0900 Subject: [PATCH] Use direct node sccess model in ltj-math.lua and ltj-setwidth.lua. --- src/ltj-jfmglue.lua | 61 ++++++++++++++++++----------- src/ltj-math.lua | 100 ++++++++++++++++++++++++++--------------------- src/ltj-setwidth.lua | 107 +++++++++++++++++++++++++++++---------------------- 3 files changed, 157 insertions(+), 111 deletions(-) diff --git a/src/ltj-jfmglue.lua b/src/ltj-jfmglue.lua index 42195ec..46ed66d 100644 --- a/src/ltj-jfmglue.lua +++ b/src/ltj-jfmglue.lua @@ -3,7 +3,7 @@ -- luatexbase.provides_module({ name = 'luatexja.jfmglue', - date = '2014/1/12', + date = '2014/1/21', description = 'Insertion process of JFM glues and kanjiskip', }) module('luatexja.jfmglue', package.seeall) @@ -13,15 +13,31 @@ luatexja.load_module('stack'); local ltjs = luatexja.stack luatexja.load_module('jfont'); local ltjf = luatexja.jfont luatexja.load_module('pretreat'); local ltjp = luatexja.pretreat -local has_attr = node.has_attribute -local set_attr = node.set_attribute -local insert_before = node.insert_before -local node_next = node.next +local Dnode = node -- node.direct or node + +local setfield = (Dnode == node.direct) and Dnode.setfield or function(n, i, c) n[i] = c end +local getfield = (Dnode == node.direct) and Dnode.getfield or function(n, i) return n[i] end +local getid = (Dnode == node.direct) and Dnode.getid or function(n) return n.id end +local getfont = (Dnode == node.direct) and Dnode.getfont or function(n) return n.font end +local getlist = (Dnode == node.direct) and Dnode.getlist or function(n) return n.head end +local getchar = (Dnode == node.direct) and Dnode.getlist or function(n) return n.char end +local getsubtype = (Dnode == node.direct) and Dnode.getlist 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.next local round = tex.round local ltjf_font_metric_table = ltjf.font_metric_table local ltjf_find_char_class = ltjf.find_char_class -local node_new = node.new -local node_copy = node.copy +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 id_glyph = node.id('glyph') local id_hlist = node.id('hlist') @@ -304,7 +320,7 @@ local calc_np_auxtable = { if lp.subtype==sid_user 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 + head = node_remove(head, lp); node_free(lp); ihb_flag = true return false, lq; else set_attr(lp, attr_icflag, PROCESSED) @@ -333,7 +349,7 @@ local calc_np_auxtable = { [id_math] = function(lp) Np.first, Np.nuc = (Np.first or lp), lp; set_attr(lp, attr_icflag, PROCESSED) -- set_attr_icflag_processed(lp); - lp = node.end_of_math(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); @@ -390,7 +406,7 @@ function calc_np(lp, last) if lpa>=PACKED then if lpa%PROCESSED_BEGIN_FLAG == BOXBDD then local lq = node_next(lp) - head = node.remove(head, lp); node.free(lp); lp = lq + head = node_remove(head, lp); node_free(lp); lp = lq else return calc_np_pbox(lp, last) end -- id_pbox else @@ -444,7 +460,7 @@ do c = x.char else while xc and xs and xs%4>=2 do - x = node.tail(xc); xc, xs = x.components, x.subtype + x = node_tail(xc); xc, xs = x.components, x.subtype end c = x.char end @@ -630,14 +646,14 @@ local function calc_ja_ja_aux(gb,ga, db, da) gb.spec.shrink = -round(diffmet_rule( -rbb*gb.spec.shrink - rba*ga.spec.shrink, -rab*gb.spec.shrink - raa*ga.spec.shrink )) - node.free(ga) + node_free(ga) return gb elseif k == 'kernkern' then -- 両方とも kern. gb.kern = round(diffmet_rule( rbb*gb.kern + rba*ga.kern, rab*gb.kern + raa*ga.kern )) - node.free(ga) + node_free(ga) return gb elseif k == 'kernglue' then -- gb: kern, ga: glue @@ -648,7 +664,7 @@ local function calc_ja_ja_aux(gb,ga, db, da) rba*ga.spec.stretch, raa*ga.spec.stretch )) ga.spec.shrink = -round(diffmet_rule( -rba*ga.spec.shrink,-raa*ga.spec.shrink )) - node.free(gb) + node_free(gb) return ga else -- gb: glue, ga: kern @@ -659,7 +675,7 @@ local function calc_ja_ja_aux(gb,ga, db, da) rbb*gb.spec.stretch, rab*gb.spec.stretch )) gb.spec.shrink = -round(diffmet_rule( -rbb*gb.spec.shrink,-rab*gb.spec.shrink )) - node.free(ga) + node_free(ga) return gb end end @@ -841,7 +857,7 @@ local function handle_list_tail(mode) local g = new_jfm_glue(pm, Np.class, fast_find_char_class('boxbdd', pm)) if g then set_attr(g, attr_icflag, BOXBDD) - head = node.insert_after(head, Np.last, g) + head = insert_after(head, Np.last, g) end end end @@ -902,12 +918,12 @@ local function init_var(mode) or ((lpi==id_hlist) and (lps==3))) do if (lpi==id_hlist) and (lps==3) then par_indented = 'parbdd' end lp=node_next(lp); lpi, lps = lp.id, lp.subtype end - return lp, node.tail(head), par_indented + return lp, node_tail(head), par_indented else -- the current list is the contents of a hbox: -- insert a sentinel local g = node_new(id_kern) - node.insert_after(head, node.tail(head), g); last = g + insert_after(head, node_tail(head), g); last = g return head, g, 'boxbdd' end end @@ -915,7 +931,7 @@ end local function cleanup(mode, last) -- adjust attr_icflag for avoiding error tex.setattribute('global', attr_icflag, 0) - node.free(kanji_skip); node.free(xkanji_skip) + node_free(kanji_skip); node_free(xkanji_skip) if mode then local h = node_next(head) if h.id == id_penalty and h.penalty == 10000 then @@ -926,7 +942,7 @@ local function cleanup(mode, last) end return head else - head = node.remove(head, last); node.free(last);-- remove the sentinel + head = node_remove(head, last); node_free(last);-- remove the sentinel set_attr(head, attr_icflag, get_attr_icflag(head) + PROCESSED_BEGIN_FLAG); return head @@ -998,11 +1014,12 @@ do end end + local node_prev = Dnode.prev 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 + local x, y = node_prev(Nq.nuc), Nq.nuc Nq.first, Nq.nuc, Nq.last = x, x, x - head = node.remove(head, y) + head = node_remove(head, y) end return s end diff --git a/src/ltj-math.lua b/src/ltj-math.lua index 5f9e650..1f213e2 100644 --- a/src/ltj-math.lua +++ b/src/ltj-math.lua @@ -8,11 +8,24 @@ luatexja.load_module('jfont'); local ltjf = luatexja.jfont luatexja.load_module('stack'); local ltjs = luatexja.stack luatexja.load_module('setwidth'); local ltjw = luatexja.setwidth -local node_new = node.new -local node_next = node.next -local node_free = node.free -local has_attr = node.has_attribute -local set_attr = node.set_attribute +local Dnode = node.direct or node + +local setfield = (Dnode == node.direct) and Dnode.setfield or function(n, i, c) n[i] = c end +local getfield = (Dnode == node.direct) and Dnode.getfield or function(n, i) return n[i] end +local getid = (Dnode == node.direct) and Dnode.getid or function(n) return n.id end +local getlist = (Dnode == node.direct) and Dnode.getlist or function(n) return n.head end +local getchar = (Dnode == node.direct) and Dnode.getlist or function(n) return n.char end + +local nullfunc = function(n) return n end +local to_node = (Dnode == node.direct) and Dnode.tonode or nullfunc +local to_direct = (Dnode == node.direct) and Dnode.todirect or nullfunc + +local node_traverse = Dnode.traverse +local node_new = Dnode.new +local node_next = Dnode.next +local node_free = Dnode.free +local has_attr = Dnode.has_attribute +local set_attr = Dnode.set_attribute local tex_getcount = tex.getcount local attr_jchar_class = luatexbase.attributes['ltj@charclass'] @@ -46,38 +59,37 @@ local conv_jchar_to_hbox_A -- sty : 0 (display or text), 1 (script), >=2 (scriptscript) local function conv_jchar_to_hbox(head, sty) - local p = head - local bhead = head - while p do - if p.id == id_simple or p.id == id_accent then - p.nucleus = conv_jchar_to_hbox_A(p.nucleus, sty) - p.sub = conv_jchar_to_hbox_A(p.sub, sty + 1) - p.sup = conv_jchar_to_hbox_A(p.sup, sty + 1) - elseif p.id == id_choice then - p.display = conv_jchar_to_hbox(p.display, 0) - p.text = conv_jchar_to_hbox(p.text, 0) - p.script = conv_jchar_to_hbox(p.script, 1) - p.scriptscript = conv_jchar_to_hbox(p.scriptscript, 2) - elseif p.id == id_frac then - p.num = conv_jchar_to_hbox_A(p.num, sty + 1) - p.denom = conv_jchar_to_hbox_A(p.denom, sty + 1) - elseif p.id == id_radical then - p.nucleus = conv_jchar_to_hbox_A(p.nucleus, sty) - p.sub = conv_jchar_to_hbox_A(p.sub, sty + 1) - p.sup = conv_jchar_to_hbox_A(p.sup, sty + 1) - if p.degree then - p.degree = conv_jchar_to_hbox_A(p.degree, sty + 1) + for p in node_traverse(head) do + local pid = getid(p) + if pid == id_simple or pid == id_accent then + setfield(p, 'nucleus', conv_jchar_to_hbox_A(getfield(p, 'nucleus'), sty)) + setfield(p, 'sub', conv_jchar_to_hbox_A(getfield(p, 'sub'), sty+1)) + setfield(p, 'sup', conv_jchar_to_hbox_A(getfield(p, 'sup'), sty+1)) + elseif pid == id_choice then + setfield(p, 'display', conv_jchar_to_hbox_A(getfield(p, 'display'), 0)) + setfield(p, 'text', conv_jchar_to_hbox_A(getfield(p, 'text'), 0)) + setfield(p, 'script', conv_jchar_to_hbox_A(getfield(p, 'script'), 1)) + setfield(p, 'scriptscript', conv_jchar_to_hbox_A(getfield(p, 'scriptscript'), 2)) + elseif pid == id_frac then + setfield(p, 'num', conv_jchar_to_hbox_A(getfield(p, 'num'), sty+1)) + setfield(p, 'denom', conv_jchar_to_hbox_A(getfield(p, 'denom'), sty+1)) + elseif pid == id_radical then + setfield(p, 'nucleus', conv_jchar_to_hbox_A(getfield(p, 'nucleus'), sty)) + setfield(p, 'sub', conv_jchar_to_hbox_A(getfield(p, 'sub'), sty+1)) + setfield(p, 'sup', conv_jchar_to_hbox_A(getfield(p, 'sup'), sty+1)) + if getfield(p, 'degree') then + setfield(p, 'degree', conv_jchar_to_hbox_A(getfield(p, 'degree'), sty + 1)) end - elseif p.id == id_style then - if p.style == "display'" or p.style == 'display' - or p.style == "text'" or p.style == 'text' then + elseif pid == id_style then + local ps = getfield(p, 'style') + if ps == "display'" or ps == 'display' + or ps == "text'" or ps == 'text' then sty = 0 - elseif p.style == "script'" or p.style == 'script' then + elseif ps == "script'" or ps == 'script' then sty = 1 else sty = 2 end end - p = node.next(p) end return head end @@ -85,37 +97,39 @@ end local MJT = luatexja.stack_table_index.MJT local MJS = luatexja.stack_table_index.MJS local MJSS = luatexja.stack_table_index.MJSS +local capsule_glyph = ltjw.capsule_glyph conv_jchar_to_hbox_A = function (p, sty) if not p then return nil else - local pid = p.id + local pid = getid(p) if pid == id_sub_mlist then - if p.head then - p.head = conv_jchar_to_hbox(p.head, sty) + if getlist(p) then + setfield(p, 'head', conv_jchar_to_hbox(getlist(p), sty)) end elseif pid == id_mchar then local fam = has_attr(p, attr_jfam) or -1 - if (not is_math_letters[p.char]) and ltjc.is_ucs_in_japanese_char(p) and fam>=0 then + local pc = getchar(p) + if (not is_math_letters[pc]) and ltjc.is_ucs_in_japanese_char(to_node(p)) and fam>=0 then local f = ltjs.get_penalty_table(MJT + 0x100 * sty + fam, -1, tex_getcount('ltj@@stack')) if f ~= -1 then local q = node_new(id_sub_box) - local r = node_new(id_glyph); r.next = nil - r.char = p.char; r.font = f; r.subtype = 256 + local r = node_new(id_glyph); setfield(r, 'next', nil) + setfield(r, 'char', pc); setfield(r, 'font', f); setfield(r, 'subtype', 256) local k = has_attr(r,attr_ykblshift) or 0 set_attr(r, attr_ykblshift, 0) -- ltj-setwidth 内で実際の位置補正はおこなうので,補正量を退避 ltjw.head = r; local met = ltjf_font_metric_table[f] - ltjw.capsule_glyph(r, tex.mathdir , true, met, ltjf_find_char_class(p.char, met)); - q.head = ltjw.head; node_free(p); p=q; - set_attr(q.head, attr_yablshift, k) + capsule_glyph(r, tex.mathdir , true, met, ltjf_find_char_class(pc, met)); + setfield(q, 'head', ltjw.head); node_free(p); p=q; + set_attr(getlist(q), attr_yablshift, k) end end - elseif pid == id_sub_box and p.head then + elseif pid == id_sub_box and getlist(p) then -- \hbox で直に与えられた内容は上下位置を補正する必要はない - set_attr(p.head, attr_icflag, PROCESSED) + set_attr(getlist(p), attr_icflag, PROCESSED) end end return p @@ -123,7 +137,7 @@ end luatexbase.add_to_callback('mlist_to_hlist', function (n, display_type, penalties) - local head = conv_jchar_to_hbox(n, 0); + local head = to_node(conv_jchar_to_hbox(to_direct(n), 0)) head = node.mlist_to_hlist(head, display_type, penalties) return head end,'ltj.mlist_to_hlist', 1) diff --git a/src/ltj-setwidth.lua b/src/ltj-setwidth.lua index ef94612..eec65ad 100644 --- a/src/ltj-setwidth.lua +++ b/src/ltj-setwidth.lua @@ -1,25 +1,29 @@ -- --- luatexja/setwidth.lua +-- src/ltj-setwidth.lua -- -luatexbase.provides_module({ - name = 'luatexja.setwidth', - date = '2013/12/05', - description = '', -}) -module('luatexja.setwidth', package.seeall) -local err, warn, info, log = luatexbase.errwarinf(_NAME) luatexja.load_module('base'); local ltjb = luatexja.base luatexja.load_module('jfont'); local ltjf = luatexja.jfont -local node_type = node.type -local node_new = node.new -local node_tail = node.tail -local node_next = node.next -local has_attr = node.has_attribute -local set_attr = node.set_attribute -local node_insert_before = node.insert_before -local node_insert_after = node.insert_after +local Dnode = node.direct or node + +local setfield = (Dnode == node.direct) and Dnode.setfield or function(n, i, c) n[i] = c end +local getfield = (Dnode == node.direct) and Dnode.getfield or function(n, i) return n[i] end +local getid = (Dnode == node.direct) and Dnode.getid or function(n) return n.id end +local getfont = (Dnode == node.direct) and Dnode.getfont or function(n) return n.font end +local getlist = (Dnode == node.direct) and Dnode.getlist or function(n) return n.head end +local getchar = (Dnode == node.direct) and Dnode.getlist or function(n) return n.char end +local getsubtype = (Dnode == node.direct) and Dnode.getlist or function(n) return n.subtype end + +local node_traverse = Dnode.traverse +local node_new = Dnode.new +local node_remove = Dnode.remove +local node_tail = Dnode.tail +local node_next = Dnode.getnext +local has_attr = Dnode.has_attribute +local set_attr = Dnode.set_attribute +local node_insert_before = Dnode.insert_before +local node_insert_after = Dnode.insert_after local round = tex.round local id_glyph = node.id('glyph') @@ -42,88 +46,98 @@ local PROCESSED = luatexja.icflag_table.PROCESSED local IC_PROCESSED = luatexja.icflag_table.IC_PROCESSED local PROCESSED_BEGIN_FLAG = luatexja.icflag_table.PROCESSED_BEGIN_FLAG +local get_pr_begin_flag do local floor = math.floor - function get_pr_begin_flag(p) + get_pr_begin_flag = function (p) local i = has_attr(p, attr_icflag) or 0 return i - i%PROCESSED_BEGIN_FLAG end end -local get_pr_begin_flag = get_pr_begin_flag -head = nil; +local ltjw = {} +luatexja.setwidth = ltjw luatexbase.create_callback("luatexja.set_width", "data", function (fstable, fmtable, jchar_class) return fstable end) +local call_callback = luatexbase.call_callback local fshift = { down = 0, left = 0} -- mode: true iff p will be always encapsuled by a hbox -function capsule_glyph(p, dir, mode, met, class) +local function capsule_glyph(p, dir, mode, met, class) local char_data = met.char_type[class] if not char_data then return node_next(p) end - local fwidth, pwidth = char_data.width, p.width + local fwidth, pwidth = char_data.width, getfield(p, 'width') fwidth = (fwidth ~= 'prop') and fwidth or pwidth fshift.down = char_data.down; fshift.left = char_data.left - fshift = luatexbase.call_callback("luatexja.set_width", fshift, met, class) + fshift = call_callback("luatexja.set_width", fshift, met, class) local fheight, fdepth = char_data.height, char_data.depth - if (mode or pwidth ~= fwidth or p.height ~= fheight or p.depth ~= fdepth) then + if (mode or pwidth ~= fwidth or getfield(p, 'height') ~= fheight or getfield(p, 'depth') ~= fdepth) then local y_shift, ca - = - p.yoffset + (has_attr(p,attr_ykblshift) or 0), char_data.align - local q; head, q = node.remove(head, p) - p.yoffset, p.next = -fshift.down, nil + = - getfield(p, 'yoffset') + (has_attr(p,attr_ykblshift) or 0), char_data.align + local q + ltjw.head, q = node_remove(ltjw.head, p) + setfield(p, 'yoffset', -fshift.down); setfield(p, 'next', nil) if ca~='left' then - p.xoffset = p.xoffset - fshift.left - + (((ca=='right') and fwidth - pwidth) or round((fwidth - pwidth)*0.5)) + setfield(p, 'xoffset', getfield(p, 'xoffset') - fshift.left + + (((ca=='right') and fwidth - pwidth) or round((fwidth - pwidth)*0.5))) else - p.xoffset = p.xoffset - fshift.left + setfield(p, 'xoffset', getfield(p, 'xoffset') - fshift.left) end local box = node_new(id_hlist); - box.width, box.height, box.depth = fwidth, fheight, fdepth - box.head, box.shift, box.dir = p, y_shift, (dir or 'TLT') - --box.glue_set, box.glue_order = 0, 0 not needed + setfield(box, 'width', fwidth) + setfield(box, 'height', fheight) + setfield(box, 'depth', fdepth) + setfield(box, 'head', p) + setfield(box, 'shift', y_shift) + setfield(box, 'dir', dir or 'TLT') set_attr(box, attr_icflag, PACKED + get_pr_begin_flag(p)) - head = q and node_insert_before(head, q, box) - or node_insert_after(head, node_tail(head), box) + ltjw.head = q and node_insert_before(ltjw.head, q, box) + or node_insert_after(ltjw.head, node_tail(ltjw.head), box) return q else set_attr(p, attr_icflag, PROCESSED + get_pr_begin_flag(p)) - p.xoffset = p.xoffset - fshift.left - p.yoffset = p.yoffset - (has_attr(p, attr_ykblshift) or 0) - fshift.down + setfield(p, 'xoffset', getfield(p, 'xoffset') - fshift.left) + setfield(p, 'yoffset', getfield(p, 'yoffset') - (has_attr(p, attr_ykblshift) or 0) - fshift.down) return node_next(p) end end +luatexja.setwidth.capsule_glyph = capsule_glyph -function set_ja_width(ahead, dir) - local p = ahead; head = ahead +function luatexja.setwidth.set_ja_width(ahead, dir) + local p = ahead; ltjw.head = p local m = false -- is in math mode? while p do - local pid = p.id + local pid = getid(p) if (pid==id_glyph) and ((has_attr(p, attr_icflag) or 0)%PROCESSED_BEGIN_FLAG)<=0 then - local pf = p.font + local pf = getfont(p) if pf == has_attr(p, attr_curjfnt) then p = capsule_glyph(p, dir, false, ltjf_font_metric_table[pf], has_attr(p, attr_jchar_class)) else set_attr(p, attr_icflag, PROCESSED + get_pr_begin_flag(p)) - p.yoffset = p.yoffset - (has_attr(p,attr_yablshift) or 0); p = node_next(p) + setfield(p, 'yoffset', + getfield(p, 'yoffset') - (has_attr(p,attr_yablshift) or 0)) + p = node_next(p) end - elseif p.id==id_math then - m = (p.subtype==0); p = node_next(p) + elseif pid==id_math then + m = (getsubtype(p)==0); p = node_next(p) else if m then -- 数式の位置補正 if pid==id_hlist or pid==id_vlist then if (has_attr(p, attr_icflag) or 0) ~= PROCESSED then - p.shift = p.shift + (has_attr(p,attr_yablshift) or 0) + setfield(p, 'shift', getfield(p, 'shift') + (has_attr(p,attr_yablshift) or 0)) end elseif pid==id_rule then if (has_attr(p, attr_icflag) or 0) ~= PROCESSED then local v = has_attr(p,attr_yablshift) or 0 - p.height = p.height - v; p.depth = p.depth + v + setfield(p, 'height', getfield(p, 'height')-v) + setfield(p, 'depth', getfield(p, 'depth')+v) set_attr(p, attr_icflag, PROCESSED + get_pr_begin_flag(p)) end end @@ -133,5 +147,6 @@ function set_ja_width(ahead, dir) end -- adjust attr_icflag tex.setattribute('global', attr_icflag, 0) - return head + return ltjw.head end + -- 2.11.0