3 %% 行末の句読点の位置によって,全角取りか半角取りかを自動的に調整する
4 %% 仕様:全調整量が二分以上なら,全角取りにする
5 \documentclass{article}
6 \usepackage{luatexja,luacode,xcolor}
8 local id_hlist = node.id('hlist')
9 local id_glue = node.id('glue')
10 local id_glue_spec = node.id('glue_spec')
11 local attr_icflag = luatexbase.attributes['ltj@icflag']
13 local PROCESSED_BEGIN_FLAG = 16
18 local function get_attr_icflag(p)
19 return (node.has_attribute(p, attr_icflag) or 0) % PROCESSED_BEGIN_FLAG
22 -- box 内で伸縮された glue の合計値を計算
24 local function get_stretched(q, go, gs)
26 if not qs.writable then return 0 end
27 if gs == 1 then -- stretching
28 if qs.stretch_order == go then return qs.stretch end
30 if qs.shrink_order == go then return qs.shrink end
34 local function get_total_stretched(p)
35 local go, gf, gs = p.glue_order, p.glue_set, p.glue_sign
37 other = 0, xkanji = 0, jfm = 0, kanji = 0,
38 glue_set = gf, glue_sign = gs
40 if go ~= 0 then return nil end
41 if gs ~= 1 and gs ~= 2 then return res end
42 for q in node.traverse_id(id_glue, p.head) do
43 local a, ic = get_stretched(q, go, gs), get_attr_icflag(q)
44 if ic == KANJI_SKIP then res.kanji = res.kanji + a
45 elseif ic == XKANJI_SKIP then res.xkanji = res.xkanji + a
46 elseif ic == FROM_JFM then res.jfm = res.jfm + a
47 else res.other = res.other + a
53 local function clear_stretch(p, ic)
54 for q in node.traverse_id(id_glue, p.head) do
55 if get_attr_icflag(q) == ic then
58 qs.stretch_order, qs.shrink_order, qs.stretch, qs.shrink = 0, 0, 0, 0
64 local function set_stretch(p, after, before, ic)
66 print (ic, before, after)
67 local ratio = after/before
68 for q in node.traverse_id(id_glue, p.head) do
69 if get_attr_icflag(q) == ic then
72 qs.stretch, qs.shrink = qs.stretch*ratio, qs.shrink*ratio
79 function adjust_width(head)
80 if not head then return head end
81 for p in node.traverse_id(id_hlist, head) do
82 local res = get_total_stretched(p)
85 local total = tex.round((res.other + res.xkanji + res.jfm + res.kanji) * res.glue_set)
86 print('before: ', p.glue_set, p.glue_sign, p.glue_order )
87 print(total, res.other, res.xkanji, res.jfm, res.kanji)
88 if total <= res.other then -- 和文処理グルー以外で足りる
89 clear_stretch(p, KANJI_SKIP)
90 clear_stretch(p, XKANJI_SKIP)
91 clear_stretch(p, FROM_JFM)
92 local f = node.hpack(p.head, p.width, 'exactly')
93 f.head, p.glue_set, p.glue_sign, p.glue_order
94 = nil, f.glue_set, f.glue_sign, f.glue_order
97 total = total - res.other
98 if total <= res.jfm then -- JFMグルーだけで良い
99 clear_stretch(p, KANJI_SKIP)
100 clear_stretch(p, XKANJI_SKIP)
101 set_stretch(p, total,res.jfm, FROM_JFM)
102 local f = node.hpack(p.head, p.width, 'exactly')
103 f.head, p.glue_set, p.glue_sign, p.glue_order
104 = nil, f.glue_set, f.glue_sign, f.glue_order
107 total = total - res.jfm
108 if total <= res.xkanji then -- xkanjiskip まで
109 clear_stretch(p, KANJI_SKIP)
110 set_stretch(p, total,res.xkanji, XKANJI_SKIP)
111 local f = node.hpack(p.head, p.width, 'exactly')
112 f.head, p.glue_set, p.glue_sign, p.glue_order
113 = nil, f.glue_set, f.glue_sign, f.glue_order
116 total = total - res.xkanji
117 if total <= res.kanji then -- kanjiskip まで
118 set_stretch(p, total,res.kanji, KANJI_SKIP)
119 local f = node.hpack(p.head, p.width, 'exactly')
120 f.head, p.glue_set, p.glue_sign, p.glue_order
121 = nil, f.glue_set, f.glue_sign, f.glue_order
124 -- glue_set > 1 なので,どうしようもない
129 print('after: ', p.glue_set, p.glue_sign, p.glue_order )
138 \def\sq{\hbox to 1\zw{\hss\fboxsep=-.5\fboxrule\fbox{ }\hss}}
139 \def\sb{\hbox to 1\zw{\hss\fboxsep=-.5\fboxrule\fbox{■}\hss}}
141 \setbox\gridbox=\hbox to 20\zw{\sq\sq\sq\sq\sb\sq\sq\sq\sq\sb\sq\sq\sq\sq\sb\sq\sq\sq\sq\sb}
143 \leavevmode\hbox to 2em{\tt #1\hss}\vrule
144 \textcolor{cyan!50!white}{\copy\gridbox}\hskip-20\zw\copy0\vrule\par
147 \def\DisableCB{\directlua{luatexbase.remove_from_callback('post_linebreak_filter', 'Adjust width')}}
148 \def\EnableCB{\directlua{luatexbase.add_to_callback('post_linebreak_filter', adjust_width, 'Adjust width', 100)}}
150 \long\def\testbox#1{%
151 \EnableCB\setbox0=\vbox{\hsize=20\zw\parfillskip0pt#1}\outbox{ON}\par
152 \DisableCB\setbox0=\vbox{\hsize=20\zw\parfillskip0pt#1}\outbox{OFF}\par
157 {\tt kanjiskip: \ltjgetparameter{kanjiskip}
159 \ltjsetparameter{xkanjiskip=.25\zw plus .25\zw minus -.125\zw}
160 xkanjiskip: \ltjgetparameter{xkanjiskip}}
167 あいうえおかきくけこ「「さしすせそたちつて
171 あいうえおかきA B C Dこさ\texttt{DO i=1,10}『
175 「\texttt{\textbackslash expandafter}ユーザの集い」が開催された
179 あいうえおきくけこ「」さ123456そたちつて
182 \def\pTeX{p\kern-.2em\TeX}
184 日本では\pTeX,p\LaTeX がよく使われている。