X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=src%2Fltj-ruby.lua;h=84c31d7fc5e26284ad646014a4d70f4859f6ad4b;hb=1379fbf6aae445cdce3906e7b83cc1c8550e78d5;hp=42c4074fe0c46bd771f5bff78e0be59957e6bc4a;hpb=ca2f902449134e3055387148c03930652e4ee67f;p=luatex-ja%2Fluatexja.git diff --git a/src/ltj-ruby.lua b/src/ltj-ruby.lua index 42c4074..84c31d7 100644 --- a/src/ltj-ruby.lua +++ b/src/ltj-ruby.lua @@ -3,8 +3,8 @@ -- luatexbase.provides_module({ name = 'luatexja.ruby', - date = '2014/02/06', - description = 'Ruby', + date = '2014/05/08', + description = 'Ruby annotation', }) module('luatexja.ruby', package.seeall) local err, warn, info, log = luatexbase.errwarinf(_NAME) @@ -53,6 +53,7 @@ local attr_ruby_maxmargin = luatexbase.attributes['ltj@kcat1'] local attr_ruby_stretch = luatexbase.attributes['ltj@kcat2'] local attr_ruby_mode = luatexbase.attributes['ltj@kcat3'] local attr_ruby_id = luatexbase.attributes['ltj@kcat4'] -- uniq id +local attr_ruby_intergap = luatexbase.attributes['ltj@kcat5'] local attr_ruby = luatexbase.attributes['ltj@rubyattr'] -- ルビ内部処理用,以下のようにノードによって使われ方が異なる -- * (whatsit) では JAglue 処理時に, @@ -90,26 +91,39 @@ local function gauss(coef) local deg = #coef for i = 1, deg do if coef[i][i]==0 then - for j = i+1, deg do + for j = i+1, deg do if coef[j][i]~=0 then coef[i], coef[j] = coef[j], coef[i]; break end end end - for j = 1,deg do + for j = 1,deg do local d = coef[i][i]; if j~=i then local e = coef[j][i] for k = 1, deg+1 do coef[j][k] = coef[j][k] - e*coef[i][k]/d end - else + else for k = 1, deg+1 do coef[i][k] = coef[i][k]/d end end end end end +local function solve_1(coef) + local a, b, c = coef[1][4], coef[2][4], coef[3][4] + coef[1][4], coef[2][4], coef[3][4] = c-b, a+b-c, c-a + return coef +end + +local function solve_2(coef) + local a, b, c, d, e = coef[1][6], coef[2][6], coef[3][6], coef[4][6], coef[5][6] + coef[1][6], coef[2][6], coef[3][6], coef[4][6], coef[5][6] + = e-c, a+c-e, e-a-d, b+d-e, e-b + return coef +end + + -- 実行回数 + ルビ中身 から uniq_id を作る関数 --- 未実装.これを使えば 2 回目以降の組版に 1 回目の情報が使える old_break_info = {} -- public, 前 run 時の分割情報 local make_uniq_id do @@ -131,7 +145,7 @@ local function concat(f, b) setfield(f, 'head', nil); node_free(f) setfield(b, 'head', nil); node_free(b) return Dnode.hpack(luatexja.jfmglue.main(h,false)) - else + else return f end elseif b then @@ -172,15 +186,14 @@ do enlarge = function (box, new_width, pre, middle, post, prenw, postnw) -- pre, middle, post: 伸縮比率 -- prenw, postnw: 前後の自然長 (sp) - local h = getlist(box); + local h = getlist(box); local hh, hd = getfield(box, 'height'), getfield(box, 'depth') local hx = h while hx do - if has_attr(hx, attr_icflag) == KANJI_SKIP - or has_attr(hx, attr_icflag) == KANJI_SKIP_JFM - or has_attr(hx, attr_icflag) == XKANJI_SKIP - or has_attr(hx, attr_icflag) == XKANJI_SKIP_JFM - or has_attr(hx, attr_icflag) == FROM_JFM then + local hic = has_attr(hx, attr_icflag) + if (hic == KANJI_SKIP) or (hic == KANJI_SKIP_JFM) + or (hic == XKANJI_SKIP) or (hic == XKANJI_SKIP_JFM) + or ((hic<=FROM_JFM+2) and (hic>=FROM_JFM-2)) then -- この 5 種類の空白をのばす if getid(hx) == id_kern then local k = node_new(id_glue) @@ -247,8 +260,9 @@ local function texiface_low(rst, rtlr, rtlp) setfield(wv, 'value', floor(#rtlr)) set_attr(wv, attr_ruby, rst.rubyzw) set_attr(wv, attr_ruby_maxmargin, rst.maxmargin) - set_attr(wv, attr_ruby_maxprep, rst.intrusionpre) - set_attr(wv, attr_ruby_maxpostp, rst.intrusionpost) + set_attr(wv, attr_ruby_maxprep, rst.pre) + set_attr(wv, attr_ruby_maxpostp, rst.post) + set_attr(wv, attr_ruby_intergap, rst.intergap) set_attr(wv, attr_ruby_stretch, rst.stretch) set_attr(wv, attr_ruby_mode, rst.mode) local n = wv @@ -300,17 +314,17 @@ local function enlarge_parent(r, p, ppre, pmid, ppost, mapre, mapost, intmode) local sumprot = rwidth - getfield(p, 'width') -- >0 local pre_intrusion, post_intrusion if intmode == 0 then -- とりあえず組んでから決める - p = enlarge(p, rwidth, ppre, pmid, ppost, 0, 0) + p = enlarge(p, rwidth, ppre, pmid, ppost, 0, 0) pre_intrusion = min(mapre, round(ppre*getfield(p, 'glue_set')*65536)) post_intrusion = min(mapost, round(ppost*getfield(p, 'glue_set')*65536)) elseif intmode == 1 then - pre_intrusion = min(mapre, sumprot); + pre_intrusion = min(mapre, sumprot); post_intrusion = min(mapost, max(sumprot-pre_intrusion, 0)) p = enlarge(p, rwidth, ppre, pmid, ppost, pre_intrusion, post_intrusion) elseif intmode == 2 then - post_intrusion = min(mapost, sumprot); + post_intrusion = min(mapost, sumprot); pre_intrusion = min(mapre, max(sumprot-post_intrusion, 0)) - p = enlarge(p, rwidth, ppre, pmid, ppost, pre_intrusion, post_intrusion) + p = enlarge(p, rwidth, ppre, pmid, ppost, pre_intrusion, post_intrusion) else -- intmode == 3 local n = min(mapre, mapost)*2 if n < sumprot then @@ -318,7 +332,7 @@ local function enlarge_parent(r, p, ppre, pmid, ppost, mapre, mapost, intmode) else pre_intrusion = floor(sumprot/2); post_intrusion = sumprot - pre_intrusion end - p = enlarge(p, rwidth, ppre, pmid, ppost, pre_intrusion, post_intrusion) + p = enlarge(p, rwidth, ppre, pmid, ppost, pre_intrusion, post_intrusion) pre_intrusion = min(mapre, pre_intrusion + round(ppre*getfield(p, 'glue_set')*65536)) post_intrusion = min(mapost, post_intrusion + round(ppost*getfield(p, 'glue_set')*65536)) end @@ -334,13 +348,19 @@ end -- ルビボックスの生成(単一グループ) -- returned value: , , local max_margin -local function new_ruby_box(r, p, ppre, pmid, ppost, - rpre, rmid, rpost, mapre, mapost, intmode) +local function new_ruby_box(r, p, ppre, pmid, ppost, + mapre, mapost, imode, rgap) local post_intrusion = 0 + local intmode = imode%4 + local rpre, rmid, rpost, rsmash + imode = floor(imode/262144); rsmash = (imode%2 ==1) + imode = floor(imode/2); rpost = imode%8; + imode = (imode-rpost)/8; rmid = imode%8; + imode = (imode-rmid)/8; rpre = imode%8 if getfield(r, 'width') > getfield(p, 'width') then -- change the width of p r, p, post_intrusion = enlarge_parent(r, p, ppre, pmid, ppost, mapre, mapost, intmode) elseif getfield(r, 'width') < getfield(p, 'width') then -- change the width of r - r = enlarge(r, getfield(p, 'width'), rpre, rmid, rpost, 0, 0) + r = enlarge(r, getfield(p, 'width'), rpre, rmid, rpost, 0, 0) post_intrusion = 0 local need_repack = false -- margin が大きくなりすぎた時の処理 @@ -360,15 +380,20 @@ local function new_ruby_box(r, p, ppre, pmid, ppost, setfield(rt, 'head', nil); node_free(rt); end end - local a = node_new(id_rule) - setfield(a, 'width', 0) - setfield(a, 'height', 0) - setfield(a, 'depth', 0) - insert_after(r, r, a); insert_after(r, a, p) - setfield(p, 'next', nil) - a = Dnode.vpack(r) - setfield(a, 'shift', 0) + local a, k = node_new(id_rule), node_new(id_kern) + setfield(a, 'width', 0); setfield(a, 'height', 0) + setfield(a, 'depth', 0); setfield(k, 'kern', rgap) + insert_after(r, r, a); insert_after(r, a, k); + insert_after(r, k, p); setfield(p, 'next', nil) + a = Dnode.vpack(r); setfield(a, 'shift', 0) set_attr(a, attr_ruby, post_intrusion) + if rsmash or getfield(a, 'height')0 then - -- 直前のルビで intrusion がおこる可能性あり. - -- 前 run のデータが残っていればそれを使用, - -- そうでなければ行中形のデータを利用する - local op = old_break_info[atr] or post_intrusion_backup - max_allow_pre = max(0, max_allow_pre - op) + if max_allow_pre < 0 then + if atr>0 then + -- 直前のルビで intrusion がおこる可能性あり. + -- 前 run のデータが残っていればそれを使用, + -- そうでなければ行中形のデータを利用する + local op = old_break_info[atr] or post_intrusion_backup + max_allow_pre = max(0, -max_allow_pre - op) + else + max_allow_pre = -max_allow_pre + end end post_intrusion_backup = 0 max_allow_post = has_attr(nv, attr_ruby_maxpostp) or 0 @@ -505,7 +538,7 @@ local function pre_high(ahead) local coef = pre_low_cal_box(n, getfield(nv, 'value')) local s = node_tail(nv) --ルビ文字 head, n = pre_low_app_node( - head, n, getfield(nv, 'value'), coef, + head, n, getfield(nv, 'value'), coef, getfield(s, 'height'), getfield(s, 'depth') ) else @@ -513,7 +546,7 @@ local function pre_high(ahead) end end return to_node(head) -end +end luatexbase.add_to_callback('pre_linebreak_filter', pre_high, 'ltj.ruby.pre', 100) luatexbase.add_to_callback('hpack_filter', pre_high, 'ltj.ruby.pre', 100) @@ -525,9 +558,9 @@ do local function write_aux(wv, num) local id = has_attr(wv, attr_ruby_id) if id>0 then - tex.sprint(cat_lp, - '\\write\\@mainaux{\\string\\directlua{luatexja.ruby.old_break_info[' - .. tostring(id) .. ']=' .. num + tex.sprint(cat_lp, + '\\write\\@mainaux{\\string\\directlua{luatexja.ruby.old_break_info[' + .. tostring(id) .. ']=' .. num .. '}}') end end @@ -538,7 +571,7 @@ do local hn = has_attr(rs[1], attr_ruby) local fn = has_attr(rs[#rs], attr_ruby) local wv = getfield(rw, 'value') - if hn==1 then + if hn==1 then if fn==2*cmp+2 then local hn = node_tail(wv) node_remove(wv, hn) @@ -547,7 +580,7 @@ do write_aux(wv, has_attr(hn, attr_ruby))-- 行中形 else local deg, hn = (fn-1)/2, wv - for i = 1, deg do hn = node_next(hn) end; + for i = 1, deg do hn = node_next(hn) end; node_remove(wv, hn) setfield(hn, 'next', nil) insert_after(ch, rs[#rs], hn) @@ -555,9 +588,9 @@ do write_aux(wv, has_attr(hn, attr_ruby)) end else - local deg, hn = max((hn-1)/2,2), wv + local deg, hn = max((hn-1)/2,2), wv for i = 1, cmp+deg-1 do hn = node_next(hn) end - -- -1 is needed except the case hn = 3, + -- -1 is needed except the case hn = 3, -- because a ending-line form is removed already from the list node_remove(wv, hn); setfield(hn, 'next', nil) insert_after(ch, rs[#rs], hn) @@ -566,7 +599,7 @@ do write_aux(wv, has_attr(hn, attr_ruby)) end end - for i = 1,#rs do + for i = 1,#rs do local ri = rs[i] ch = node_remove(ch, ri); node_free(ri); end @@ -576,30 +609,8 @@ do end end --- local function is_zero_parfillskip(h,n) --- if getid(n)==id_glue then --- if getsubtype(n)==15 then --- local ns = getfield(n, 'spec') --- local n_width = getfield(ns, 'width') --- if getfield(h, 'glue_sign')==1 --- and getfield(h, 'glue_order') == getfield(ns, 'stretch_order') then --- n_width = n_width --- + round(getfield(h, 'glue_set')*getfield(ns, 'stretch')) --- elseif getfield(h, 'glue_sign')==2 --- and getfield(h, 'glue_order') == getfield(ns, 'shrink_order') then --- n_width = n_width --- - round(getfield(h, 'glue_set')*getfield(n,s 'shrink')) --- end --- n = node_next(n) -- rightskip 未完 --- return (n_width <= 0) --- else return false --- end --- else return false --- end --- end - local function post_high_break(head) - local rs = {} -- rs: sequence of ruby_nodes, + local rs = {} -- rs: sequence of ruby_nodes, local rw = nil -- rw: main whatsit local cmp = -2 -- dummy for h in Dnode.traverse_id(id_hlist, to_direct(head)) do @@ -607,69 +618,55 @@ local function post_high_break(head) local ha = getlist(h) while ha do local hai = getid(ha) - local i = (((hai == id_glue and getsubtype(ha)==0) - or (hai == id_rule and getsubtype(ha)==0) - or (hai == id_whatsit and getsubtype(ha)==sid_user - and getfield(ha, 'user_id')==RUBY_POST)) - and has_attr(ha, attr_ruby)) or 0 - if i==1 then + local i = ((hai == id_glue and getsubtype(ha)==0) + or (hai == id_rule and getsubtype(ha)==0) + or (hai == id_whatsit and getsubtype(ha)==sid_user + and getfield(ha, 'user_id', RUBY_POST))) + and has_attr(ha, attr_ruby) or 0 + if i==0 then + ha = node_next(ha) + elseif i==1 then setfield(h, 'head', post_lown(rs, rw, cmp, getlist(h))) for i = 2, #rs do rs[i] = nil end -- rs[1] is set by the next statement rs[1], rw = ha, nil; ha = node_next(ha) - elseif i==2*cmp+2 then - -- local par_not_end = true - -- local hn = node_next(ha) - -- if hn and getid(hn)==id_penalty and getfield(hn, 'penalty')==10000 then - -- local hm = node_next(hn) - -- if is_zero_parfillskip(h,hm) then - -- par_not_end = false - -- end - -- end - -- if par_not_end then - rs[#rs+1] = ha; ha = node_next(ha) - -- else - -- setfield(h, 'head', node_remove(getlist(h), ha)); break - -- end - elseif i>=3 then - rs[#rs+1] = ha; ha = node_next(ha) - elseif i==2 then + elseif i==2 then rw = ha cmp = getfield(getfield(rw, 'value'), 'value') local hb, hc = node_remove(getlist(h), rw) setfield(h, 'head', hb); ha = hc - else - ha = node_next(ha) + else -- i>=3 + rs[#rs+1] = ha; ha = node_next(ha) end end setfield(h, 'head', post_lown(rs, rw, cmp, getlist(h))) end return head -end +end local function post_high_hbox(ahead) local ha = to_direct(ahead); local head = ha - local rs = {}; -- rs: sequence of ruby_nodes, + local rs = {}; -- rs: sequence of ruby_nodes, local rw = nil; -- rw: main whatsit local cmp while ha do local hai = getid(ha) - local i = (((hai == id_glue and getsubtype(ha)==0) - or (hai == id_rule and getsubtype(ha)==0) - or (hai == id_whatsit and getsubtype(ha)==sid_user - and getfield(ha, 'user_id', RUBY_POST))) - and has_attr(ha, attr_ruby)) or 0 - if i==1 then + local i = ((hai == id_glue and getsubtype(ha)==0) + or (hai == id_rule and getsubtype(ha)==0) + or (hai == id_whatsit and getsubtype(ha)==sid_user + and getfield(ha, 'user_id', RUBY_POST))) + and has_attr(ha, attr_ruby) or 0 + if i==0 then + ha = node_next(ha) + elseif i==1 then head = post_lown(rs, rw, cmp, head) for i = 2, #rs do rs[i] = nil end -- rs[1] is set by the next statement rs[1], rw = ha, nil; ha = node_next(ha) - elseif i>=3 then - rs[#rs+1] = ha; ha = node_next(ha) - elseif i==2 then + elseif i==2 then rw = ha cmp = getfield(getfield(rw, 'value'), 'value') head, ha = node_remove(head, rw) - else - ha = node_next(ha) + else -- i >= 3 + rs[#rs+1] = ha; ha = node_next(ha) end end return to_node(post_lown(rs, rw, cmp, head)) @@ -684,25 +681,39 @@ luatexbase.add_to_callback('hpack_filter', post_high_hbox, 'ltj.ruby.post_hbox', ---------------------------------------------------------------- do local RIPRE = luatexja.stack_table_index.RIPRE - local function whatsit_callback(Np, lp, Nq, bsl) - if Np.nuc then return Np + local function whatsit_callback(Np, lp, Nq, bsl) + if Np.nuc then return Np elseif getfield(lp, 'user_id') == RUBY_PRE then Np.first, Np.nuc, Np.last = lp, lp, lp local lpv = getfield(lp, 'value') local x = node_next(node_next(lpv)) Np.last_char = luatexja.jfmglue.check_box_high(Np, getlist(x), nil) - if Nq.id ~=id_pbox_w and type(Nq.char)=='number' then - -- Nq is a JAchar - if has_attr(lpv, attr_ruby_maxprep) < 0 then -- auto - local p = round((ltjs.table_current_stack[RIPRE + Nq.char] or 0) - *has_attr(lpv, attr_ruby)) - if has_attr(lpv, attr_ruby_mode)%2 == 0 then -- intrusion 無効 - p = 0 + if Nq.id ~=id_pbox_w then + if type(Nq.char)=='number' then + -- Nq is a JAchar + if has_attr(lpv, attr_ruby_maxprep) < 0 then -- auto + local p = round((ltjs.table_current_stack[RIPRE + Nq.char] or 0) + *has_attr(lpv, attr_ruby)) + if has_attr(lpv, attr_ruby_mode)%2 == 0 then -- intrusion 無効 + p = 0 + end + set_attr(lpv, attr_ruby_maxprep, -p) + end + if Nq.prev_ruby then + set_attr(lp, attr_ruby, Nq.prev_ruby) + end + elseif has_attr(lpv, attr_ruby_maxprep) < 0 then -- auto + if Nq.char == 'parbdd' then + local p = round((ltjs.table_current_stack[RIPRE-1] or 0) + *has_attr(lpv, attr_ruby)) + p = min(p, Nq.width) + if has_attr(lpv, attr_ruby_mode)%2 == 0 then -- intrusion 無効 + p = 0 + end + set_attr(lpv, attr_ruby_maxprep, p) + else + set_attr(lpv, attr_ruby_maxprep, 0) end - set_attr(lpv, attr_ruby_maxprep, p) - end - if Nq.prev_ruby then - set_attr(lp, attr_ruby, Nq.prev_ruby) end elseif has_attr(lpv, attr_ruby_maxprep) < 0 then -- auto set_attr(lpv, attr_ruby_maxprep, 0) @@ -750,9 +761,6 @@ do if has_attr(nqnv, attr_ruby_mode)%4 >= 2 then set_attr(nqnv, attr_ruby_maxprep, 0) end - --if Np and Np.id == id_pbox_w then - -- set_attr(nqnv, attr_ruby_maxprep, 0) - --end end end return true