OSDN Git Service

test27-lineprofile: 行送りを \baselineskip よりは狭めないように
[luatex-ja/luatexja.git] / test / test27-lineprofile.tex
1 \documentclass[10ptj]{ltjsarticle}
2 \usepackage[width=40\zw, lines=40,centering]{geometry}
3 \usepackage{amsmath,luacode,xcolor}
4 \begin{luacode}
5   lineskip = {}
6 do
7   local insert = table.insert
8   local rangedimensions, max = node.rangedimensions, math.max
9   function lineskip.p_profile(before, after)
10     local t = {}
11     do
12       local w_acc, d_before = 0, 0
13       local x = before.head; local xn = x.next
14       while x do
15         local w, d
16         if xn then w, _, d= rangedimensions(before,x,xn)
17         else w, _, d= rangedimensions(before,x) end
18         if d~=d_before then
19           d_before = d; t[w_acc] = t[w_acc] or {}
20           if t[w_acc][1] then t[w_acc][1]=max(t[w_acc][1],d)
21           else t[w_acc][1]=d end
22         end
23         w_acc = w_acc + w
24         x = xn; if x then xn = x.next end
25       end
26     end
27     do
28       local w_acc, h_before = 0, 0
29       local x = after.head; local xn = x.next
30       while x do
31         local w, h
32         if xn then w, h = rangedimensions(after,x,xn)
33         else w, h = rangedimensions(after,x) end
34         if h~=h_before then
35           h_before = h; t[w_acc] = t[w_acc] or {}
36           if t[w_acc][2] then t[w_acc][2]=max(t[w_acc][2],h)
37           else t[w_acc][2]=h end
38         end
39         w_acc = w_acc + w
40         x = xn; if x then xn = x.next end
41       end
42     end
43     local t2 = {}
44     for i,v in pairs(t) do insert(t2, { i, v[1], v[2] } ) end
45     table.sort(t2, function(a,b) return a[1]<b[1] end)
46     do
47       local bls = tex.baselineskip.width
48       local dmax, d, hmax, h, lmin = 0, 0, 0, 0, 1/0
49       for i,v in ipairs(t2) do
50         d, h = (v[2] or d), (v[3] or h)
51         if d>dmax then dmax=d end
52         if h>hmax then hmax=h end
53         if (bls-h-d)<lmin then lmin=bls-h-d end
54       end
55       if lmin==1/0 then lmin = 0 end
56       return lmin, bls - lmin - (before.depth+after.height)
57     end
58   end
59   function lineskip.p_dummy(before, after)
60     return nil, 0
61   end
62 end
63 do
64   local setglue = node.setglue
65   local floor, max = math.floor, math.max
66   function lineskip.l_dummy(dist, g, adj, normal)
67     if dist < tex.lineskiplimit then
68       local ng = tex.lineskip; g.subtype=1
69       setglue(g, ng.width + adj, ng.stretch, ng.shrink, ng.stretch_order, ng.shrink_order)
70     else
71       local ng = tex.baselineskip; g.subtype=2
72       setglue(g, normal, ng.stretch, ng.shrink, ng.stretch_order, ng.shrink_order)
73     end
74   end
75   function lineskip.l_step(dist, g, adj, normal)
76     if dist < tex.lineskiplimit then
77       local ng = tex.baselineskip; g.subtype=1
78       local f = max(1,ng.width*lineskip.step_factor)
79       setglue(g,
80         normal - f * floor((dist-tex.lineskip.width)/f),
81         ng.stretch, ng.shrink, ng.stretch_order, ng.shrink_order)
82     else
83       local ng = tex.baselineskip; g.subtype=2
84       setglue(g, normal, ng.stretch, ng.shrink, ng.stretch_order, ng.shrink_order)
85     end
86   end
87 end
88
89   local l_profiler, l_skip = lineskip.p_dummy, lineskip.l_dummy
90   function lineskip.setting(profiler, skip_method)
91     l_profiler = lineskip['p_'..tostring(profiler)] or lineskip.p_dummy
92     l_skip = lineskip['l_'..tostring(skip_method)] or lineskip.l_dummy
93   end
94   
95 do
96   luatexbase.add_to_callback('post_linebreak_filter',
97     function(h)
98       for x in node.traverse_id(12, h) do
99         if (x.subtype==1)or(x.subtype==2)then
100           local p, n = x.prev, x.next
101           if p then 
102             while ((p.id==14)or(p.id==12)or(p.id==13)) and p.prev do p = p.prev end
103             if p.id==0 and n.id==0 then
104               local normal = tex.baselineskip.width - p.depth - n.height
105               local lmin, adj; lmin, adj = l_profiler(p,n)
106               l_skip(lmin or normal,x,adj, normal)
107             end
108           end
109         end
110       end
111       return true
112     end, 'test', 10000
113   )
114 end
115
116 do
117   local to_direct, to_node = node.direct.todirect, node.direct.tonode
118   local make_dir_whatsit = luatexja.direction.make_dir_whatsit
119   local get_dir_count = luatexja.direction.get_dir_count
120   local function lineskip_append_vlist(b, loc, prev, mirrored)
121      local new_b = to_node(loc=='box' and 
122            make_dir_whatsit(to_direct(b), to_direct(b), get_dir_count(), 'append_vlist')) or b
123      local tail = tex.nest[tex.nest.ptr].tail
124      if tail and tail.id==12 and tail.subtype==3 then
125         tail = tail.prev
126      end
127      if tail and (prev > -65536000) then
128         local normal = tex.baselineskip.width - prev - new_b.height
129         local lmin, adj = nil, 0;
130         if tail.id==0 and new_b.id==0 then
131           if tail.depth==prev then lmin, adj = l_profiler(tail,new_b) end
132         end
133         local g = node.new(12); l_skip(lmin or normal, g, adj, normal)
134         node.write(g)
135       end
136       node.write(new_b)
137       tex.prevdepth = new_b.depth
138       return nil -- do nothing on tex side
139    end
140    luatexbase.remove_from_callback('append_to_vlist_filter','ltj.direction')
141    luatexja.base.add_to_callback('append_to_vlist_filter',
142                         lineskip_append_vlist,
143                         'line profile', 10000)
144 end  
145 \end{luacode}
146 \begin{document}
147 \directlua{%
148   lineskip.step_factor = 0.5
149 }
150
151 % #1: null(TeX 既定) or profile(行の中身を考慮した行間測定)
152 % #2: null(TeX 既定)
153 %   or step(行送りが \baselineskip で十分でなかった場合,
154 %            lineskip.step_factor * \baselineskip の倍数だけ広げて
155 %            行間が \lineskip 以上になるようにする)
156 \def\R#1#2{\directlua{lineskip.setting('#1','#2')}%
157 \noindent\fbox{\parbox{25\zw}{%
158 \baselineskip14pt\noindent
159 \setbox2=\vtop{\noindent\hsize20\zw\textcolor{cyan!30!white}{%
160  □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
161  □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
162  □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
163  □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
164  □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
165  □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
166  □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
167  □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
168  □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
169  □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
170  □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
171  □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
172  □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
173  □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
174  □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
175  □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
176  □□□□■□□□□■□□□□■□□□□■
177 }}\dp2=0pt\rlap{\copy2}\par\vspace*{-\baselineskip}
178 \textbf{#1, #2}\\
179 \vrule height 2pt depth 0pt width 10\zw\\
180 \vrule height 2pt depth 0pt width 10\zw\\
181 \the\baselineskip あああああああああああああああ\\
182 あああああああああ$X_{X_{X_X}}$ああああああ\\
183 ああああああああああああああああああ\\
184 ……であるから$b=\dfrac1{X_2}$となる.\\
185 一方$\dfrac{A^A}{B_B}=21$なので……\\
186 ……であるから$b=\dfrac1{X_2}$となる.\\%\vadjust{あああああ$\dfrac34$}\\
187 一方$\dfrac{A^A}{B_B}=21$なので……
188
189 あいであるから$b=\dfrac1{X_2}$となる.新段落!\\
190 一方$\dfrac{A^A}{B_B}=21$なので……
191
192 \hbox{感じ感じ$\displaystyle\int$}
193 ほげであるから$b=\dfrac1{X_2}$となる.新段落!\\
194 一方$\dfrac{A^A}{B_B}=21$なので……
195
196 \hrule
197 かきであるから$b=\dfrac1{X_2}$となる.hrule無効\\
198 一方$\dfrac{A^A}{B_B}=21$なので……
199
200 \prevdepth0pt
201 うえであるから$b=\dfrac1{X_2}$prevdepth設定のため無効\\
202 一方$\dfrac{A^A}{B_B}=21$なので……
203 }}\newpage}
204
205
206 \R{null}{null}
207 \R{profile}{null}
208 \R{null}{step}
209 \R{profile}{step}
210
211 \end{document}