X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=src%2Fluatexja-core.lua;h=673f581d8f2e198e1df6386b16ae644df2c41d6c;hb=2a89ff80358ba323dd8d07585322e346d320cbbf;hp=a2c43db172c976d32fdeb1e5338551e88b2ec98d;hpb=a0fd185190cb293c9800298a5039ffc909127eaa;p=luatex-ja%2Fluatexja.git diff --git a/src/luatexja-core.lua b/src/luatexja-core.lua index a2c43db..673f581 100644 --- a/src/luatexja-core.lua +++ b/src/luatexja-core.lua @@ -1,3 +1,15 @@ +require('lualibs') +require('luatexja.rmlgbm'); local ltjr = luatexja.rmlgbm -- must be 1st +require('luatexja.base'); local ltjb = luatexja.base +require('luatexja.charrange'); local ltjc = luatexja.charrange +require('luatexja.jfont'); local ltjf = luatexja.jfont +require('luatexja.inputbuf'); local ltji = luatexja.inputbuf +require('luatexja.jfmglue'); local ltjj = luatexja.jfmglue +require('luatexja.math'); local ltjm = luatexja.math +require('luatexja.pretreat'); local ltjp = luatexja.pretreat +require('luatexja.stack'); local ltjs = luatexja.stack +require('luatexja.setwidth'); local ltjw = luatexja.setwidth + local node_type = node.type local node_new = node.new local node_prev = node.prev @@ -6,7 +18,6 @@ local has_attr = node.has_attribute local node_insert_before = node.insert_before local node_insert_after = node.insert_after local node_hpack = node.hpack -local round = tex.round local id_penalty = node.id('penalty') local id_glyph = node.id('glyph') @@ -18,22 +29,24 @@ local id_vlist = node.id('vlist') local id_rule = node.id('rule') local id_math = node.id('math') local id_whatsit = node.id('whatsit') - -local attr_jchar_class = luatexbase.attributes['luatexja@charclass'] -local attr_curjfnt = luatexbase.attributes['luatexja@curjfnt'] -local attr_yablshift = luatexbase.attributes['luatexja@yablshift'] -local attr_ykblshift = luatexbase.attributes['luatexja@ykblshift'] -local attr_icflag = luatexbase.attributes['luatexja@icflag'] --- attr_icflag: 1: kern from \/, 2: 'lineend' kern from JFM - -local lang_ja_token = token.create('luatexja@japanese') -local lang_ja = lang_ja_token[2] - --- -local rgjc_get_range_setting = ltj.int_get_range_setting -local rgjc_char_to_range = ltj.int_char_to_range -local rgjc_is_ucs_in_japanese_char = ltj.int_is_ucs_in_japanese_char -local ljfm_find_char_class = ltj.int_find_char_class +local sid_user = node.subtype('user_defined') + +local attr_jchar_class = luatexbase.attributes['ltj@charclass'] +local attr_curjfnt = luatexbase.attributes['ltj@curjfnt'] +local attr_yablshift = luatexbase.attributes['ltj@yablshift'] +local attr_icflag = luatexbase.attributes['ltj@icflag'] +local cat_lp = luatexbase.catcodetables['latex-package'] + +local ITALIC = 1 +local PACKED = 2 +local KINSOKU = 3 +local FROM_JFM = 4 +local LINE_END = 5 +local KANJI_SKIP = 6 +local XKANJI_SKIP = 7 +local PROCESSED = 8 +local IC_PROCESSED = 9 +local BOXBDD = 15 ------------------------------------------------------------------------ -- naming: @@ -48,7 +61,7 @@ end -- Three aux. functions, bollowed from tex.web local unity=65536 -local function print_scaled(s) +function print_scaled(s) local out='' local delta=10 if s<0 then @@ -89,70 +102,10 @@ local function print_spec(p) return out end --- return true if and only if p is a Japanese character node -local function is_japanese_glyph_node(p) - return p and (p.id==id_glyph) - and (p.font==has_attr(p,attr_curjfnt)) -end - - ------------------------------------------------------------------------- --- CODE FOR STACK TABLE FOR CHARACTER PROPERTIES (prefix: cstb) ------------------------------------------------------------------------- +function math.two_add(a,b) return a+b end +function math.two_average(a,b) return (a+b)/2 end ---- table: charprop_stack_table [stack_level][chr_code].{pre|post|xsp} -local charprop_stack_table={}; charprop_stack_table[0]={} - -local function cstb_get_stack_level() - local i = tex.getcount('ltj@@stack') - if tex.currentgrouplevel > tex.getcount('ltj@@group@level') then - i = i+1 -- new stack level - tex.setcount('ltj@@group@level', tex.currentgrouplevel) - for j,v in pairs(charprop_stack_table) do -- clear the stack above i - if j>=i then charprop_stack_table[j]=nil end - end - charprop_stack_table[i] = table.fastcopy(charprop_stack_table[i-1]) - tex.setcount('ltj@@stack', i) - end - return i -end - --- EXT -function ltj.ext_set_stack_table(g,m,c,p,lb,ub) - local i = cstb_get_stack_level() - if pub then - ltj.error('Invalid code (' .. p .. '), should in the range ' - .. tostring(lb) .. '..' .. tostring(ub) .. '.', - {"I'm going to use 0 instead of that illegal code value."}) - p=0 - elseif c<-1 or c>0x10FFFF then - ltj.error('Invalid character code (' .. p - .. '), should in the range -1.."10FFFF.',{}) - return - elseif not charprop_stack_table[i][c] then - charprop_stack_table[i][c] = {} - end - charprop_stack_table[i][c][m] = p - if g=='global' then - for j,v in pairs(charprop_stack_table) do - if not charprop_stack_table[j][c] then charprop_stack_table[j][c] = {} end - charprop_stack_table[j][c][m] = p - end - end -end - -local function cstb_get_penalty_table(m,c) - local i = charprop_stack_table[tex.getcount('ltj@@stack')][c] - if i then i=i[m] end - return i or 0 -end - -local function cstb_get_inhibit_xsp_table(c) - local i = charprop_stack_table[tex.getcount('ltj@@stack')][c] - if i then i=i.xsp end - return i or 3 -end -ltj.int_get_inhibit_xsp_table = cstb_get_inhibit_xsp_table ------------------------------------------------------------------------ -- CODE FOR GETTING/SETTING PARAMETERS @@ -160,28 +113,28 @@ ltj.int_get_inhibit_xsp_table = cstb_get_inhibit_xsp_table -- EXT: print parameters that don't need arguments function ltj.ext_get_parameter_unary(k) - if k == 'yabaselineshift' then - tex.write(print_scaled(tex.getattribute('luatexja@yablshift'))..'pt') - elseif k == 'ykbaselineshift' then - tex.write(print_scaled(tex.getattribute('luatexja@ykblshift'))..'pt') + if k == 'yalbaselineshift' then + tex.write(print_scaled(tex.getattribute('ltj@yablshift'))..'pt') + elseif k == 'yjabaselineshift' then + tex.write(print_scaled(tex.getattribute('ltj@ykblshift'))..'pt') elseif k == 'kanjiskip' then - tex.write(print_spec(tex.getskip('kanjiskip'))) + tex.write(print_spec(ltjs.get_skip_table('kanjiskip', tex.getcount('ltj@@stack')))) elseif k == 'xkanjiskip' then - tex.write(print_spec(tex.getskip('xkanjiskip'))) + tex.write(print_spec(ltjs.get_skip_table('xkanjiskip', tex.getcount('ltj@@stack')))) elseif k == 'jcharwidowpenalty' then - tex.write(tex.getcount('jcharwidowpenalty')) + tex.write(ltjs.get_penalty_table('jwp', 0, 0, tex.getcount('ltj@@stack'))) elseif k == 'autospacing' then - tex.write(tostring(ltj.auto_spacing)) + tex.write(tex.getattribute('ltj@autospc')) elseif k == 'autoxspacing' then - tex.write(tostring(ltj.auto_xspacing)) + tex.write(tex.getattribute('ltj@autoxspc')) elseif k == 'differentjfm' then - if ltj.calc_between_two_jchar_aux==ltj.calc_between_two_jchar_aux_large then + if luatexja.jfmglue.diffmet_rule == math.max then tex.write('large') - elseif ltj.calc_between_two_jchar_aux==ltj.calc_between_two_jchar_aux_small then + elseif luatexja.jfmglue.diffmet_rule == math.min then tex.write('small') - elseif ltj.calc_between_two_jchar_aux==ltj.calc_between_two_jchar_aux_average then + elseif luatexja.jfmglue.diffmet_rule == math.two_average then tex.write('average') - elseif ltj.calc_between_two_jchar_aux==ltj.calc_between_two_jchar_aux_both then + elseif luatexja.jfmglue.diffmet_rule == math.two_add then tex.write('both') else -- This can't happen. tex.write('???') @@ -191,422 +144,49 @@ end -- EXT: print parameters that need arguments function ltj.ext_get_parameter_binary(k,c) - if k == 'jcharrange' then - if c<0 or c>216 then c=0 end - tex.write(rgjc_get_range_setting(c)) + if k == 'jacharrange' then + if c<0 or c>216 then + ltjb.package_error('luatexja', + 'invalid character range number (' .. c .. ')', + 'A character range number should be in the range 0..216,\n'.. + 'So I changed this one to zero.') + c=0 + end + tex.write(ltjc.get_range_setting(c)) else if c<0 or c>0x10FFFF then - ltj.error('Invalid character code (' .. c - .. '), should in the range 0.."10FFFF.', - {"I'm going to use 0 instead of that illegal character code."}) + ltjb.package_error('luatexja', + 'bad character code (' .. c .. ')', + 'A character number must be between -1 and 0x10ffff.\n'.. + "(-1 is used for denoting `math boundary')\n".. + 'So I changed this one to zero.') c=0 end if k == 'prebreakpenalty' then - tex.write(cstb_get_penalty_table('pre',c)) + tex.write(ltjs.get_penalty_table('pre', c, 0, tex.getcount('ltj@@stack'))) elseif k == 'postbreakpenalty' then - tex.write(cstb_get_penalty_table('post',c)) + tex.write(ltjs.get_penalty_table('post', c, 0, tex.getcount('ltj@@stack'))) elseif k == 'kcatcode' then - tex.write(cstb_get_penalty_table('kcat',c)) + tex.write(ltjs.get_penalty_table('kcat', c, 0, tex.getcount('ltj@@stack'))) elseif k == 'chartorange' then - tex.write(rgjc_char_to_range(c)) - elseif k == 'cjkxspmode' or k == 'asciixspmode' then - tex.write(cstb_get_inhibit_xsp_table(c)) + tex.write(ltjc.char_to_range(c)) + elseif k == 'jaxspmode' or k == 'alxspmode' then + tex.write(ltjs.get_penalty_table('xsp', c, 3, tex.getcount('ltj@@stack'))) end end end -- EXT: print \global if necessary function ltj.ext_print_global() - if ltj.isglobal=='global' then tex.sprint('\\global') end -end - - ------------------------------------------------------------------------- --- MAIN PROCESS STEP 1: replace fonts (prefix: main1) ------------------------------------------------------------------------- - ---- the following function is modified from jafontspec.lua (by K. Maeda). ---- Instead of "%", we use U+FFFFF for suppressing spaces. -local function main1_process_input_buffer(buffer) - local c = utf.byte(buffer, utf.len(buffer)) - local p = node_new(id_glyph) - p.char = c - if utf.len(buffer) > 0 - and rgjc_is_ucs_in_japanese_char(p) then - buffer = buffer .. string.char(0xF3,0xBF,0xBF,0xBF) -- U+FFFFF - end - return buffer -end - -local function main1_suppress_hyphenate_ja(head) - local p - for p in node.traverse(head) do - if p.id == id_glyph then - if rgjc_is_ucs_in_japanese_char(p) then - local v = has_attr(p, attr_curjfnt) - if v then - p.font = v - node.set_attribute(p,attr_jchar_class, - ljfm_find_char_class(p.char, ltj.font_metric_table[v].jfm)) - end - v = has_attr(p, attr_ykblshift) - if v then - node.set_attribute(p, attr_yablshift, v) - else - node.unset_attribute(p, attr_yablshift) - end - p.lang=lang_ja - end - end - end - lang.hyphenate(head) - return head -- 共通化のため値を返す -end - --- CALLBACKS -luatexbase.add_to_callback('process_input_buffer', - function (buffer) - return main1_process_input_buffer(buffer) - end,'ltj.process_input_buffer') -luatexbase.add_to_callback('hpack_filter', - function (head,groupcode,size,packtype) - return main1_suppress_hyphenate_ja(head) - end,'ltj.hpack_filter_pre',0) -luatexbase.add_to_callback('hyphenate', - function (head,tail) - return main1_suppress_hyphenate_ja(head) - end,'ltj.hyphenate') - - ------------------------------------------------------------------------- --- MAIN PROCESS STEP 2: insert glue/kerns from JFM (prefix: main2) ------------------------------------------------------------------------- - --- EXT: for \inhibitglue -function ltj.ext_create_inhibitglue_node() - local g=node_new(id_whatsit, node.subtype('user_defined')) - g.user_id=30111; g.type=number; g.value=1; node.write(g) -end - - -local function main2_find_size_metric(px) - if is_japanese_glyph_node(px) then - return ltj.font_metric_table[px.font].size, ltj.font_metric_table[px.font].jfm - else - return nil, nil - end -end - -local function main2_new_jfm_glue(size,mt,bc,ac) --- mt: metric key, bc, ac: char classes - local g=nil - local w=bc*0x800+ac - local z = ltj.metrics[mt] - if z.glue[w] then - local h = node_new(id_glue_spec) - h.width = round(size*z.glue[w][0]) - h.stretch = round(size*z.glue[w][1]) - h.shrink = round(size*z.glue[w][2]) - h.stretch_order=0; h.shrink_order=0 - g = node_new(id_glue) - g.subtype = 0; g.spec = h - elseif z.kern[w] then - g = node_new(id_kern) - g.subtype = 1; g.kern = round(size*z.kern[w]) - end - return g -end - --- return value: g (glue/kern from JFM), w (width of 'lineend' kern) -local function main2_calc(qs,qm,q,p,last,ihb_flag) - -- q, p: node (possibly null) - local ps, pm, g, h - local w = 0 - if (not p) or p==last then - -- q is the last node - if not qm then - return nil, 0 - elseif not ihb_flag then - g=main2_new_jfm_glue(qs,qm, - has_attr(q,attr_jchar_class), - ljfm_find_char_class('boxbdd',qm)) - end - elseif qs==0 then - -- p is the first node etc. - ps, pm = main2_find_size_metric(p) - if not pm then - return nil, 0 - elseif not ihb_flag then - g=main2_new_jfm_glue(ps,pm, - ljfm_find_char_class('boxbdd',pm), - has_attr(p,attr_jchar_class)) - end - else -- p and q are not nil - ps, pm = main2_find_size_metric(p) - if ihb_flag or ((not pm) and (not qm)) then - g = nil - elseif (qs==ps) and (qm==pm) then - -- Both p and q are Japanese glyph nodes, and same metric and size - g = main2_new_jfm_glue(ps,pm, - has_attr(q,attr_jchar_class), - has_attr(p,attr_jchar_class)) - elseif not qm then - -- q is not a Japanese glyph node - g = main2_new_jfm_glue(ps,pm, - ljfm_find_char_class('jcharbdd',pm), - has_attr(p,attr_jchar_class)) - elseif not pm then - -- p is not a Japanese glyph node - g = main2_new_jfm_glue(qs,qm, - has_attr(q,attr_jchar_class), - ljfm_find_char_class('jcharbdd',qm)) - else - g = main2_new_jfm_glue(qs,qm, - has_attr(q,attr_jchar_class), - ljfm_find_char_class('diffmet',qm)) - h = main2_new_jfm_glue(ps,pm, - ljfm_find_char_class('diffmet',pm), - has_attr(p,attr_jchar_class)) - g = ltj.calc_between_two_jchar_aux(g,h) - end - end - if g then node.set_attribute(g, attr_icflag, 3) end - if qm then - local x = ljfm_find_char_class('lineend', qm) - if x~=0 then - x = has_attr(q,attr_jchar_class)*0x800 + x - if ltj.metrics[qm].kern[x] then - w = round(qs*ltj.metrics[qm].kern[x]) - end - end - end - - return g, w -end - -local function main2_between_two_char(head,q,p,p_bp,ihb_flag,last) - local qs = 0; local g, w - local qm = nil - if q then - qs, qm = main2_find_size_metric(q) - end - g, w = main2_calc(qs, qm, q, p, last, ihb_flag) - if w~=0 and (not p_bp) then - p_bp = node_new(id_penalty); p_bp.penalty = 0 - head = node_insert_before(head, p, p_bp) - end - if g then - if g.id==id_kern then - g.kern = round(g.kern - w) - else - g.spec.width = round(g.spec.width - w) - end - head = node_insert_before(head, p, g) - elseif w~=0 then - g = node_new(id_kern); g.kern = -w; g.subtype = 1 - node.set_attribute(g,attr_icflag,2) - head = node_insert_before(head, p, g) - -- this g might be replaced by \[x]kanjiskip in step 3. - end - if w~=0 then - g = node_new(id_kern); g.kern = w; g.subtype = 0 - head = node_insert_before(head, p_bp, g) - end -return head, p_bp -end - --- In the beginning of a hlist created by line breaking, there are the followings: --- - a hbox by \parindent --- - a whatsit node which contains local paragraph materials. --- When we insert jfm glues, we ignore these nodes. -local function main2_is_parindent_box(p) - if p.id==id_hlist then - return (p.subtype==3) - -- hlist (subtype=3) is a box by \parindent - elseif p.id==id_whatsit then - return (p.subtype==node.subtype('local_par')) - end -end - --- next three functions deal with inserting penalty by kinsoku. -local function main2_add_penalty_before(head,p,p_bp,pen) - if p_bp then - p_bp.penalty = p_bp.penalty + pen - else -- we must create a new penalty node - local g = node_new(id_penalty); g.penalty = pen - local q = node_prev(p) - if q then - if has_attr(q, attr_icflag) ~= 3 then - q = p - end - return node_insert_before(head, q, g) - end - end - return head -end - -local function main2_add_kinsoku_penalty(head,p,p_bp) - local c = p.char - local e = cstb_get_penalty_table('pre',c) - if e~=0 then - head = main2_add_penalty_before(head, p, p_bp, e) - end - e = cstb_get_penalty_table('post',c) - if e~=0 then - local q = node_next(p) - if q and q.id==id_penalty then - q.penalty = q.penalty + e - return false - else - q = node_new(id_penalty); q.penalty = e - node_insert_after(head,p,q) - return true - end - end -end - -local function main2_add_widow_penalty(head,widow_node,widow_bp) - if not widow_node then - return head - else - return main2_add_penalty_before(head, widow_node, - widow_bp, tex.getcount('jcharwidowpenalty')) - end -end - -local depth="" - --- Insert jfm glue: main routine --- mode = true iff insert_jfm_glue is called from pre_linebreak_filter -local function main2_insert_jfm_glue(head, mode) - local p = head - local p_bp = nil -- p と直前の文字の間の penalty node - local q = nil -- the previous node of p - local widow_node = nil -- 最後の「句読点扱いでない」和文文字 - local widow_bp = nil -- \jcharwidowpenalty 挿入位置 - local last -- the sentinel - local ihb_flag = false -- is \inhibitglue specified? - local g - -- initialization - if not p then return head - elseif mode then - while p and main2_is_parindent_box(p) do p=node_next(p) end - last=node.tail(head) - if last and last.id==id_glue and last.subtype==15 then - last=node.prev(last) - while (last and last.id==id_penalty) do last=node.prev(last) end - end - if last then last=node_next(last) end - else -- 番人を挿入 - last=node.tail(head); g = node_new('kern') - node_insert_after(head,last,g); last = g - end - -- main loop - while q~=last do - if p.id==id_whatsit and p.subtype==node.subtype('user_defined') - and p.user_id==30111 then - g = p; p = node_next(p) - ihb_flag = true; head, p = node.remove(head, g) - else - head, p_bp = main2_between_two_char(head, q, p, p_bp, ihb_flag, last) - q=p; ihb_flag=false - if is_japanese_glyph_node(p) then - if cstb_get_penalty_table('kcat',p.char)%2~=1 then - widow_node = p; widow_bp = p_bp - end - if main2_add_kinsoku_penalty(head, p, p_bp) then - p_bp = node_next(p); p = p_bp - else p_bp = nil - end - else p_bp = nil - end - p=node_next(p) - end - end - if mode then - -- Insert \jcharwidowpenalty - head = main2_add_widow_penalty(head, widow_node, widow_bp) - -- cleanup - p = node_prev(last) - if p and p.id==id_kern and has_attr(p,attr_icflag)==2 then - head = node.remove(head, p) - end - else - head = node.remove(head, last) - end - return head -end - - ------------------------------------------------------------------------- --- MAIN PROCESS STEP 4: width of japanese chars (prefix: main4) ------------------------------------------------------------------------- - --- TeX's \hss -local function main4_get_hss() - local hss = node_new(id_glue) - local fil_spec = node_new(id_glue_spec) - fil_spec.width = 0 - fil_spec.stretch = 65536 - fil_spec.stretch_order = 2 - fil_spec.shrink = 65536 - fil_spec.shrink_order = 2 - hss.spec = fil_spec - return hss -end - -local function main4_set_ja_width(head) - local p = head - local met_tb, t, s, g, th, q, a - local m = false -- is in math mode? - while p do - local v=has_attr(p,attr_yablshift) or 0 - if p.id==id_glyph then - p.yoffset = p.yoffset-v - if is_japanese_glyph_node(p) then - met_tb = ltj.font_metric_table[p.font] - t = ltj.metrics[met_tb.jfm] - s = t.char_type[has_attr(p,attr_jchar_class)] - if not(s.left==0.0 and s.down==0.0 - and round(s.width*met_tb.size)==p.width) then - -- must be encapsuled by a \hbox - head, q = node.remove(head,p) - p.next=nil - p.yoffset=round(p.yoffset-met_tb.size*s.down) - p.xoffset=round(p.xoffset-met_tb.size*s.left) - node_insert_after(p, p, main4_get_hss()) - g = node_hpack(p, round(met_tb.size*s.width), 'exactly') - g.height = round(met_tb.size*s.height) - g.depth = round(met_tb.size*s.depth) - head, p = node_insert_before(head, q, g) - p = q - else p=node_next(p) - end - else p=node_next(p) - end - elseif p.id==id_math then - m=(p.subtype==0); p=node_next(p) - else - if m then - if p.id==id_hlist or p.id==id_vlist then - p.shift=p.shift+v - elseif p.id==id_rule then - p.height=p.height-v; p.depth=p.depth+v - end - end - p=node_next(p) - end - end -return head + if ltj.isglobal=='global' then tex.sprint(cat_lp, '\\global') end end -- main process -- mode = true iff main_process is called from pre_linebreak_filter -local function main_process(head, mode) +local function main_process(head, mode, dir) local p = head - p = main2_insert_jfm_glue(p,mode) - p = ltj.int_insert_kanji_skip(p) - p = main4_set_ja_width(p) + p = ltjj.main(p,mode) + p = ltjw.set_ja_width(p, dir) return p end @@ -616,47 +196,136 @@ local debug_depth function ltj.ext_show_node_list(head,depth,print_fn) debug_depth = depth if head then - debug_show_node_list_X(head, print_fn) + while head do + debug_show_node_X(head, print_fn); head = node_next(head) + end else print_fn(debug_depth .. ' (null list)') end end -function debug_show_node_list_X(p,print_fn) - debug_depth=debug_depth.. '.' +function ltj.ext_show_node(head,depth,print_fn) + debug_depth = depth + if head then + debug_show_node_X(head, print_fn) + else + print_fn(debug_depth .. ' (null list)') + end +end +function debug_show_node_X(p,print_fn) local k = debug_depth - while p do - local pt=node_type(p.id) - if pt == 'glyph' then - print_fn(debug_depth.. ' glyph ', p.subtype, utf.char(p.char), p.font) - elseif pt=='hlist' then - print_fn(debug_depth.. ' hlist ', p.subtype, '(' .. print_scaled(p.height) - .. '+' .. print_scaled(p.depth) - .. ')x' .. print_scaled(p.width) ) - debug_show_node_list_X(p.head,print_fn) - debug_depth=k - elseif pt == 'whatsit' then - print_fn(debug_depth.. ' whatsit', p.subtype) - elseif pt == 'glue' then - print_fn(debug_depth.. ' glue ', p.subtype, print_spec(p.spec)) - elseif pt == 'kern' then - print_fn(debug_depth.. ' kern ', p.subtype, print_scaled(p.kern) .. 'pt') - elseif pt == 'penalty' then - print_fn(debug_depth.. ' penalty', p.penalty) + local s + local pt=node_type(p.id) + local base = debug_depth .. string.format('%X', has_attr(p,attr_icflag) or 0) + .. ' ' .. pt .. ' ' .. tostring(p.subtype ) + 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' then + s = base .. '(' .. print_scaled(p.height) .. '+' + .. print_scaled(p.depth) .. ')x' .. print_scaled(p.width) + if p.shift~=0 then + s = s .. ', shifted ' .. print_scaled(p.shift) + end + if p.glue_sign >= 1 then + s = s .. ' glue set ' + if p.glue_sign == 2 then s = s .. '-' end + s = s .. tostring(math.floor(p.glue_set*10000)/10000) + if p.glue_order == 0 then + s = s .. 'pt' + else + s = s .. 'fi' + for i = 2, p.glue_order do s = s .. 'l' end + end + end + if has_attr(p, attr_icflag, PACKED) then + s = s .. ' (packed)' + end + print_fn(s) + local q = p.head + debug_depth=debug_depth.. '.' + while q do + debug_show_node_X(q, print_fn); q = node_next(q) + end + debug_depth=k + elseif pt == 'glue' then + s = base .. ' ' .. print_spec(p.spec) + if has_attr(p, attr_icflag)==FROM_JFM then + s = s .. ' (from JFM)' + elseif has_attr(p, attr_icflag)==KANJI_SKIP then + s = s .. ' (kanjiskip)' + elseif has_attr(p, attr_icflag)==XKANJI_SKIP then + s = s .. ' (xkanjiskip)' + end + print_fn(s) + elseif pt == 'kern' then + s = base .. ' ' .. print_scaled(p.kern) .. 'pt' + if p.subtype==2 then + s = s .. ' (for accent)' + elseif has_attr(p, attr_icflag)==IC_PROCESSED then + s = s .. ' (italic correction)' + -- elseif has_attr(p, attr_icflag)==ITALIC then + -- s = s .. ' (italic correction)' + elseif has_attr(p, attr_icflag)==FROM_JFM then + s = s .. ' (from JFM)' + elseif has_attr(p, attr_icflag)==LINE_END then + s = s .. " (from 'lineend' in JFM)" + end + print_fn(s) + elseif pt == 'penalty' then + s = base .. ' ' .. tostring(p.penalty) + if has_attr(p, attr_icflag)==KINSOKU then + s = s .. ' (for kinsoku)' + end + print_fn(s) + elseif pt == 'whatsit' then + s = base .. ' subtype: ' .. tostring(p.subtype) + if p.subtype==sid_user then + s = s .. ' user_id: ' .. p.user_id .. ' ' .. p.value else - print_fn(debug_depth.. ' ' .. node.type(p.id), p.subtype) + s = s .. node.subtype(p.subtype) + end + print_fn(s) + -------- math node -------- + elseif pt=='noad' then + s = base ; print_fn(s) + if p.nucleus then + debug_depth = k .. 'N'; debug_show_node_X(p.nucleus, print_fn); + end + if p.sup then + debug_depth = k .. '^'; debug_show_node_X(p.sup, print_fn); + end + if p.sub then + debug_depth = k .. '_'; debug_show_node_X(p.sub, print_fn); end - p=node_next(p) + debug_depth = k; + elseif pt=='math_char' then + s = base .. ' fam: ' .. p.fam .. ' , char = ' .. utf.char(p.char) + print_fn(s) + elseif pt=='sub_box' then + print_fn(base) + if p.head then + debug_depth = k .. '.'; debug_show_node_X(p.head, print_fn); + end + else + print_fn(base) end + p=node_next(p) end - -- callbacks + luatexbase.add_to_callback('pre_linebreak_filter', function (head,groupcode) - return main_process(head, true) - end,'ltj.pre_linebreak_filter',2) + return main_process(head, true, tex.textdir) + end,'ltj.pre_linebreak_filter', + luatexbase.priority_in_callback('pre_linebreak_filter', + 'luaotfload.pre_linebreak_filter') + 1) luatexbase.add_to_callback('hpack_filter', - function (head,groupcode,size,packtype) - return main_process(head, false) - end,'ltj.hpack_filter',2) + function (head,groupcode,size,packtype, dir) + return main_process(head, false, dir) + end,'ltj.hpack_filter', + luatexbase.priority_in_callback('hpack_filter', + 'luaotfload.hpack_filter') + 1)