From: Hironori Kitagawa Date: Wed, 7 May 2014 11:14:17 +0000 (+0900) Subject: ltj-rmlgbm.lua: support vertical form. X-Git-Tag: 20150420.0~222 X-Git-Url: http://git.osdn.jp/view?a=commitdiff_plain;h=3c1d8a6574a9305e9ff4d36b349022c49d8ab0f7;p=luatex-ja%2Fluatexja.git ltj-rmlgbm.lua: support vertical form. --- diff --git a/src/ltj-direction.lua b/src/ltj-direction.lua index 8717556..ee3331a 100644 --- a/src/ltj-direction.lua +++ b/src/ltj-direction.lua @@ -4,6 +4,7 @@ luatexja.load_module('base'); local ltjb = luatexja.base luatexja.load_module('stack'); local ltjs = luatexja.stack +luatexja.load_module('rmlgbm'); local ltjr = luatexja.rmlgbm luatexja.direction = {} local attr_dir = luatexbase.attributes['ltj@dir'] @@ -62,24 +63,30 @@ end do local tex_getcount = tex.getcount - local function set_dir_flag(h) - local new_dir = ltjs.table_current_stack[DIR] - local w = node_new(id_whatsit, sid_user) + local function set_dir_flag(h, gc) + local hd, new_dir = to_direct(h), ltjs.table_current_stack[DIR] + local w + if hd and getid(hd)==id_whatsit and getsubtype(hd)==sid_user + and getfield(hd, 'user_id')==wh_DIR then + w = hd + else + w = node_new(id_whatsit, sid_user) + setfield(w, 'next', hd) + end setfield(w, 'user_id', wh_DIR) setfield(w, 'type', 100) setfield(w, 'value', new_dir) - setfield(w, 'next', to_direct(h)) return to_node(w) end luatexbase.add_to_callback('hpack_filter', set_dir_flag, 'ltj.set_dir_flag', 10000) luatexbase.add_to_callback('vpack_filter', - function (h) + function (h, gc) local box_set, cl = 0, tex.currentgrouplevel + 1 for w in traverse_id(id_whatsit, to_direct(h)) do if getfield(w, 'value')==cl then box_set = 1; break end end ltjs.report_stack_level(tex_getcount('ltj@@stack') + box_set) - return set_dir_flag(h) + return set_dir_flag(h, gc) end, 'ltj.set_dir_flag', 1) luatexbase.add_to_callback('post_linebreak_filter', function (h) @@ -87,7 +94,7 @@ do for line in traverse_id(id_hlist, to_direct(h)) do set_attr(line, attr_dir, new_dir) end - return h + return set_dir_flag(h, gc) end, 'ltj.set_dir_flag', 100) end @@ -149,8 +156,9 @@ do }, } - make_dir_node = function (head, b, new_dir) + make_dir_node = function (head, b, new_dir, origin) -- head: list head, b: box + -- origin: コール元 (for debug) -- return value: (new head), (next of b), (new b), (is_b_dir_node) -- (new b): b か dir_node に被せられた b local old_dir @@ -159,13 +167,14 @@ do and getfield(bh, 'user_id')==wh_DIR then old_dir = getfield(bh, 'value') setfield(b, 'head', node_next(bh)) - set_attr(b, attr_icflag, PROCESSED) + set_attr(b, attr_icflag, PROCESSED) node_free(bh) else old_dir = has_attr(b, attr_dir) or dir_yoko if old_dir==0 then old_dir =dir_yoko end end - if old_dir==new_dir then + --print('make_dir_node', origin, old_dir,new_dir) + if old_dir==new_dir then set_attr(b, attr_icflag, PROCESSED) return head, node_next(b), b, false elseif -old_dir == new_dir then @@ -225,13 +234,14 @@ do return nh, nb, ret, flag end end - local function process_dir_node(head) + local function process_dir_node(head, gc) local h = to_direct(head) local x, new_dir = h, ltjs.table_current_stack[DIR] or dir_yoko while x do local xid = getid(x) - if (xid==id_hlist and has_attr(x, attr_icflag)~=PACKED) or xid==id_vlist then - h, x = make_dir_node(h, x, new_dir) + if (xid==id_hlist and has_attr(x, attr_icflag)~=PACKED) + or xid==id_vlist then + h, x = make_dir_node(h, x, new_dir, 'process_dir_node:' .. gc) else x = node_next(x) end @@ -246,7 +256,6 @@ end local font_vert_table = {} -- key: fontnumber do local font_vert_basename = {} -- key: basename - local function add_feature_table(tname, src, dest) for i,v in pairs(src) do if type(v.slookups)=='table' then @@ -262,7 +271,7 @@ do -- test if already loaded if type(id)=='number' then -- sometimes id is an integer font_vert_table[n] = font_vert_table[id]; return - elseif not id then return + elseif (not id) or font_vert_table[n] then return end local fname = id.filename @@ -289,7 +298,7 @@ do function luatexja.direction.get_vert_glyph(n, chr) local fn = font_vert_table[n] - return (fn and fn[chr]) or chr + return fn and fn[chr] or chr end luatexbase.add_to_callback('luatexja.define_font', @@ -297,5 +306,8 @@ do prepare_vert_data(id, res) end, 'prepare_vert_data', 1) + + local function a (n, dat) font_vert_table[n] = dat end + luatexja.rmlgbm.vert_addfunc = a end diff --git a/src/ltj-jfmglue.lua b/src/ltj-jfmglue.lua index 4e26e27..9910c55 100644 --- a/src/ltj-jfmglue.lua +++ b/src/ltj-jfmglue.lua @@ -34,6 +34,7 @@ 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 ltjd_make_dir_node = ltjd.make_dir_node local ltjf_font_metric_table = ltjf.font_metric_table local ltjf_find_char_class = ltjf.find_char_class local node_new = Dnode.new @@ -306,14 +307,14 @@ local calc_np_auxtable = { end, [id_hlist] = function(lp) local op, flag - head, lp, op, flag = ltjd.make_dir_node(head, lp, list_dir) + head, lp, op, flag = ltjd_make_dir_node(head, lp, list_dir, 'jfm hlist') Np.first = Np.first or op; Np.last = op; Np.nuc = op; Np.id = (flag or getfield(op, 'shift')~=0) and id_box_like or id_hlist return true, lp end, box_like = function(lp) local op - head, lp, op = ltjd.make_dir_node(head, lp, list_dir) + head, lp, op = ltjd_make_dir_node(head, lp, list_dir, 'jfm:' .. getid(lp)) Np.first = Np.first or op; Np.last = op; Np.nuc = op; Np.id = id_box_like; return true, lp diff --git a/src/ltj-plain.sty b/src/ltj-plain.sty index ab264ff..493a40c 100644 --- a/src/ltj-plain.sty +++ b/src/ltj-plain.sty @@ -62,6 +62,7 @@ xkanjiskip=.25\zw plus 1pt minus 1pt, autospacing, autoxspacing, jacharrange={-1}, yalbaselineshift=0pt, yjabaselineshift=0pt, + talbaselineshift=0pt, tjabaselineshift=0pt, jcharwidowpenalty=500, differentjfm=paverage } diff --git a/src/ltj-rmlgbm.lua b/src/ltj-rmlgbm.lua index 484960f..a785a57 100644 --- a/src/ltj-rmlgbm.lua +++ b/src/ltj-rmlgbm.lua @@ -5,7 +5,7 @@ luatexja.load_module('base'); local ltjb = luatexja.base local cidfont_data = {} local cache_chars = {} -local cache_ver = '2' +local cache_ver = '3' local cid_reg, cid_order, cid_supp, cid_name local cid_replace = { @@ -121,40 +121,48 @@ do cidfont_data[cid_name] = k -- CID => Unicode 符号空間 - -- TODO: vertical fonts? - tt, cidm = {}, {} + local tth, cidmo = {}, {} + tt, cidm = tth, cidmo for i = 0,kx[2] do cidm[i] = -1 end open_cmap_file(kx[1] .. "-H", increment, tonumber, entry) - k.characters = tt + k.characters = tth -- Unicode にマップされなかった文字の処理 -- これらは TrueType フォントを使って表示するときはおかしくなる local ttu, pricode = {}, 0xF0000 - for i,v in ipairs(cidm) do + for i,v in ipairs(cidmo) do if v==-1 then - tt[pricode], cidm[i], pricode + tth[pricode], cidmo[i], pricode = { index = i }, pricode, pricode+1; end - ttu[cid_order .. '.' .. i] = cidm[i] + ttu[cid_order .. '.' .. i] = cidmo[i] end + + -- 縦書用字形 + tt, cidm = {}, {} + for i = 0,kx[2] do cidm[i] = -1 end + open_cmap_file(kx[1] .. "-V", increment, tonumber, entry) + local ttv = {} + for i,v in pairs(tt) do ttv[i] = cidmo[v.index] end + -- shared k.shared = { otfdata = { cidinfo= k.cidinfo, verbose = false, shared = { featuredata = {}, }, - luatex = { features = {}, + luatex = { features = {}, defaultwidth=1000, - sequences = { }, }, + }, }, dynamics = {}, features = {}, processes = {}, + ltj_vert_table = ttv } k.resources = { unicodes = ttu, } k.descriptions = {} cache_chars[cid_name] = { [655360] = k.characters } -- tounicode エントリ - local cidp = {nil, nil}; local cidmo = cidm - tt, ttu, cidm = {}, {}, {} + local cidp = {nil, nil}; tt, ttu, cidm = {}, {}, {} open_cmap_file(cid_name .. "-UCS2", function(a) a[2] = a[2] +1 ; return a @@ -215,6 +223,7 @@ local function mk_rml(name, size, id) local fontdata = {} local cachedata = {} local s = cidfont_data[cid_name] + luatexja.rmlgbm.vert_addfunc(id, s.shared.ltj_vert_table) for k, v in pairs(s) do fontdata[k] = v cachedata[k] = v @@ -330,11 +339,13 @@ local function font_callback(name, size, id, fallback) end end -cid_reg, cid_order, cid_name, cid_supp = 'Adobe', 'Japan1', 'Adobe-Japan1' -read_cid_font() - - luatexja.rmlgbm = { cidfont_data = cidfont_data, font_callback = font_callback, + vert_addfunc = function () end, -- dummy, set in ltj-direction.lua } + +cid_reg, cid_order, cid_name, cid_supp = 'Adobe', 'Japan1', 'Adobe-Japan1' +read_cid_font() + + diff --git a/src/ltj-setwidth.lua b/src/ltj-setwidth.lua index 93c7b49..7ce76b0 100644 --- a/src/ltj-setwidth.lua +++ b/src/ltj-setwidth.lua @@ -45,6 +45,8 @@ local attr_jchar_class = luatexbase.attributes['ltj@charclass'] local attr_curjfnt = luatexbase.attributes['ltj@curjfnt'] local attr_yablshift = luatexbase.attributes['ltj@yablshift'] local attr_ykblshift = luatexbase.attributes['ltj@ykblshift'] +local attr_tablshift = luatexbase.attributes['ltj@tablshift'] +local attr_tkblshift = luatexbase.attributes['ltj@tkblshift'] local attr_icflag = luatexbase.attributes['ltj@icflag'] local ltjf_font_metric_table = ltjf.font_metric_table @@ -122,7 +124,7 @@ local function capsule_glyph_tate(p, met, class) setfield(p, 'char', ltjd.get_vert_glyph(getfont(p), getchar(p))) local y_shift - = - getfield(p, 'yoffset') + (has_attr(p,attr_ykblshift) or 0) + = - getfield(p, 'yoffset') + (has_attr(p,attr_tkblshift) or 0) local q head, q = node_remove(head, p) local box = node_new(id_hlist) @@ -182,8 +184,9 @@ luatexja.setwidth.capsule_glyph_math = capsule_glyph_math function luatexja.setwidth.set_ja_width(ahead, adir) local p = ahead; head = p; dir = adir or 'TLT' local m = false -- is in math mode? - local capsule_glyph = (ltjs.table_current_stack[DIR]==dir_yoko) - and capsule_glyph_yoko or capsule_glyph_tate + local is_dir_tate = ltjs.table_current_stack[DIR]==dir_tate + local capsule_glyph = is_dir_tate and capsule_glyph_tate or capsule_glyph_yoko + local attr_ablshift = is_dir_tate and attr_tablshift or attr_yablshift while p do local pid = getid(p) if (pid==id_glyph) @@ -195,7 +198,7 @@ function luatexja.setwidth.set_ja_width(ahead, adir) else set_attr(p, attr_icflag, PROCESSED + get_pr_begin_flag(p)) setfield(p, 'yoffset', - getfield(p, 'yoffset') - (has_attr(p,attr_yablshift) or 0)) + getfield(p, 'yoffset') - (has_attr(p,attr_ablshift) or 0)) p = node_next(p) end elseif pid==id_math then diff --git a/src/luatexja-core.sty b/src/luatexja-core.sty index ebd25c1..07e1adb 100644 --- a/src/luatexja-core.sty +++ b/src/luatexja-core.sty @@ -141,8 +141,10 @@ \newluatexattribute\ltj@charclass % \newluatexattribute\ltj@autospc % attribute for autospacing \newluatexattribute\ltj@autoxspc % attribute for autoxspacing -\newluatexattribute\ltj@yablshift % attribute for \yabaselineshift -\newluatexattribute\ltj@ykblshift % attribute for \ykbaselineshift +\newluatexattribute\ltj@yablshift % attribute for yalbaselineshift +\newluatexattribute\ltj@ykblshift % attribute for yjabaselineshift +\newluatexattribute\ltj@tablshift % attribute for talbaselineshift +\newluatexattribute\ltj@tkblshift % attribute for tjabaselineshift \newluatexattribute\jfam % index for current jfam \newluatexattribute\ltj@dir % temp attr for indicating box direction @@ -294,6 +296,16 @@ \directlua{tex.setattribute(luatexja.isglobal, luatexbase.attributes['ltj@ykblshift'], \ltj@safe@dimen@or\ltj@defdimen{#1})}} +% talbaselineshift = +% tjabaselineshift = +\define@key[ltj]{japaram}{talbaselineshift}{% + \directlua{tex.setattribute(luatexja.isglobal, + luatexbase.attributes['ltj@tablshift'], + \ltj@safe@dimen@or\ltj@defdimen{#1})}} +\define@key[ltj]{japaram}{tjabaselineshift}{% + \directlua{tex.setattribute(luatexja.isglobal, + luatexbase.attributes['ltj@tkblshift'], + \ltj@safe@dimen@or\ltj@defdimen{#1})}} % jaxspmode = {, } % mode: inhibit, preonly, postonly, allow diff --git a/src/luatexja.lua b/src/luatexja.lua index 3332c1e..7737163 100644 --- a/src/luatexja.lua +++ b/src/luatexja.lua @@ -198,6 +198,12 @@ do yjabaselineshift = function(t) return print_scaled(tex.getattribute('ltj@ykblshift'))..'pt' end, + talbaselineshift = function(t) + return print_scaled(tex.getattribute('ltj@tablshift'))..'pt' + end, + tjabaselineshift = function(t) + return print_scaled(tex.getattribute('ltj@tkblshift'))..'pt' + end, kanjiskip = function(t) return print_spec(ltjs.get_stack_skip(stack_table_index.KSK, t)) end, @@ -295,7 +301,8 @@ do local to_node = (Dnode ~= node) and Dnode.tonode or nullfunc local to_direct = (Dnode ~= node) and Dnode.todirect or nullfunc -- mode = true iff main_process is called from pre_linebreak_filter - local function main_process(head, mode, dir) + local function main_process(head, mode, dir, gc) + --print('main_process', gc, mode, tex.getcount('ltj@@stack')) tex.setattribute('global', attr_icflag, 0) local p = to_direct(head) p = ltjj.main(p,mode) @@ -315,14 +322,14 @@ do luatexbase.add_to_callback( 'pre_linebreak_filter', function (head,groupcode) - return main_process(head, true, tex.textdir) + return main_process(head, true, tex.textdir, groupcode) end,'ltj.pre_linebreak_filter', luatexbase.priority_in_callback('pre_linebreak_filter', 'luaotfload.node_processor') + 1) luatexbase.add_to_callback( 'hpack_filter', function (head,groupcode,size,packtype, dir) - return main_process(head, false, dir) + return main_process(head, false, dir, groupcode) end,'ltj.hpack_filter', luatexbase.priority_in_callback('hpack_filter', 'luaotfload.node_processor') + 1) @@ -363,16 +370,15 @@ local function debug_show_node_X(p,print_fn) local pt=node_type(p.id) local base = debug_depth .. string.format('%X', get_attr_icflag(p)) .. ' ' .. pt .. ' ' .. tostring(p.subtype) .. ' ' - .. ' dir=' .. tostring(has_attr(p, attr_dir)) .. ' ' if pt == 'glyph' then s = base .. ' ' .. utf.char(p.char) .. ' ' .. tostring(p.font) .. ' (' .. print_scaled(p.height) .. '+' .. print_scaled(p.depth) .. ')x' .. print_scaled(p.width) print_fn(s) - elseif pt=='hlist' or pt=='vlist' then + elseif pt=='hlist' or pt=='vlist' or pt=='unset' then s = base .. '(' .. print_scaled(p.height) .. '+' .. print_scaled(p.depth) .. ')x' .. print_scaled(p.width) .. p.dir - if p.shift~=0 then + if p.shift or 0~=0 then s = s .. ', shifted ' .. print_scaled(p.shift) end if p.glue_sign >= 1 then @@ -429,7 +435,7 @@ local function debug_show_node_X(p,print_fn) end print_fn(s) elseif pt == 'whatsit' then - s = base + s = base .. '(' .. node.whatsits()[p.subtype] .. ') ' if p.subtype==sid_user then if p.type ~= 110 then s = s .. ' user_id: ' .. p.user_id .. ' ' .. p.value