X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=src%2Fltj-setwidth.lua;h=acbe7543ee19d6642bb005711f2faa02b92e3ac9;hb=eb118f3e5ea0852407b5261817700401699528b9;hp=33ee822267d4cce368c560c023427fa5f688f028;hpb=ca6676906e752933ba79cd19bb87d3f877eb75eb;p=luatex-ja%2Fluatexja.git diff --git a/src/ltj-setwidth.lua b/src/ltj-setwidth.lua index 33ee822..acbe754 100644 --- a/src/ltj-setwidth.lua +++ b/src/ltj-setwidth.lua @@ -46,15 +46,14 @@ local attr_tkblshift = luatexbase.attributes['ltj@tkblshift'] local attr_icflag = luatexbase.attributes['ltj@icflag'] local ltjf_font_metric_table = ltjf.font_metric_table -local ltjf_get_vert_glyph = ltjf.get_vert_glyph +local ltjf_font_extra_info = ltjf.font_extra_info local PACKED = luatexja.icflag_table.PACKED 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 PROCESSED_BEGIN_FLAG = luatexja.icflag_table.PROCESSED_BEGIN_FLAG local floor = math.floor get_pr_begin_flag = function (p) local i = has_attr(p, attr_icflag) or 0 @@ -66,91 +65,97 @@ local ltjw = {} --export luatexja.setwidth = ltjw luatexbase.create_callback("luatexja.set_width", "data", - function (fstable, fmtable, jchar_class) + function (fstable, fmtable, char_data) return fstable end) local call_callback = luatexbase.call_callback local fshift = { down = 0, left = 0} -local min = math.min -local function capsule_glyph_yoko(p, met, class, head, dir) - local char_data = met.char_type[class] +local min, max = math.min, math.max + +-- 和文文字の位置補正(横) +local function capsule_glyph_yoko(p, met, char_data, head, dir) if not char_data then return node_next(p), head, p end - -- f*: whd specified in JFM - 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 = call_callback("luatexja.set_width", fshift, met, class) - local fheight, fdepth = char_data.height, char_data.depth + fshift = call_callback("luatexja.set_width", fshift, met, char_data) local kbl = has_attr(p, attr_ykblshift) or 0 - -- - local need_hbox + -- + -- f*: whd specified in JFM + local fwidth, pwidth = char_data.width, getfield(p, 'width') + fwidth = fwidth or pwidth + local fheight, pheight = char_data.height, getfield(p, 'height') + fheight = fheight or pheight + local fdepth, pdepth = char_data.depth,getfield(p, 'depth') + fdepth = fdepth or pdepth if pwidth==fwidth then -- 補正後glyph node は ht: p.height - kbl - down, dp: p.depth + min(0, kbl+down) を持つ -- 設定されるべき寸法: ht: fheight - kbl, dp: fdepth + kbl - local ht_diff = fheight + fshift.down - getfield(p, 'height') - local dp_diff = fdepth + kbl - getfield(p, 'depth') - min(kbl + fshift.down, 0) - if ht_diff == 0 and dp_diff ==0 then -- offset only + local ht_diff = fheight + fshift.down - pheight + local dp_diff = fdepth + kbl - pdepth - min(kbl + fshift.down, 0) + if ht_diff == 0 and dp_diff ==0 then -- offset only set_attr(p, attr_icflag, PROCESSED) setfield(p, 'xoffset', getfield(p, 'xoffset') - fshift.left) - setfield(p, 'yoffset', - kbl - fshift.down) + setfield(p, 'yoffset', getfield(p, 'yoffset') - kbl - fshift.down) return node_next(p), head, p elseif ht_diff >= 0 and dp_diff >=0 then -- rule local box = node_new(id_rule) - setfield(p, 'yoffset', - kbl - fshift.down) + setfield(p, 'yoffset', getfield(p, 'yoffset') - kbl - fshift.down) setfield(box, 'width', 0) setfield(box, 'height', fheight - kbl) setfield(box, 'depth', fdepth + kbl) setfield(box, 'dir', dir) set_attr(box, attr_icflag, PACKED) - set_attr(p, attr_icflag, PACKED) + --set_attr(p, attr_icflag, PACKED) head = p and node_insert_before(head, p, box) or node_insert_after(head, node_tail(head), box) return node_next(p), head, p, box - else - need_hbox = true end - else - need_hbox = true end - if need_hbox then - local q - head, q = node_remove(head, p) - setfield(p, 'yoffset', -fshift.down); setfield(p, 'next', nil) - setfield(p, 'xoffset', getfield(p, 'xoffset') - + char_data.align*(fwidth-pwidth) - fshift.left) - local box = node_new(id_hlist) - setfield(box, 'width', fwidth) - setfield(box, 'height', fheight) - setfield(box, 'depth', fdepth) - setfield(box, 'head', p) - setfield(box, 'shift', kbl) - setfield(box, 'dir', dir) - set_attr(box, attr_icflag, PACKED) - head = q and node_insert_before(head, q, box) - or node_insert_after(head, node_tail(head), box) - return q, head, box - end + local q + head, q = node_remove(head, p) + setfield(p, 'yoffset', getfield(p, 'yoffset') -fshift.down); + setfield(p, 'next', nil) + setfield(p, 'xoffset', getfield(p, 'xoffset') + + char_data.align*(fwidth-pwidth) - fshift.left) + local box = node_new(id_hlist) + setfield(box, 'width', fwidth) + setfield(box, 'height', fheight) + setfield(box, 'depth', fdepth) + setfield(box, 'head', p) + setfield(box, 'shift', kbl) + setfield(box, 'dir', dir) + set_attr(box, attr_icflag, PACKED) + head = q and node_insert_before(head, q, box) + or node_insert_after(head, node_tail(head), box) + return q, head, box end luatexja.setwidth.capsule_glyph_yoko = capsule_glyph_yoko -local function capsule_glyph_tate(p, met, class, head, dir) - local char_data = met.char_type[class] +-- 和文文字の位置補正(縦) +local function capsule_glyph_tate(p, met, char_data, head, dir) if not char_data then return node_next(p), head end local ascent, descent = met.ascent, met.descent - local fwidth, pwidth = char_data.width, ascent + descent - fwidth = (fwidth ~= 'prop') and fwidth or pwidth + local fwidth, pwidth = char_data.width + do + local pf = getfont(p) + local pc = getchar(p) + setfield(p, 'char', pc) + pwidth = ltjf_font_extra_info[pf] and ltjf_font_extra_info[pf][pc] + and ltjf_font_extra_info[pf][pc].vwidth + and ltjf_font_extra_info[pf][pc].vwidth * met.size or (ascent+descent) + pwidth = pwidth + (met.v_advance[pc] or 0) + ascent = met.v_origin[pc] and ascent - met.v_origin[pc] or ascent + end + fwidth = fwidth or pwidth fshift.down = char_data.down; fshift.left = char_data.left - fshift = call_callback("luatexja.set_width", fshift, met, class) - local fheight, fdepth = char_data.height, char_data.depth - - setfield(p, 'char', ltjf_get_vert_glyph(getfont(p), getchar(p))) - + fshift = call_callback("luatexja.set_width", fshift, met, char_data) + local fheight = char_data.height or 0 + local fdepth = char_data.depth or 0 local y_shift - = - getfield(p, 'yoffset') + (has_attr(p,attr_tkblshift) or 0) + = getfield(p, 'xoffset') + (has_attr(p,attr_tkblshift) or 0) local q head, q = node_remove(head, p) local box = node_new(id_hlist) @@ -160,15 +165,15 @@ local function capsule_glyph_tate(p, met, class, head, dir) setfield(box, 'shift', y_shift) setfield(box, 'dir', dir) - setfield(p, 'xoffset', -fshift.down) - setfield(p, 'yoffset', - (getfield(p, 'xoffset') + ascent + setfield(p, 'xoffset', - fshift.down) + setfield(p, 'yoffset', getfield(p, 'yoffset') -(ascent + char_data.align*(fwidth-pwidth) - fshift.left) ) local ws = node_new(id_whatsit, sid_save) local wm = node_new(id_whatsit, sid_matrix) setfield(wm, 'data', '0 1 -1 0') - local pwnh = - 0.5*getfield(p, 'width') - local k2 = node_new(id_kern); setfield(k2, 'kern', - 0.5*getfield(p, 'width')) - local k3 = node_copy(k2) + local pwnh = -round(0.5*getfield(p, 'width')) + local k2 = node_new(id_kern); setfield(k2, 'kern', pwnh) + local k3 = node_new(id_kern); setfield(k3, 'kern', -getfield(p, 'width')-pwnh) local wr = node_new(id_whatsit, sid_restore) setfield(box, 'head', ws) setfield(ws, 'next', wm); setfield(wm, 'next', k2); @@ -182,16 +187,15 @@ local function capsule_glyph_tate(p, met, class, head, dir) end luatexja.setwidth.capsule_glyph_tate = capsule_glyph_tate -local function capsule_glyph_math(p, met, class) - local char_data = met.char_type[class] +local function capsule_glyph_math(p, met, char_data) if not char_data then return nil end 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 = call_callback("luatexja.set_width", fshift, met, class) + fshift = call_callback("luatexja.set_width", fshift, met, char_data) local fheight, fdepth = char_data.height, char_data.depth - local y_shift, ca - = - getfield(p, 'yoffset') + (has_attr(p,attr_ykblshift) or 0), char_data.align + local y_shift + = - getfield(p, 'yoffset') + (has_attr(p,attr_ykblshift) or 0) setfield(p, 'yoffset', -fshift.down) setfield(p, 'xoffset', getfield(p, 'xoffset') + char_data.align*(fwidth-pwidth) - fshift.left) local box = node_new(id_hlist); @@ -210,7 +214,7 @@ luatexja.setwidth.capsule_glyph_math = capsule_glyph_math function luatexja.setwidth.apply_ashift_math(head, last, attr_ablshift) for p in node_traverse(head) do local pid = getid(p) - if p==last then + if p==last then return elseif (has_attr(p, attr_icflag) or 0) ~= PROCESSED then if pid==id_hlist or pid==id_vlist then @@ -229,3 +233,40 @@ function luatexja.setwidth.apply_ashift_math(head, last, attr_ablshift) end end end + +-- discretionary の位置補正 +do + local attr_yablshift = luatexbase.attributes['ltj@yablshift'] + local attr_tablshift = luatexbase.attributes['ltj@tablshift'] + local attr_ablshift + local disc, tex_dir + local function ashift_disc_inner(field) + local head = getfield(disc, field) + if not head then return end + local y_adjust, node_depth, adj_depth = 0, 0, 0 + for lp in node_traverse_id(id_glyph, head) do + y_adjust = has_attr(lp,attr_ablshift) or 0 + node_depth = max(getfield(lp, 'depth') + min(y_adjust, 0), node_depth) + adj_depth = (y_adjust>0) and max(getfield(lp, 'depth') + y_adjust, adj_depth) or adj_depth + setfield(lp, 'yoffset', getfield(lp, 'yoffset') - y_adjust) + end + if adj_depth>node_depth then + local r = node_new(id_rule) + setfield(r, 'width', 0); setfield(r, 'height', 0) + setfield(r, 'depth', adj_depth); setfield(r, 'dir', tex_dir) + set_attr(r, attr_icflag, PROCESSED) + if field=='post' then + node_insert_after(head, head, r) + else + setfield(disc, field, (node_insert_before(head, head, r))) + end + end + end + function luatexja.setwidth.apply_ashift_disc(d, is_dir_tate, dir) + attr_ablshift = is_dir_tate and attr_tablshift or attr_yablshift + disc, tex_dir = d, dir + ashift_disc_inner('pre') + ashift_disc_inner('post') + ashift_disc_inner('replace') + end +end