+++ /dev/null
-
--- gb: 前側の和文文字 b 由来の glue/kern (maybe nil)
--- ga: 後側の和文文字 a 由来の glue/kern (maybe nil)
--- 両者から,b と a の間に入る glue/kern を計算する
-
-function ltj.calc_between_two_jchar_aux_large(gb,ga)
- if not gb then
- return ga
- else
- if not ga then return gb end
- local k = node.type(gb.id) .. node.type(ga.id)
- if k == 'glueglue' then
- -- 両方とも glue.大きい方をとる
- gb.spec.width = math.max(gb.spec.width,ga.spec.width)
- gb.spec.stretch = math.max(gb.spec.stretch,ga.spec.shrink)
- gb.spec.shrink = math.min(gb.spec.shrink,ga.spec.shrink)
- return gb
- elseif k == 'kernkern' then
- -- 両方とも kern.
- gb.kern = math.max(gb.kern,ga.kern)
- return gb
- elseif k == 'kernglue' then
- -- gb: kern, ga: glue
- ga.spec.width = math.max(gb.kern,ga.spec.width)
- ga.spec.stretch = math.max(ga.spec.stretch,0)
- ga.spec.shrink = math.min(ga.spec.shrink,0)
- return ga
- else
- -- gb: glue, ga: kern
- gb.spec.width = math.max(ga.kern,gb.spec.width)
- gb.spec.stretch = math.max(gb.spec.stretch,0)
- gb.spec.shrink = math.min(gb.spec.shrink,0)
- return gb
- end
- end
-end
-function ltj.calc_between_two_jchar_aux_small(gb,ga)
- if not gb then
- return ga
- else
- if not ga then return gb end
- local k = node.type(gb.id) .. node.type(ga.id)
- if k == 'glueglue' then
- -- 両方とも glue.大きい方をとる
- gb.spec.width = math.min(gb.spec.width,ga.spec.width)
- gb.spec.stretch = math.min(gb.spec.stretch,ga.spec.shrink)
- gb.spec.shrink = math.max(gb.spec.shrink,ga.spec.shrink)
- return gb
- elseif k == 'kernkern' then
- -- 両方とも kern.
- gb.kern = math.min(gb.kern,ga.kern)
- return gb
- elseif k == 'kernglue' then
- -- gb: kern, ga: glue
- ga.spec.width = math.min(gb.kern,ga.spec.width)
- ga.spec.stretch = math.min(ga.spec.stretch,0)
- ga.spec.shrink = math.max(ga.spec.shrink,0)
- return ga
- else
- -- gb: glue, ga: kern
- gb.spec.width = math.min(ga.kern,gb.spec.width)
- gb.spec.stretch = math.min(gb.spec.stretch,0)
- gb.spec.shrink = math.max(gb.spec.shrink,0)
- return gb
- end
- end
-end
-function ltj.calc_between_two_jchar_aux_average(gb,ga)
- if not gb then
- return ga
- else
- if not ga then return gb end
- local k = node.type(gb.id) .. node.type(ga.id)
- if k == 'glueglue' then
- -- 両方とも glue.平均をとる
- gb.spec.width = tex.round((gb.spec.width+ga.spec.width)/2)
- gb.spec.stretch = tex.round((gb.spec.stretch+ga.spec.shrink)/2)
- gb.spec.shrink = tex.round((gb.spec.shrink+ga.spec.shrink)/2)
- return gb
- elseif k == 'kernkern' then
- -- 両方とも kern.平均をとる
- gb.kern = tex.round((gb.kern+ga.kern)/2)
- return gb
- elseif k == 'kernglue' then
- -- gb: kern, ga: glue
- ga.spec.width = tex.round((gb.kern+ga.spec.width)/2)
- ga.spec.stretch = tex.round(ga.spec.stretch/2)
- ga.spec.shrink = tex.round(ga.spec.shrink/2)
- return ga
- else
- -- gb: glue, ga: kern
- gb.spec.width = tex.round((ga.kern+gb.spec.width)/2)
- gb.spec.stretch = tex.round(gb.spec.stretch/2)
- gb.spec.shrink = tex.round(gb.spec.shrink/2)
- return gb
- end
- end
-end
-function ltj.calc_between_two_jchar_aux_both(gb,ga)
- if not gb then
- return ga
- else
- if not ga then return gb end
- local k = node.type(gb.id) .. node.type(ga.id)
- if k == 'glueglue' then
- gb.spec.width = tex.round((gb.spec.width+ga.spec.width))
- gb.spec.stretch = tex.round((gb.spec.stretch+ga.spec.shrink))
- gb.spec.shrink = tex.round((gb.spec.shrink+ga.spec.shrink))
- return gb
- elseif k == 'kernkern' then
- gb.kern = tex.round((gb.kern+ga.kern))
- return gb
- elseif k == 'kernglue' then
- -- gb: kern, ga: glue
- ga.spec.width = tex.round((gb.kern+ga.spec.width))
- return ga
- else
- -- gb: glue, ga: kern
- gb.spec.width = tex.round((ga.kern+gb.spec.width))
- return gb
- end
- end
-end
-
-ltj.calc_between_two_jchar_aux=ltj.calc_between_two_jchar_aux_average
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 ITALIC = 1
+local TEMPORARY = 2
+local FROM_JFM = 3
+local KINSOKU = 4
+local LINE_END = 5
+
------------------------------------------------------------------------
-- naming:
-- ltj.ext_... : called from \directlua{}
and (p.font==has_attr(p,attr_curjfnt))
end
+function math.two_add(a,b) return a+b end
+function math.two_average(a,b) return (a+b)/2 end
------------------------------------------------------------------------
-- CODE FOR STACK TABLE FOR CHARACTER PROPERTIES (prefix: cstb)
{"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
+ ltj.error('Invalid character code (' .. c
.. '), should in the range -1.."10FFFF.',{})
return
elseif not charprop_stack_table[i][c] then
if i then i=i[m] end
return i or 0
end
+ltj.int_get_penalty_table = cstb_get_penalty_table
local function cstb_get_inhibit_xsp_table(c)
local i = charprop_stack_table[tex.getcount('ltj@@stack')][c]
elseif k == 'jcharwidowpenalty' then
tex.write(tex.getcount('jcharwidowpenalty'))
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 ltj.ja_diffmet_rule == math.max then
tex.write('large')
- elseif ltj.calc_between_two_jchar_aux==ltj.calc_between_two_jchar_aux_small then
+ elseif ltj.ja_diffmet_rule == math.min then
tex.write('small')
- elseif ltj.calc_between_two_jchar_aux==ltj.calc_between_two_jchar_aux_average then
+ elseif ltj.ja_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 ltj.ja_diffmet_rule == math.two_add then
tex.write('both')
else -- This can't happen.
tex.write('???')
end
end
lang.hyphenate(head)
- return head -- 共通化のため値を返す
+ return head -- 互換性のために値を返す
end
-- CALLBACKS
------------------------------------------------------------------------
--- 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, ltj.font_metric_table[px.font].var
- else
- return nil, 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 z = ltj.metrics[mt].char_type[bc]
- if z.glue and z.glue[ac] then
- local h = node_new(id_glue_spec)
- h.width = round(size*z.glue[ac][1])
- h.stretch = round(size*z.glue[ac][2])
- h.shrink = round(size*z.glue[ac][3])
- h.stretch_order=0; h.shrink_order=0
- g = node_new(id_glue)
- g.subtype = 0; g.spec = h
- elseif z.kern and z.kern[ac] then
- g = node_new(id_kern)
- g.subtype = 1; g.kern = round(size*z.kern[ac])
- end
- return g
-end
-
--- return value: g (glue/kern from JFM), w (width of 'lineend' kern)
-local function main2_calc(qs,qm,qv,q,p,last,ihb_flag)
- -- q, p: node (possibly null)
- local ps, pm, pv, 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, pv = 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, pv = main2_find_size_metric(p)
- if ihb_flag or ((not pm) and (not qm)) then
- g = nil
- elseif (qs==ps) and (qm==pm) and (qv==pv) 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
- qv = ltj.metrics[qm].char_type[has_attr(q,attr_jchar_class)]
- if qv.kern and qv.kern[x] then
- w = round(qs*qv.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, qv
- if q then
- qs, qm, qv = main2_find_size_metric(q)
- end
- g, w = main2_calc(qs, qm, qv, 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)
------------------------------------------------------------------------
-- mode = true iff main_process is called from pre_linebreak_filter
local function main_process(head, mode)
local p = head
- p = main2_insert_jfm_glue(p,mode)
- p = ltj.int_insert_kanji_skip(p)
+ p = ltj.int_insert_jfm_glue(p,mode)
+ p = ltj.int_insert_kanji_skip(p)
+ -- off because we write the code of step 2
p = main4_set_ja_width(p)
return p
end
function debug_show_node_list_X(p,print_fn)
debug_depth=debug_depth.. '.'
local k = debug_depth
+ local s
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)
+ 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)
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))
+ s = debug_depth.. ' glue ' .. p.subtype
+ .. ' ' .. print_spec(p.spec)
+ if has_attr(p, attr_icflag)==2 then
+ s = s .. ' (might be replaced)'
+ elseif has_attr(p, attr_icflag)==3 then
+ s = s .. ' (from JFM)'
+ end
+ print_fn(s)
elseif pt == 'kern' then
- print_fn(debug_depth.. ' kern ', p.subtype, print_scaled(p.kern) .. 'pt')
+ s = debug_depth.. ' kern ' .. p.subtype
+ .. ' ' .. print_scaled(p.kern) .. 'pt'
+ if has_attr(p, attr_icflag)==ITALIC then
+ s = s .. ' (italic correction)'
+ elseif has_attr(p, attr_icflag)==TEMPORARY then
+ s = s .. ' (might be replaced)'
+ 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
- print_fn(debug_depth.. ' penalty', p.penalty)
+ s = debug_depth.. ' penalty ' .. tostring(p.penalty)
+ if has_attr(p, attr_icflag)==KINSOKU then
+ s = s .. ' (for kinsoku)'
+ end
+ print_fn(s)
else
print_fn(debug_depth.. ' ' .. node.type(p.id), p.subtype)
end
end
-
-- callbacks
luatexbase.add_to_callback('pre_linebreak_filter',
function (head,groupcode)
\newluatexattribute\ltj@charclass %
\newluatexattribute\ltj@yablshift % attribute for \yabaselineshift
\newluatexattribute\ltj@ykblshift % attribute for \ykbaselineshift
+\newluatexattribute\ltj@autospc % attribute for autospacing
+\newluatexattribute\ltj@autoxspc % attribute for autoxspacing
\newluatexattribute\ltj@icflag % attribute for italic correction
\newlanguage\ltj@japanese
% For Ryumin-Light and GothicBBB-Medium.
ltj.loadlua('luatexja-jfont.lua')
ltj.loadlua('luatexja-core.lua')
+ ltj.loadlua('luatexja-jfmglue.lua')
ltj.loadlua('luatexja-xkanji.lua')
- ltj.loadlua('luatexja-core-aux.lua')
}
% autospacing = <bool> (default: true)
\define@boolkey[ltj]{japaram}{autospacing}[true]{%
\ifltj@japaram@autospacing
- \directlua{ltj.auto_spacing=true}%
+ \directlua{ltj.ext_print_global()}\ltj@autospc=1
\else
- \directlua{ltj.auto_spacing=false}%
- \fi
- }
+ \directlua{ltj.ext_print_global()}\ltj@autospc=0
+ \fi}
% autoxspacing = <bool> (default: true)
\define@boolkey[ltj]{japaram}{autoxspacing}[true]{%
\ifltj@japaram@autoxspacing
- \directlua{ltj.auto_xspacing=true}%
+ \directlua{ltj.ext_print_global()}\ltj@autoxspc=1
\else
- \directlua{ltj.auto_xspacing=false}%
- \fi
- }
+ \directlua{ltj.ext_print_global()}\ltj@autoxspc=0
+ \fi}
\define@key[ltj]{japaram}{kanjiskip}{% % SKIP
\directlua{ltj.ext_print_global()}\kanjiskip=#1 }
\define@choicekey*+[ltj]{japaram}{differentjfm}[\ltj@temp\ltj@tempr]%
{large,small,average,both}{%
\ifcase\ltj@tempr
- \directlua{ltj.calc_between_two_jchar_aux=ltj.calc_between_two_jchar_aux_large}\or
- \directlua{ltj.calc_between_two_jchar_aux=ltj.calc_between_two_jchar_aux_small}\or
- \directlua{ltj.calc_between_two_jchar_aux=ltj.calc_between_two_jchar_aux_average}\or
- \directlua{ltj.calc_between_two_jchar_aux=ltj.calc_between_two_jchar_aux_both}%
+ \directlua{ltj.ja_diffmet_rule = math.max}\or
+ \directlua{ltj.ja_diffmet_rule = math.min}\or
+ \directlua{ltj.ja_diffmet_rule = math.two_average}\or
+ \directlua{ltj.ja_diffmet_rule = math.two_add}
\fi
}{\@PackageWarning{luatexja}{ignored invalid argument '#1' for 'differentjfm'}}
% large, small, average, both
--- /dev/null
+------------------------------------------------------------------------
+-- MAIN PROCESS STEP 2: insert glue/kerns from JFM (prefix: none)
+------------------------------------------------------------------------
+
+local node_type = node.type
+local node_new = node.new
+local node_remove = node.remove
+local node_prev = node.prev
+local node_next = node.next
+local has_attr = node.has_attribute
+local node_insert_before = node.insert_before
+local node_insert_after = node.insert_after
+local round = tex.round
+
+local id_penalty = node.id('penalty')
+local id_glyph = node.id('glyph')
+local id_glue_spec = node.id('glue_spec')
+local id_glue = node.id('glue')
+local id_kern = node.id('kern')
+local id_hlist = node.id('hlist')
+local id_whatsit = node.id('whatsit')
+local sid_user = node.subtype('user_defined')
+
+local TEMPORARY = 2
+local FROM_JFM = 3
+local KINSOKU = 4
+local LINE_END = 5
+
+
+local attr_jchar_class = luatexbase.attributes['ltj@charclass']
+local attr_curjfnt = luatexbase.attributes['ltj@curjfnt']
+local attr_icflag = luatexbase.attributes['ltj@icflag']
+-- attr_icflag: 1: kern from \/, 2: 'lineend' kern from JFM
+
+--
+local cstb_get_penalty_table = ltj.int_get_penalty_table
+local ljfm_find_char_class = ltj.int_find_char_class
+
+-- arithmetic with penalty.
+-- p += e
+local function add_penalty(p,e)
+ local i = p
+ if i>=10000 then
+ if e<=-10000 then i = 0 end
+ elseif i<=-10000 then
+ if e>=10000 then i = 0 end
+ else
+ i = i + e
+ if i>=10000 then i = 10000
+ elseif i<=-10000 then i = -10000 end
+ end
+return p
+end
+
+-- return true if and only if p is a Japanese character node
+local function is_japanese_glyph_node(p)
+ return (p.id==id_glyph) and (p.font==has_attr(p,attr_curjfnt))
+end
+
+-- EXT: for \inhibitglue
+function ltj.ext_create_inhibitglue_node()
+ local g=node_new(id_whatsit, sid_user)
+ g.user_id=30111; g.type=number; g.value=1; node.write(g)
+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 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
+
+local function 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, ltj.font_metric_table[px.font].var }
+ else
+ return nil
+ end
+end
+
+local function new_jfm_glue(size,mt,bc,ac)
+-- mt: metric key, bc, ac: char classes
+ local g=nil
+ local z = ltj.metrics[mt].char_type[bc]
+ if z.glue and z.glue[ac] then
+ local h = node_new(id_glue_spec)
+ h.width = round(size*z.glue[ac][1])
+ h.stretch = round(size*z.glue[ac][2])
+ h.shrink = round(size*z.glue[ac][3])
+ h.stretch_order=0; h.shrink_order=0
+ g = node_new(id_glue)
+ g.subtype = 0; g.spec = h
+ elseif z.kern and z.kern[ac] then
+ g = node_new(id_kern)
+ g.subtype = 1; g.kern = round(size*z.kern[ac])
+ end
+ return g
+end
+
+-- Insert jfm glue: main routine
+-- local variables
+local p
+local q = nil -- the previous node of p
+local q_post -- the postbreakpenalty of q
+local ps, qs
+local widow_node -- 最後の「句読点扱いでない」和文文字
+local widow_bp -- 挿入位置 (a penalty)
+local last -- the sentinel
+local chain = false -- is q a Japanese character?
+local ihb_flag = false -- is \inhibitglue specified?
+local head -- the head of current list
+local mode -- true iff insert_jfm_glue is called from pre_linebreak_filter
+
+-- initialize (insert the sentinel, etc.)
+local function init_var()
+ p = head; q = nil; widow_node = nil; widow_bp = nil
+ chain = false; ihb_flag = false;
+ if mode then
+ while p and 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); local g = node_new('kern')
+ node_insert_after(head, last, g); last = g
+ end
+end
+
+-- Insert JFM glue before the first node (which is a Japanese glyph node)
+local function ins_gk_head()
+ if is_japanese_glyph_node(p) then
+ ps = find_size_metric(p)
+ local g = new_jfm_glue(ps[1], ps[2],
+ ljfm_find_char_class('boxbdd',ps[2]),
+ has_attr(p,attr_jchar_class))
+ if g then
+ node.set_attribute(g, attr_icflag, FROM_JFM)
+ head = node_insert_before(head, p, g)
+ end
+ q_post = cstb_get_penalty_table('post',p.char); chain = true
+ elseif p.id==id_glyph then
+ q_post = cstb_get_penalty_table('post',p.char)
+ end
+ qs = ps; q = p; p = node_next(p)
+end
+
+-- The real insertion process is handled in this procedure.
+local function real_insert(g, w, pen, always_penalty_ins)
+ -- g: glur/kern from JFM
+ -- w: the width of kern that will be inserted between q and the end of a line
+ -- pen: penalty
+ -- always_penalty_ins: true iff we insert a penalty,
+ -- for the linebreak between q and p.
+ if w~=0 then
+ if not g then
+ g = node_new(id_kern); g.kern = -w; g.subtype = 1
+ node.set_attribute(g, attr_icflag, TEMPORARY)
+ -- this g might be replaced by \[x]kanjiskip in step 3.
+ else
+ node.set_attribute(g, attr_icflag, FROM_JFM)
+ if g.id==id_kern then w=0
+ else g.spec.width = round(g.spec.width - w)
+ end
+ end
+ end
+ if w~=0 then
+ local h = node_new(id_kern)
+ node.set_attribute(h, attr_icflag, LINE_END)
+ h.kern = w; h.subtype = 0; node_insert_before(head, p, h)
+ elseif g then
+ node.set_attribute(g, attr_icflag, FROM_JFM)
+ if g.id==id_kern then
+ pen=0; always_penalty_ins = false
+ end
+ end
+ if w~=0 or pen~=0 or ((not g) and always_penalty_ins) then
+ local h = node_new(id_penalty)
+ h.penalty = pen; node.set_attribute(h, attr_icflag, KINSOKU)
+ node_insert_before(head, p, h)
+ end
+ if g then
+ node_insert_before(head, p, g);
+ end
+end
+
+-- This is a variant of real_insert (the case which a kern is related)
+local function real_insert_kern(g)
+ if g then
+ if g.id==id_glue then
+ local h = node_new(id_penalty)
+ h.penalty = 10000; node.set_attribute(h, attr_icflag, KINSOKU)
+ node_insert_before(head, p, h)
+ end
+ node.set_attribute(g, attr_icflag, FROM_JFM)
+ node_insert_before(head, p, g)
+ end
+end
+
+-- Calc the glue between two Japanese characters
+local function calc_ja_ja_glue()
+ if ihb_flag then return nil
+ elseif table.are_equal(qs,ps) then
+ return new_jfm_glue(ps[1],ps[2],
+ has_attr(q,attr_jchar_class),
+ has_attr(p,attr_jchar_class))
+ else
+ local g = new_jfm_glue(qs[1],qs[2],
+ has_attr(q,attr_jchar_class),
+ ljfm_find_char_class('diffmet',qs[2]))
+ local h = new_jfm_glue(ps[1],ps[2],
+ ljfm_find_char_class('diffmet',ps[2]),
+ has_attr(p,attr_jchar_class))
+ return calc_ja_ja_aux(g,h)
+ end
+end
+
+ltj.ja_diffmet_rule = math.two_average
+
+local function calc_ja_ja_aux(gb,ga)
+ if not gb then
+ return ga
+ else
+ if not ga then return gb end
+ local k = node.type(gb.id) .. node.type(ga.id)
+ if k == 'glueglue' then
+ -- 両方とも glue.
+ gb.spec.width = round(ltj.ja_diffmet_rule(gb.spec.width, ga.spec.width))
+ gb.spec.stretch = round(ltj.ja_diffmet_rule(gb.spec.stretch,ga.spec.shrink))
+ gb.spec.shrink = -round(ltj.ja_diffmet_rule(-gb.spec.shrink, -ga.spec.shrink))
+ return gb
+ elseif k == 'kernkern' then
+ -- 両方とも kern.
+ gb.kern = round(ltj.ja_diffmet_rule(gb.kern, ga.kern))
+ return gb
+ elseif k == 'kernglue' then
+ -- gb: kern, ga: glue
+ ga.spec.width = round(ltj.ja_diffmet_rule(gb.kern,ga.spec.width))
+ ga.spec.stretch = round(ltj.ja_diffmet_rule(ga.spec.stretch, 0))
+ ga.spec.shrink = -round(ltj.ja_diffmet_rule(-ga.spec.shrink, 0))
+ return ga
+ else
+ -- gb: glue, ga: kern
+ gb.spec.width = round(ltj.ja_diffmet_rule(ga.kern, gb.spec.width))
+ gb.spec.stretch = round(ltj.ja_diffmet_rule(gb.spec.stretch, 0))
+ gb.spec.shrink = -round(ltj.ja_diffmet_rule(-gb.spec.shrink, 0))
+ return gb
+ end
+ end
+end
+
+local function ins_gk_any_JA()
+ ps = find_size_metric(p)
+ if chain then -- (q,p): JA-JA
+ local g = calc_ja_ja_glue()
+ local w = 0; local x = ljfm_find_char_class('lineend', qs[2])
+ if (not ihb_flag) and x~=0 then
+ local h = ltj.metrics[qs[2]].char_type[has_attr(q, attr_jchar_class)]
+ if h.kern and h.kern[x] then w = round(qs[1]*h.kern[x]) end
+ end
+ q_post = add_penalty(q_post, cstb_get_penalty_table('pre', p.char))
+ real_insert(g, w, q_post, false)
+ elseif q.id==id_glyph then -- (q,p): AL-JA
+ local g = nil
+ if not ihb_flag then
+ g = new_jfm_glue(ps[1], ps[2],
+ ljfm_find_char_class('jcharbdd',ps[2]),
+ has_attr(p,attr_jchar_class))
+ end
+ q_post = add_penalty(q_post, cstb_get_penalty_table('pre', p.char))
+ real_insert(g, 0, q_post, true)
+ elseif q.id==id_kern then -- (q,p): kern-JA
+ local g = nil
+ if not ihb_flag then
+ g = new_jfm_glue(ps[1], ps[2],
+ ljfm_find_char_class('jcharbdd',ps[2]),
+ has_attr(p,attr_jchar_class))
+ end
+ real_insert_kern(g)
+ else
+ local g = nil
+ if not ihb_flag then
+ g = new_jfm_glue(ps[1], ps[2],
+ ljfm_find_char_class('jcharbdd',ps[2]),
+ has_attr(p,attr_jchar_class))
+ end
+ real_insert(g, 0, q_post, true)
+ end
+ q, qs, q_post = p, ps, cstb_get_penalty_table('post',p.char)
+ if cstb_get_penalty_table('kcat',p.char)%2~=1 then
+ widow_node = p
+ end
+ p = node_next(p); chain = true
+end
+
+local function ins_gk_JA_any()
+ -- the case (q,p): JA-JA is treated in ins_gk_any_JA()
+ local g = nil
+ if not ihb_flag then
+ g = new_jfm_glue(qs[1], qs[2],
+ has_attr(q,attr_jchar_class),
+ ljfm_find_char_class('jcharbdd',qs[2]))
+ end
+ if p.id==id_glyph then -- (q,p): JA-AL
+ local w = 0; local x = ljfm_find_char_class('lineend', qs[2])
+ if (not ihb_flag) and x~=0 then
+ local h = ltj.metrics[qs[2]].char_type[has_attr(q,attr_jchar_class)]
+ if h.kern and h.kern[x] then w = round(qs[1]*h.kern[x]) end
+ end
+ q_post = add_penalty(q_post, cstb_get_penalty_table('pre',p.char))
+ real_insert(g, w, q_post, true)
+ elseif p.id==id_kern then -- (q,p): JA-kern
+ real_insert_kern(g)
+ else
+ local w = 0; local x = ljfm_find_char_class('lineend', qs[2])
+ if (not ihb_flag) and x~=0 then
+ local h = ltj.metrics[qs[2]].char_type[has_attr(q,attr_jchar_class)]
+ if h.kern and h.kern[x] then w = round(qs[1]*h.kern[x]) end
+ end
+ real_insert(g, w, q_post, false)
+ end
+ chain = false; q, qs, q_post = p, nil, 0; p = node_next(p)
+end
+
+-- Insert JFM glue after thr last node
+local function ins_gk_tail()
+ local g
+ if is_japanese_glyph_node(p) then
+ if mode then
+ local w = 0; local x = ljfm_find_char_class('lineend', qs[2])
+ if (not ihb_flag) and x~=0 then
+ local h = ltj.metrics[qs[2]].char_type[has_attr(q,attr_jchar_class)]
+ if h.kern and h.kern[x] then w = round(qs[1]*h.kern[x]) end
+ end
+ if w~=0 then
+ g = node_new(id_kern); g.subtype = 0; g.kern = w
+ node.set_attribute(g, attr_icflag, LINE_END)
+ node_insert_before(head, last, g)
+ end
+ end
+ end
+end
+
+local function add_widow_penalty()
+ -- widoe_node: must be
+ if not widow_node then return end
+ local a = node_prev(widow_node)
+ local i = has_attr(a, attr_icflag) or 0
+ local wp = tex.getcount('jcharwidowpenalty')
+ if i==4 then
+ a.penalty=add_penalty(a.penalty, wp)
+ elseif i>=2 then
+ local b = node_prev(a)
+ if i==4 then
+ b.penalty=add_penalty(b.penalty, wp)
+ else
+ local g = node_new(id_penalty)
+ g.penalty = wp; head = node_insert_before(head,a,g)
+ end
+ else
+ local g = node_new(id_penalty)
+ g.penalty = wp; head = node_insert_before(head,widow_node,g)
+ end
+end
+
+-- Finishing: add \jcharwidowpenalty or remove the sentinel
+local function finishing()
+ if mode then
+ -- Insert \jcharwidowpenalty
+ add_widow_penalty()
+ else
+ head = node_remove(head, last)
+ end
+end
+
+-- The interface
+function ltj.int_insert_jfm_glue(ahead, amode)
+ if not ahead then return ahead end
+ head = ahead; mode = amode; init_var();
+ while p~=last and p.id==id_whatsit and p.subtype==sid_user and p.user_id==30111 do
+ local g = p; p = node_next(p); ihb_flag = true; head, p = node.remove(head, g)
+ end
+ if p~=last then ins_gk_head() else finishing() return head end
+
+ while p~=last do
+ if p.id==id_whatsit and p.subtype==sid_user and p.user_id==30111 then
+ local g = p; p = node_next(p)
+ ihb_flag = true; head, p = node.remove(head, g)
+ else
+ if is_japanese_glyph_node(p) then -- p: JAchar
+ ins_gk_any_JA()
+ elseif chain then -- q: JAchar
+ ins_gk_JA_any()
+ else
+ q, qs, q_post = p, nil, 0; p = node_next(p)
+ end
+ ihb_flag = false
+ end
+ end
+
+ ins_gk_tail(); finishing(); return head
+end
+
local id_glyph = node.id('glyph')
local id_kern = node.id('kern')
+local ITALIC = 1
------------------------------------------------------------------------
-- LOADING JFM (prefix: ljfm)
------------------------------------------------------------------------
if #v.chars ~= 1 then defjfm_res= nil; return end
elseif type(w) == 'number' then
real_char = true
+ elseif type(w) == 'string' and utf.len(w)==1 then
+ real_char = true; w = utf.byte(w)
end
if not t.chars[w] then
t.chars[w] = i
end
v.chars = nil
end
- if v.kern then
+ if v.kern and v.glue then
for j,w in pairs(v.glue) do
if v.kern[j] then defjfm_res= nil; return end
end
if p and p.id==id_glyph then
local f = p.font
local g = node_new(id_kern)
- g.subtype = 1; node.set_attribute(g, attr_icflag, 1)
+ g.subtype = 1; node.set_attribute(g, attr_icflag, ITALIC)
if rgjc_is_ucs_in_japanese_char(p) then
f = has_attr(p, attr_curjfnt)
- print(f, p.char)
local j = ltj.font_metric_table[f]
local c = ljfm_find_char_class(p.char, j.jfm)
g.kern = round(j.size * ltj.metrics[j.jfm].char_type[c].italic)
\ltjsetparameter{alxspmode={``,preonly}}
\ltjsetparameter{alxspmode={`',postonly}}
\ltjsetparameter{alxspmode={`;,postonly}}
-\ltjsetparameter{alxspmode={47,postonly}}
+\ltjsetparameter{alxspmode={44,postonly}}
\ltjsetparameter{alxspmode={`.,postonly}}
% for 8bit Latin
\ltjsetparameter{alxspmode={"80,allow}}
jcharwidowpenalty=500, differentjfm=average
}
+\ltj@tempcnta="0%"
+\loop\ifnum\ltj@tempcnta<"100%"
+ \ltjsetparameter{alxspmode={\ltj@tempcnta,0}}%
+ \advance\ltj@tempcnta by1
+\repeat
+
+\ltj@tempcnta=`\0%"
+\loop\ifnum\ltj@tempcnta<`\:%"
+ \ltjsetparameter{alxspmode={\ltj@tempcnta,3}}%
+ \advance\ltj@tempcnta by1
+\repeat
+
+\ltj@tempcnta=`\A%"
+\loop\ifnum\ltj@tempcnta<`\[%"
+ \ltjsetparameter{alxspmode={\ltj@tempcnta,3}}%
+ \advance\ltj@tempcnta by1
+\repeat
+
+\ltj@tempcnta=`\a%"
+\loop\ifnum\ltj@tempcnta<`\{%"
+ \ltjsetparameter{alxspmode={\ltj@tempcnta,3}}%
+ \advance\ltj@tempcnta by1
+\repeat
+
\input luatexja-kinsoku.tex
\ltj@tempcnta="2000%"
local node_new = node.new
local node_prev = node.prev
local node_next = node.next
+local node_copy = node.copy
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')
local id_whatsit = node.id('whatsit')
local attr_icflag = luatexbase.attributes['ltj@icflag']
+local attr_autospc = luatexbase.attributes['ltj@autospc']
+local attr_autoxspc = luatexbase.attributes['ltj@autoxspc']
local attr_curjfnt = luatexbase.attributes['ltj@curjfnt']
+local max_dimen = 1073741823
+
+local ITALIC = 1
+local TEMPORARY = 2
+local FROM_JFM = 3
+local KINSOKU = 4
+local LINE_END = 5
local kanji_skip
local xkanji_skip
-local no_skip = 0
-local after_schar = 1
-local after_wchar = 2
-local insert_skip = no_skip
-- (glyph_node nr) ... (node nq) <GLUE> ,,, (node np)
local np, nq, nrc
local after_schar = 1
local after_wchar = 2 -- nr is a Japanese glyph_node
local insert_skip = no_skip
+local head
local cstb_get_inhibit_xsp_table = ltj.int_get_inhibit_xsp_table
and (p.font==has_attr(p,attr_curjfnt))
end
+local function get_zero_glue()
+ local g = node_new(id_glue_spec)
+ g.width = 0; g.stretch_order = 0; g.stretch = 0
+ g.shrink_order = 0; g.shrink = 0
+ return g
+end
+
-- the following 2 functions are the lowest part.
-- cx: the Kanji code of np
-local function insert_ascii_kanji_xkskip(head,q,cx)
+local function insert_ascii_kanji_xkskip(q, cx)
if cstb_get_inhibit_xsp_table(cx)<=1 then return end
local g = node_new(id_glue)
g.subtype = 0; g.spec = node.copy(xkanji_skip)
node_insert_after(head, q, g)
end
-local function insert_kanji_ascii_xkskip(head,q,p)
+local function insert_kanji_ascii_xkskip(q, p)
local g=true
local c = p.char
while p.components and p.subtype
end
end
+local function get_kanji_skip_from_jfm(p)
+ local px = { ltj.font_metric_table[p.font].size,
+ ltj.font_metric_table[p.font].jfm }
+ local i = ltj.metrics[px[2]].kanjiskip
+ print(p.font, px[1], px[2], ltj.metrics[px[2]].dir, i)
+ if i then
+ return { round(i[1]*px[1]), round(i[2]*px[1]), round(i[3]*px[1]) }
+ else return nil
+ end
+end
+
+local function insert_kanji_skip()
+ print('a', utf.char(np.char))
+ local g = node_new(id_glue); g.subtype=0
+ if kanji_skip.width==max_dimen then -- use kanjiskip from JFM
+ local gx = node_new(id_glue_spec);
+ gx.stretch_order = 0; gx.shrink_order = 0
+ local bk = nil -- incomplete
+ local ak = get_kanji_skip_from_jfm(np)
+ if bk then
+ if ak then
+ gx.width = round(ltj.ja_diffmet_rule(bk[1], ak[1]))
+ gx.stretch = round(ltj.ja_diffmet_rule(bk[2], ak[2]))
+ gx.shrink = -round(ltj.ja_diffmet_rule(-bk[3], -ak[3]))
+ else
+ gx.width = bk[1]; gx.stretch = bk[2]; gx.shrink = bk[3]
+ end
+ elseif ak then
+ gx.width = ak[1]; gx.stretch = ak[2]; gx.shrink = ak[3]
+ else
+ gx = get_zero_glue()-- ???
+ end
+ g.spec = gx
+ else
+ g.spec=node.copy(kanji_skip)
+ end
+ local h = node_prev(np)
+ if h and has_attr(h, attr_icflag)==TEMPORARY then
+ if h.id==id_kern then
+ g.spec.width = g.spec.width + h.kern
+ head = node.remove(head, h)
+ node_insert_before(head, np, g)
+ else
+ h.spec.width = g.spec.width + h.spec.width
+ h.spec.stretch = g.spec.stretch + h.spec.stretch
+ h.spec.shrink = g.spec.shrink + h.spec.shrink
+ end
+ else
+ node_insert_before(head, np, g)
+ end
+ print('b', utf.char(np.char))
+end
+
-- When p is a glyph_node ...
-local function insks_around_char(head)
+local function insks_around_char()
if is_japanese_glyph_node(np) then
if insert_skip==after_wchar then
- local g = node_new(id_glue)
- g.subtype=0; g.spec=node.copy(kanji_skip)
- node_insert_before(head, np, g)
+ insert_kanji_skip()
elseif insert_skip==after_schar then
- insert_ascii_kanji_xkskip(head, nq, np.char)
+ insert_ascii_kanji_xkskip(nq, np.char)
end
insert_skip=after_wchar; nrc = np.char
else
if insert_skip==after_wchar then
- insert_kanji_ascii_xkskip(head, nq, np)
+ insert_kanji_ascii_xkskip(nq, np)
end
set_insert_skip_after_achar(np)
end
end
-- When np is a hlist_node ...
-local function insks_around_hbox(head)
+local function insks_around_hbox()
if np.shift==0 then
find_first_char = true; first_char = nil; last_char = nil
if check_box(np.head) then
if is_japanese_glyph_node(first_char) then
nrc = first_char.char
if insert_skip==after_schar then
- insert_ascii_kanji_xkskip(head, nq, first_char.char)
+ insert_ascii_kanji_xkskip(nq, first_char.char)
elseif insert_skip==after_wchar then
- local g = node_new(id_glue)
- g.subtype = 0; g.spec = node.copy(kanji_skip)
- node_insert_before(head, np, g)
+ insert_kanji_skip()
end
insert_skip = after_wchar
elseif first_char then
if insert_skip==after_wchar then
- insert_kanji_ascii_xkskip(head, nq, first_char)
+ insert_kanji_ascii_xkskip(nq, first_char)
end
set_insert_skip_after_achar(first_char)
end
end
-- When np is a penalty ...
-local function insks_around_penalty(head)
+local function insks_around_penalty()
nq = np
end
-- When np is a kern ...
--
-local function insks_around_kern(head)
+local function insks_around_kern()
if np.subtype==1 then -- \kern or \/
local i = has_attr(np, attr_icflag)
- if not i then -- \kern
+ if not i or i==FROM_JFM then -- \kern
insert_skip = no_skip
- elseif i==1 then
+ elseif i==ITALIC or i==LINE_END or i==TEMPORARY then
nq = np
end
elseif np.subtype==2 then
end
-- When np is a math_node ...
-local function insks_around_math(head)
+local function insks_around_math()
local g = { char = -1 }
if (np.subtype==0) and (insert_skip==after_wchar) then
- insert_kanji_ascii_xkskip(head, nq, g)
+ insert_kanji_ascii_xkskip(nq, g)
insert_skip = no_skip
else
nq = np; set_insert_skip_after_achar(g)
end
end
-function ltj.int_insert_kanji_skip(head)
- if ltj.auto_spacing then
- kanji_skip=tex.skip['kanjiskip']
- else
- kanji_skip=node_new(id_glue_spec)
- kanji_skip.width=0; kanji_skip.stretch=0; kanji_skip.shrink=0
- end
- if ltj.auto_xspacing then
- xkanji_skip=tex.skip['xkanjiskip']
- else
- xkanji_skip=node_new(id_glue_spec)
- xkanji_skip.width=0; xkanji_skip.stretch=0; xkanji_skip.shrink=0
- end
+function ltj.int_insert_kanji_skip(ahead)
+ kanji_skip=tex.skip['kanjiskip']
+ xkanji_skip=tex.skip['xkanjiskip']
+ head = ahead
np = head; nq = nil; insert_skip = no_skip
while np do
if np.id==id_glyph then
repeat
- insks_around_char(head); np=node_next(np)
+ insks_around_char(); np=node_next(np)
until (not np) or np.id~=id_glyph
else
if np.id==id_hlist then
- insks_around_hbox(head)
+ insks_around_hbox()
elseif np.id==id_penalty then
- insks_around_penalty(head)
+ insks_around_penalty()
elseif np.id==id_kern then
- insks_around_kern(head)
+ insks_around_kern()
elseif np.id==id_math then
- insks_around_math(head)
+ insks_around_math()
elseif np.id==id_ins or np.id==id_mark
or np.id==id_adjust or np.id==id_whatsit then
-- do nothing
end
end
return head
-end
+end
\ No newline at end of file
--- /dev/null
+This is LuaTeX, Version beta-0.71.0-2011050715 (format=luatex 2011.5.7) 8 MAY 2011 21:45
+ restricted \write18 enabled.
+**test04-jfm.tex
+(./test04-jfm.tex
+(/opt/texlive/p2010/../texmf-local/tex/generic/luatexja/luatexja-core.sty
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/luaotfload.sty
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase.sty
+Package: luatexbase 2010/10/06 v0.3 Module utilities for LuaTeX
+(/opt/texlive/p2010/texmf-dist/tex/generic/oberdiek/ifluatex.sty
+Package: ifluatex 2010/03/01 v1.3 Provides the ifluatex switch (HO)
+Package ifluatex Info: LuaTeX detected.
+)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-compat.sty
+Package: luatexbase-compat 2010/10/10 v0.3 Compatibility tools for LuaTeX
+(/opt/texlive/p2010/texmf-dist/tex/generic/oberdiek/ifluatex.sty
+Package ifluatex Info: The package is already loaded.
+))
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-loader.sty
+Package: luatexbase-loader 2010/10/10 v0.3 Lua module loader for LuaTeX
+(/opt/texlive/p2010/texmf-dist/tex/generic/oberdiek/ifluatex.sty
+Package ifluatex Info: The package is already loaded.
+)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-compat.sty)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase.loader.lua))
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-regs.sty
+Package: luatexbase-regs 2010/10/10 v0.3 Registers allocation for LuaTeX
+(/opt/texlive/p2010/texmf-dist/tex/generic/oberdiek/ifluatex.sty
+Package ifluatex Info: The package is already loaded.
+))
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-attr.sty
+Package: luatexbase-attr 2010/10/10 v0.3 Attributes allocation for LuaTeX
+(/opt/texlive/p2010/texmf-dist/tex/generic/oberdiek/ifluatex.sty
+Package ifluatex Info: The package is already loaded.
+)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-compat.sty)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-loader.sty)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/attr.lua))
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-cctb.sty
+Package: luatexbase-cctb 2010/10/10 v0.3 Catcodetable allocation for LuaTeX
+(/opt/texlive/p2010/texmf-dist/tex/generic/oberdiek/ifluatex.sty
+Package ifluatex Info: The package is already loaded.
+)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-loader.sty)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/cctb.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-compat.sty)
+\lltxb@catcodetable@alloc=\count277
+\@tempcnta=\count278
+\@tempcntb=\count279
+\CatcodeTableIniTeX=\luatexcatcodetable1
+\CatcodeTableString=\luatexcatcodetable2
+\CatcodeTableOther=\luatexcatcodetable3
+\CatcodeTableLaTeX=\luatexcatcodetable4
+\CatcodeTableLaTeXAtLetter=\luatexcatcodetable5
+\CatcodeTableExpl=\luatexcatcodetable6
+)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-mcb.sty
+Package: luatexbase-mcb 2010/10/10 v0.3 Callback management for LuaTeX
+(/opt/texlive/p2010/texmf-dist/tex/generic/oberdiek/ifluatex.sty
+Package ifluatex Info: The package is already loaded.
+)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-modutils.sty
+Package: luatexbase-modutils 2010/10/10 v0.3 Module utilities for LuaTeX
+(/opt/texlive/p2010/texmf-dist/tex/generic/oberdiek/ifluatex.sty
+Package ifluatex Info: The package is already loaded.
+)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-loader.sty)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/modutils.lua))
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/mcb.lua)
+Lua module: luatexbase-mcb 2010/05/12 0.2 register several functions in a callb
+ack
+)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luatexbase/luatexbase-modutils.sty))
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs.lua)
+Lua module: lualibs 2011/01/20 0.96 Lua additional functions.
+
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-string.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-lpeg.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-boolean.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-number.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-math.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-table.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-aux.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-io.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-os.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-file.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-md5.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-dir.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-unicode.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-utils.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-dimen.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-url.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/lualibs/lualibs-set.lua)
+(/opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/luaotfload.lua)
+Lua module: luaotfload 2011/02/16 1.24 OpenType layout system.
+
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-luat-dum.lua.(using cache: /home/h7k/.texlive2010/texmf-var/luatex-cache/gen
+eric)
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-luat-ovr.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-data-con.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-ini.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-node-dum.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-node-inj.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-tfm.lua.
+luatexbase.attributes["otfl@state"] = 1
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-cid.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-ott.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-map.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-otf.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-otd.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-oti.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-otb.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-otn.lua.
+luatexbase.attributes["otfl@markbase"] = 2
+luatexbase.attributes["otfl@markmark"] = 3
+luatexbase.attributes["otfl@markdone"] = 4
+luatexbase.attributes["otfl@cursbase"] = 5
+luatexbase.attributes["otfl@curscurs"] = 6
+luatexbase.attributes["otfl@cursdone"] = 7
+luatexbase.attributes["otfl@kernpair"] = 8
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-ota.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-otc.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-def.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-xtx.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-dum.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-nms.lua.
+luaotfload: loading file /opt/texlive/p2010/texmf-dist/tex/luatex/luaotfload/ot
+fl-font-clr.lua.
+Module luatexbase-mcb info: creating 'luaotfload.patch_font' type 4
+Module luatexbase-mcb info: inserting 'luaotfload.pre_linebreak_filter'
+(luatexbase-mcb) at position 1 in 'pre_linebreak_filter'
+Module luatexbase-mcb info: inserting 'luaotfload.hpack_filter'
+(luatexbase-mcb) at position 1 in 'hpack_filter'
+Module luatexbase-mcb info: resetting callback 'define_font'
+Module luatexbase-mcb info: inserting 'luaotfload.define_font'
+(luatexbase-mcb) at position 1 in 'define_font'
+Module luatexbase-mcb info: inserting 'luaotfload.find_vf_file'
+(luatexbase-mcb) at position 1 in 'find_vf_file'
+) (/opt/texlive/p2010/texmf-dist/tex/generic/oberdiek/ltxcmds.sty
+Package: ltxcmds 2010/04/26 v1.7 LaTeX kernel commands for general use (HO)
+)
+(/opt/texlive/p2010/texmf-dist/tex/generic/xkeyval/xkeyval.tex
+\XKV@toks=\toks13
+\XKV@tempa@toks=\toks14
+\XKV@depth=\count280
+
+2008/08/13 v2.6a key=value parser (HA)
+(/opt/texlive/p2010/texmf-dist/tex/generic/xkeyval/xkvtxhdr.tex
+2005/02/22 v1.1 xkeyval TeX header (HA))
+(/opt/texlive/p2010/texmf-dist/tex/generic/xkeyval/keyval.tex))
+(/opt/texlive/p2010/texmf-dist/tex/generic/oberdiek/infwarerr.sty
+Package: infwarerr 2010/04/08 v1.3 Providing info/warning/message (HO)
+)
+\ltj@tempcnta=\count281
+\ltj@tempcntb=\count282
+\ltj@tempcntc=\count283
+\ltj@tempdima=\dimen256
+\ltj@autospc=\count284
+\ltj@autoxspc=\count285
+\jcharwidowpenalty=\count286
+\kanjiskip=\skip256
+\xkanjiskip=\skip257
+\zw=\dimen257
+\zh=\dimen258
+\jQ=\dimen259
+\jH=\dimen260
+\ltj@curjfnt=\luatexattribute9
+\ltj@charclass=\luatexattribute10
+\ltj@yablshift=\luatexattribute11
+\ltj@ykblshift=\luatexattribute12
+\ltj@autospc=\luatexattribute13
+\ltj@autoxspc=\luatexattribute14
+\ltj@icflag=\luatexattribute15
+\ltj@japanese=\language87
+
+(/opt/texlive/p2010/../texmf-local/tex/generic/luatexja/luatexja-rmlgbm.lua)
+(/opt/texlive/p2010/../texmf-local/tex/generic/luatexja/luatexja-rmlgbm-data.lu
+a)
+(/opt/texlive/p2010/../texmf-local/tex/generic/luatexja/luatexja-jfont.lua)
+(/opt/texlive/p2010/../texmf-local/tex/generic/luatexja/luatexja-core.lua)
+Module luatexbase-mcb info: inserting 'ltj.process_input_buffer'
+(luatexbase-mcb) at position 1 in 'process_input_buffer'
+Module luatexbase-mcb info: inserting 'ltj.hpack_filter_pre'
+(luatexbase-mcb) at position 1 in 'hpack_filter'
+Module luatexbase-mcb info: inserting 'ltj.hyphenate'
+(luatexbase-mcb) at position 1 in 'hyphenate'
+Module luatexbase-mcb info: inserting 'ltj.pre_linebreak_filter'
+(luatexbase-mcb) at position 2 in 'pre_linebreak_filter'
+Module luatexbase-mcb info: inserting 'ltj.hpack_filter'
+(luatexbase-mcb) at position 2 in 'hpack_filter'
+(/opt/texlive/p2010/../texmf-local/tex/generic/luatexja/luatexja-jfmglue.lua)
+(/opt/texlive/p2010/../texmf-local/tex/generic/luatexja/luatexja-xkanji.lua)
+\ltj@kcat0=\luatexattribute16
+\ltj@kcat1=\luatexattribute17
+\ltj@kcat2=\luatexattribute18
+\ltj@kcat3=\luatexattribute19
+\ltj@kcat4=\luatexattribute20
+\ltj@kcat5=\luatexattribute21
+\ltj@kcat6=\luatexattribute22
+\ltj@@stack=\count287
+\ltj@@group@level=\count288
+
+plain format: loading luatexja-plain.tex
+(/opt/texlive/p2010/../texmf-local/tex/generic/luatexja/luatexja-plain.tex
+(/opt/texlive/p2010/../texmf-local/tex/generic/luatexja/jfm-ujis.lua)
+(/opt/texlive/p2010/../texmf-local/tex/generic/luatexja/luatexja-kinsoku.tex)))
+(load: /home/h7k/.texlive2010/texmf-var/luatex-cache/generic/fonts/otf/temp-ipa
+m.lua)(load: /home/h7k/.texlive2010/texmf-var/luatex-cache/generic/fonts/otf/te
+mp-kozminpr6n-regular.lua)(load: /home/h7k/.texlive2010/texmf-var/luatex-cache/
+generic/fonts/otf/temp-ipamp.lua)
+(./jfm-bad.lua)
+! LuaTeX-ja error: bad JFM 'bad'.
+\ltj@@jfont ->\directlua {ltj.ext_jfontdefY()}
+
+<to be read again>
+ }
+l.19 }
+
+The JFM file you specified is not valid JFM file.
+Defining Japanese font is cancelled.
+
+(load: /home/h7k/.texlive2010/texmf-var/luatex-cache/generic/fonts/otf/temp-ipa
+exg.lua)
+! LuaTeX-ja error: Invalid character code (-1), should in the range 0.."10FFFF.
+.
+\ltj@@getparam@two ...('#1', \the \ltj@tempcnta )}
+
+l.52 \ltjgetparameter{chartorange}{-1}
+ % must be error "
+I'm going to use 0 instead of that illegal character code.
+
+[1{/opt/texlive/p2010/texmf-var/fonts/map/pdftex/updmap/pdftex.map
+LuaTeX warning (file /opt/texlive/p2010/texmf-var/fonts/map/pdftex/updmap/pdfte
+x.map): fontmap entry for `bchb8r' already exists, duplicates ignored
+
+LuaTeX warning (file /opt/texlive/p2010/texmf-var/fonts/map/pdftex/updmap/pdfte
+x.map): fontmap entry for `bchbi8r' already exists, duplicates ignored
+
+LuaTeX warning (file /opt/texlive/p2010/texmf-var/fonts/map/pdftex/updmap/pdfte
+x.map): fontmap entry for `bchbo8r' already exists, duplicates ignored
+
+LuaTeX warning (file /opt/texlive/p2010/texmf-var/fonts/map/pdftex/updmap/pdfte
+x.map): fontmap entry for `bchr8r' already exists, duplicates ignored
+
+LuaTeX warning (file /opt/texlive/p2010/texmf-var/fonts/map/pdftex/updmap/pdfte
+x.map): fontmap entry for `bchri8r' already exists, duplicates ignored
+
+LuaTeX warning (file /opt/texlive/p2010/texmf-var/fonts/map/pdftex/updmap/pdfte
+x.map): fontmap entry for `bchro8r' already exists, duplicates ignored
+}]
+(./jfm-test.lua) [2] [3] [4] [5] )</opt/texlive/p2010/texmf/fonts/truetype/test
+/ipaexg.ttf></opt/texlive/p2010/texmf/fonts/truetype/test/ipamp.ttf></opt/texli
+ve/p2010/texmf/fonts/opentype/test/kozuka/KozMinPr6N-Regular.otf></opt/texlive/
+p2010/texmf/fonts/truetype/test/ipam.ttf></opt/texlive/p2010/texmf-dist/fonts/t
+ype1/public/amsfonts/cm/cmbx10.pfb></opt/texlive/p2010/texmf-dist/fonts/type1/p
+ublic/amsfonts/cm/cmr10.pfb></opt/texlive/p2010/texmf-dist/fonts/type1/public/a
+msfonts/cm/cmti10.pfb></opt/texlive/p2010/texmf-dist/fonts/type1/public/amsfont
+s/cm/cmtt10.pfb>
+Output written on test04-jfm.pdf (5 pages, 463601 bytes).
+PDF statistics: 74 PDF objects out of 1000 (max. 8388607)
+ 48 compressed objects within 1 object stream
+ 0 named destinations out of 1000 (max. 131072)
+ 1 words of extra memory for PDF output out of 10000 (max. 10000000)
+
\ltjsetparameter{jacharrange={218}}
和文扱いにもどる
-↓「あ」「い」「え」「お」以外はプロポーショナル組(IPA P明朝)
-
-\jfont\rmlh={file:ipamp.ttf:jfm=hang} at 10pt
-\rmlh プロポーショナルのテスト!あいうえおさ,かき・くけこ
-
-
\vfill\eject
-\head{‘lineend’検証}
-\jfont\rmlh={psft:Ryumin-Light:jfm=hang} at 10pt
+\noindent{\bf\gt 以下はJFMグルー挿入検証}
+\jfont\rmlh={psft:Ryumin-Light:jfm=test} at 10pt
\jfont\sixgt={psft:GothicBBB-Medium:jfm=ujis} at 6pt
\font\sixtt=cmtt10 at 6pt
-
\def\dumplist#1{\par\noindent\leavevmode
\hbox to 0.2\hsize{\copy#1\hss}%
\vbox{\hsize=0.6\hsize\sixtt\baselineskip=7.2pt\sixgt\let\\=\relax
\directlua{ltj.ext_show_node_list(tex.getbox(#1).head, '\\par', tex.print)}\hrule}}
-\setbox0=\hbox{\rmlh あえあいえ}
-\dumplist0
+\head{JA--JA (penなし)}
-\medskip
-\ltjsetparameter{postbreakpenalty={`あ,100}}
-\ltjsetparameter{postbreakpenalty={`い,100}}
-\ltjsetparameter{postbreakpenalty={`う,100}}
-\ltjsetparameter{postbreakpenalty={`え,100}}
-\setbox0=\hbox{\rmlh あえあいえ}
-\dumplist0
+\setbox0=\hbox{\rmlh あア}\dumplist0
+
+\setbox0=\hbox{\rmlh あイ}\dumplist0
+
+\setbox0=\hbox{\rmlh あウ}\dumplist0
+
+\setbox0=\hbox{\rmlh いア}\dumplist0
+
+\setbox0=\hbox{\rmlh いイ}\dumplist0
+
+\setbox0=\hbox{\rmlh いウ}\dumplist0
+
+\head{JA--EN (penなし)}
+
+\setbox0=\hbox{\rmlh あa}\dumplist0
+
+\setbox0=\hbox{\rmlh いa}\dumplist0
+
+\setbox0=\hbox{\rmlh うa}\dumplist0
+
+\setbox0=\hbox{\rmlh えa}\dumplist0
+
+\setbox0=\hbox{\rmlh おa}\dumplist0
+
+\head{EN--JA (penなし)}
+
+\setbox0=\hbox{\rmlh aあ}\dumplist0
+
+\setbox0=\hbox{\rmlh aい}\dumplist0
+
+\setbox0=\hbox{\rmlh aう}\dumplist0
+
+\head{JA--明kern (penなし)}
+
+\setbox0=\hbox{\rmlh あ\kern3pt}\dumplist0
+
+\setbox0=\hbox{\rmlh い\kern3pt}\dumplist0
+
+\setbox0=\hbox{\rmlh う\kern3pt}\dumplist0
+
+\head{明kern--JA (penなし)}
+
+\setbox0=\hbox{\rmlh \kern3ptあ}\dumplist0
+
+\setbox0=\hbox{\rmlh \kern3ptい}\dumplist0
+
+\setbox0=\hbox{\rmlh \kern3ptう}\dumplist0
+
+\head{italic correction}
+
+\setbox0=\hbox{\it f\/(\/あ}\dumplist0
+
+
+{\vfill\eject%
+
+\ltjsetparameter{prebreakpenalty={`(,123}}
+\ltjsetparameter{postbreakpenalty={`あ,123}}
+\ltjsetparameter{postbreakpenalty={`い,123}}
+\ltjsetparameter{postbreakpenalty={`う,123}}
+\ltjsetparameter{postbreakpenalty={`え,123}}
+\ltjsetparameter{postbreakpenalty={`お,123}}
+\ltjsetparameter{postbreakpenalty={`a,321}}
+\head{JA--JA (penあり)}
+
+\setbox0=\hbox{\rmlh あア}\dumplist0
+
+\setbox0=\hbox{\rmlh あイ}\dumplist0
+
+\setbox0=\hbox{\rmlh あウ}\dumplist0
+
+\setbox0=\hbox{\rmlh いア}\dumplist0
+
+\setbox0=\hbox{\rmlh いイ}\dumplist0
+
+\setbox0=\hbox{\rmlh いウ}\dumplist0
+
+\head{JA--EN (penあり)}
+
+\setbox0=\hbox{\rmlh あa}\dumplist0
+
+\setbox0=\hbox{\rmlh いa}\dumplist0
+
+\setbox0=\hbox{\rmlh うa}\dumplist0
+
+\setbox0=\hbox{\rmlh えa}\dumplist0
+
+\setbox0=\hbox{\rmlh おa}\dumplist0
+
+\head{EN--JA (penあり)}
+
+\setbox0=\hbox{\rmlh aあ}\dumplist0
+
+\setbox0=\hbox{\rmlh aい}\dumplist0
+
+\setbox0=\hbox{\rmlh aう}\dumplist0
\head{italic correction}
-\setbox0=\hbox{x{\rmlh お\/}({\rmlh お\/}あ}
-\dumplist0
+\setbox0=\hbox{\it f\/(\/あ}\dumplist0
-\setbox0=\hbox{x{\it f\/}({\it g\/}あ}
-\dumplist0
+}
+
+\vfill\eject
+\kanjiskip=\maxdimen
+\setbox0=\hbox{\rmlh ンン}\dumplist0
\end