1if not modules then modules = { } end modules ['pack-rul'] = {
2 version = 1.001,
3 optimize = true,
4 comment = "companion to pack-rul.mkiv",
5 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
6 copyright = "PRAGMA ADE / ConTeXt Development Team",
7 license = "see context related readme files"
8}
9
10
11
12
13
14
15
16
17
18local type = type
19
20local context = context
21
22local nodecodes = nodes.nodecodes
23local listcodes = nodes.listcodes
24
25local hlist_code <const> = nodecodes.hlist
26local vlist_code <const> = nodecodes.vlist
27
28local boxlist_code <const> = listcodes.box
29local linelist_code <const> = listcodes.line
30local equationlist_code <const> = listcodes.equation
31
32local texsetdimen = tex.setdimen
33local texsetcount = tex.setcount
34local texisdimen = tex.isdimen
35local texiscount = tex.iscount
36
37local implement = interfaces.implement
38
39local nuts = nodes.nuts
40
41local getnext = nuts.getnext
42local getprev = nuts.getprev
43local getlist = nuts.getlist
44local setlist = nuts.setlist
45local getwhd = nuts.getwhd
46local getid = nuts.getid
47
48local getbox = nuts.getbox
49local getdirection = nuts.getdirection
50local setshift = nuts.setshift
51local setwidth = nuts.setwidth
52local getwidth = nuts.getwidth
53local setboxglue = nuts.setglue
54local getboxglue = nuts.getglue
55
56local hpack = nuts.hpack
57local getdimensions = nuts.dimensions
58local naturalhsize = nuts.naturalhsize
59local flushnode = nuts.flush
60
61local traversers = nuts.traversers
62local nexthlist = traversers.hlist
63local nextvlist = traversers.vlist
64local nextlist = traversers.list
65
66local checkformath = false
67
68directives.register("framed.checkmath",function(v) checkformath = v end)
69
70
71
72local c_framednoflines <const> = texiscount("framednoflines")
73local d_framedfirstheight <const> = texisdimen("framedfirstheight")
74local d_framedlastdepth <const> = texisdimen("framedlastdepth")
75local d_framedminwidth <const> = texisdimen("framedminwidth")
76local d_framedmaxwidth <const> = texisdimen("framedmaxwidth")
77local d_framedaveragewidth <const> = texisdimen("framedaveragewidth")
78
79local function doreshapeframedbox(n,resync)
80 if resync then
81 resync = drivers.converters.resyncbox
82 end
83 local box = resync and resync(n) or getbox(n)
84 local noflines = 0
85 local nofnonzero = 0
86 local firstheight = nil
87 local lastdepth = nil
88 local lastlinelength = 0
89 local minwidth = 0
90 local maxwidth = 0
91 local totalwidth = 0
92 local averagewidth = 0
93 local boxwidth = getwidth(box)
94
95 if boxwidth ~= 0 then
96 local list = getlist(box)
97 if list then
98 local hdone = false
99 for n, id, subtype, list in nextlist, list do
100 local width, height, depth = getwhd(n)
101 if not firstheight then
102 firstheight = height
103 end
104 lastdepth = depth
105 noflines = noflines + 1
106 if list then
107 if id == hlist_code then
108 if subtype == boxlist_code or subtype == linelist_code then
109
110 local w, c, n = naturalhsize(list)
111 if n then
112
113 w = w - c
114 else
115
116 end
117 lastlinelength = w
118 else
119 lastlinelength = width
120 end
121 hdone = true
122 else
123 lastlinelength = width
124
125 end
126 if lastlinelength > maxwidth then
127 maxwidth = lastlinelength
128 end
129 if lastlinelength < minwidth or minwidth == 0 then
130 minwidth = lastlinelength
131 end
132 if lastlinelength > 0 then
133 nofnonzero = nofnonzero + 1
134 end
135 totalwidth = totalwidth + lastlinelength
136 end
137 end
138 if not firstheight then
139
140 elseif maxwidth ~= 0 then
141 if hdone then
142 for h, id, subtype, list in nextlist, list do
143 if list and id == hlist_code then
144
145 if subtype == boxlist_code or subtype == linelist_code then
146
147
148 local p = hpack(list,maxwidth,'exactly')
149 local set, order, sign = getboxglue(p)
150 setboxglue(h,set,order,sign)
151 setlist(p)
152 flushnode(p)
153 elseif checkformath and subtype == equationlist_code then
154
155 if nofnonzero == 1 then
156 setshift(h,0)
157 end
158 end
159 setwidth(h,maxwidth)
160 end
161 end
162 end
163
164
165
166
167
168
169
170
171 setwidth(box,maxwidth)
172 averagewidth = noflines > 0 and totalwidth/noflines or 0
173 else
174 setwidth(box,0)
175 end
176 end
177 end
178 texsetcount("global",c_framednoflines,noflines)
179 texsetdimen("global",d_framedfirstheight,firstheight or 0)
180 texsetdimen("global",d_framedlastdepth,lastdepth or 0)
181 texsetdimen("global",d_framedminwidth,minwidth)
182 texsetdimen("global",d_framedmaxwidth,maxwidth)
183 texsetdimen("global",d_framedaveragewidth,averagewidth)
184end
185
186local function doanalyzeframedbox(n)
187 local box = getbox(n)
188 local noflines = 0
189 local firstheight = nil
190 local lastdepth = nil
191 if getwidth(box) ~= 0 then
192 local list = getlist(box)
193 if list then
194 for n in nextlist, list do
195 local width, height, depth = getwhd(n)
196 if not firstheight then
197 firstheight = height
198 end
199 lastdepth = depth
200 noflines = noflines + 1
201 end
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218 end
219 end
220 texsetcount("global",c_framednoflines,noflines)
221 texsetdimen("global",d_framedfirstheight,firstheight or 0)
222 texsetdimen("global",d_framedlastdepth,lastdepth or 0)
223end
224
225implement { name = "doreshapeframedbox", actions = doreshapeframedbox, arguments = "integer" }
226implement { name = "doresyncframedbox", actions = doreshapeframedbox, arguments = { "integer", true } }
227implement { name = "doanalyzeframedbox", actions = doanalyzeframedbox, arguments = "integer" }
228
229local function maxboxwidth(box)
230 local boxwidth = getwidth(box)
231 if boxwidth == 0 then
232 return 0
233 end
234 local list = getlist(box)
235 if not list then
236 return 0
237 end
238 if getid(box) == hlist_code then
239 return boxwidth
240 end
241 local lastlinelength = 0
242 local maxwidth = 0
243 for n, subtype in nexthlist, list do
244 local l = getlist(n)
245 if l then
246 if subtype == boxlist_code or subtype == linelist_code then
247 lastlinelength = getdimensions(l)
248 else
249 lastlinelength = getwidth(n)
250 end
251 if lastlinelength > maxwidth then
252 maxwidth = lastlinelength
253 end
254 end
255 end
256 for n, subtype in nextvlist, list do
257 local l = getlist(n)
258 if l then
259 lastlinelength = getwidth(n)
260 if lastlinelength > maxwidth then
261 maxwidth = lastlinelength
262 end
263 end
264 end
265 return maxwidth
266end
267
268nodes.maxboxwidth = maxboxwidth
269
270implement {
271 name = "themaxboxwidth",
272 public = true,
273 actions = function(n) context("%rsp",maxboxwidth(getbox(n))) end,
274 arguments = "integer"
275}
276 |