1if modules then modules = { } end modules [ ' typo-bld ' ] = {
2 version = 1 . 001 ,
3 comment = " companion to typo-bld.mkiv " ,
4 author = " Hans Hagen, PRAGMA-ADE, Hasselt NL " ,
5 copyright = " PRAGMA ADE / ConTeXt Development Team " ,
6 license = " see context related readme files "
7}
8
9
10
11local insert , remove = table . insert , table . remove
12
13builders = builders or { }
14local builders = builders
15
16builders . paragraphs = builders . paragraphs or { }
17local parbuilders = builders . paragraphs
18
19parbuilders . constructors = parbuilders . constructors or { }
20local constructors = parbuilders . constructors
21
22constructors . names = constructors . names or { }
23local names = constructors . names
24
25constructors . numbers = constructors . numbers or { }
26local numbers = constructors . numbers
27
28constructors . methods = constructors . methods or { }
29local methods = constructors . methods
30
31local a_parbuilder = attributes . numbers [ ' parbuilder ' ] or 999
32constructors . attribute = a_parbuilder
33
34local unsetvalue = attributes . unsetvalue
35local texsetattribute = tex . setattribute
36local texnest = tex . nest
37local texlists = tex . lists
38
39local texget = tex . get
40local texset = tex . set
41
42local texgetdimen = tex . getdimen
43
44local nodes = nodes
45local nodeidstostring = nodes . idstostring
46local nodepool = nodes . pool
47local new_baselineskip = nodepool . baselineskip
48local new_lineskip = nodepool . lineskip
49local insert_node_before = nodes . insert_before
50local hpack_node = nodes . hpack
51
52local nuts = nodes . nuts
53local tonode = nodes . tonode
54local tonut = nodes . tonut
55local count_nodes = nuts . countall
56local getattr = nuts . getattr
57
58local starttiming = statistics . starttiming
59local stoptiming = statistics . stoptiming
60
61local registercallback = callbacks . register
62
63storage . register ( " builders/paragraphs/constructors/names " , names , " builders.paragraphs.constructors.names " )
64storage . register ( " builders/paragraphs/constructors/numbers " , numbers , " builders.paragraphs.constructors.numbers " )
65
66local trace_page_builder = false trackers . register ( " builders.page " , function ( v ) trace_page_builder = v end )
67local trace_vbox_builder = false trackers . register ( " builders.vbox " , function ( v ) trace_vbox_builder = v end )
68local trace_post_builder = false trackers . register ( " builders.post " , function ( v ) trace_post_builder = v end )
69
70local report_page_builder = logs . reporter ( " builders " , " page " )
71local report_vbox_builder = logs . reporter ( " builders " , " vbox " )
72local report_par_builder = logs . reporter ( " builders " , " par " )
73
74local mainconstructor = nil
75local nofconstructors = 0
76local stack = { }
77
78function constructors . define ( name )
79 nofconstructors = nofconstructors + 1
80 names [ nofconstructors ] = name
81 numbers [ name ] = nofconstructors
82end
83
84function constructors . set ( name )
85 if name then
86 mainconstructor = numbers [ name ] or unsetvalue
87 else
88 mainconstructor = stack [ # stack ] or unsetvalue
89 end
90 texsetattribute ( a_parbuilder , mainconstructor )
91 if mainconstructor ~ = unsetvalue then
92 constructors . enable ( )
93 end
94end
95
96function constructors . start ( name )
97 local number = numbers [ name ]
98 insert ( stack , number )
99 mainconstructor = number or unsetvalue
100 texsetattribute ( a_parbuilder , mainconstructor )
101 if mainconstructor ~ = unsetvalue then
102 constructors . enable ( )
103 end
104
105end
106
107function constructors . stop ( )
108 remove ( stack )
109 mainconstructor = stack [ # stack ] or unsetvalue
110 texsetattribute ( a_parbuilder , mainconstructor )
111 if mainconstructor = = unsetvalue then
112 constructors . disable ( )
113 end
114
115end
116
117
118
119
120
121
122
123function constructors . handler ( head , followed_by_display )
124 if type ( head ) = = " boolean " then
125 return head
126 else
127 local attribute = getattr ( head , a_parbuilder )
128 if attribute then
129 local method = names [ attribute ]
130 if method then
131 local handler = methods [ method ]
132 if handler then
133 return handler ( head , followed_by_display )
134 else
135 report_par_builder ( " contructor method %a is not defined " , tostring ( method ) )
136 return true
137 end
138 end
139 end
140 return true
141 end
142end
143
144
145
146function constructors . methods . default ( head , followed_by_display )
147 return true
148end
149
150
151
152function parbuilders . constructors . methods . oneline ( head , followed_by_display )
153
154 local t = texnest [ texnest . ptr ]
155 local h = hpack_node ( head )
156 local d = texget ( " baselineskip " , false ) - t . prevdepth - h . height
157 t . prevdepth = h . depth
158 t . prevgraf = 1
159 if d < texget ( " lineskiplimit " ) then
160 return insert_node_before ( h , h , new_lineskip ( texget ( " lineskip " , false ) ) )
161 else
162 return insert_node_before ( h , h , new_baselineskip ( d ) )
163 end
164end
165
166
167
168
169
170
171
172
173local actions = constructors . handler
174local enabled = false
175
176local function processor ( head , followed_by_display )
177
178 if enabled then
179 starttiming ( parbuilders )
180 head = tonut ( head )
181 head = actions ( head , followed_by_display )
182 head = tonode ( head )
183 stoptiming ( parbuilders )
184 return head
185 else
186 return true
187 end
188end
189
190function constructors . enable ( ) enabled = true end
191function constructors . disable ( ) enabled = false end
192
193registercallback ( ' linebreak_filter ' , processor , " breaking paragraps into lines " )
194
195statistics . register ( " linebreak processing time " , function ( )
196 return statistics . elapsedseconds ( parbuilders )
197end )
198
199
200
201nodes . builders = nodes . builder or { }
202local builders = nodes . builders
203
204local vboxactions = nodes . tasks . actions ( " vboxbuilders " )
205
206function builders . vpack_filter ( head , groupcode , size , packtype , maxdepth , direction )
207 local done = false
208 if head then
209 starttiming ( builders )
210 head = tonut ( head )
211 if trace_vbox_builder then
212 local before = count_nodes ( head )
213 head , done = vboxactions ( head , groupcode , size , packtype , maxdepth , direction )
214 local after = count_nodes ( head )
215 nodes . processors . tracer ( " vpack " , head , groupcode , before , after , done )
216 else
217 head , done = vboxactions ( head , groupcode )
218 end
219 head = tonode ( head )
220 stoptiming ( builders )
221 end
222 return head , done
223end
224
225
226
227
228local pageactions = nodes . tasks . actions ( " mvlbuilders " )
229
230
231local function report ( groupcode , head )
232 report_page_builder ( " trigger: %s " , groupcode )
233 report_page_builder ( " vsize : %p " , texget ( " vsize " ) )
234 report_page_builder ( " pagegoal : %p " , texget ( " pagegoal " ) )
235 report_page_builder ( " pagetotal: %p " , texget ( " pagetotal " ) )
236 report_page_builder ( " list : %s " , head and nodeidstostring ( head ) or " <empty> " )
237end
238
239
240
241
242
243
244
245function builders . buildpage_filter ( groupcode )
246
247 local head = texlists . contrib_head
248 local done = false
249 if head then
250
251 starttiming ( builders )
252 if trace_page_builder then
253 report ( groupcode , head )
254 end
255 head , done = pageactions ( head , groupcode )
256 stoptiming ( builders )
257
258
259 texlists . contrib_head = head or nil
260
261 return done and head or true
262 else
263
264 if trace_page_builder then
265 report ( groupcode )
266 end
267
268 return nil
269 end
270end
271
272registercallback ( ' vpack_filter ' , builders . vpack_filter , " vertical spacing etc " )
273registercallback ( ' buildpage_filter ' , builders . buildpage_filter , " vertical spacing etc (mvl) " )
274
275statistics . register ( " v-node processing time " , function ( )
276 return statistics . elapsedseconds ( builders )
277end )
278
279local implement = interfaces . implement
280
281implement { name = " defineparbuilder " , actions = constructors . define , arguments = " string " }
282implement { name = " setparbuilder " , actions = constructors . set , arguments = " string " }
283implement { name = " startparbuilder " , actions = constructors . start , arguments = " string " }
284implement { name = " stopparbuilder " , actions = constructors . stop }
285implement { name = " enableparbuilder " , actions = constructors . enable }
286implement { name = " disableparbuilder " , actions = constructors . disable }
287
288
289
290local nuts = nodes . nuts
291local tonut = nodes . tonut
292local setcolor = nodes . tracers . colors . set
293local listtoutf = nodes . listtoutf
294local new_kern = nuts . pool . kern
295local new_rule = nuts . pool . rule
296local hpack = nuts . hpack
297local getheight = nuts . getheight
298local getdepth = nuts . getdepth
299local getdirection = nuts . getdirection
300local getlist = nuts . getlist
301local setwidth = nuts . setwidth
302local setdirection = nuts . setdirection
303local setlink = nuts . setlink
304local tonode = nuts . tonode
305
306local report_hpack = logs . reporter ( " hpack routine " )
307local report_vpack = logs . reporter ( " vpack routine " )
308
309
310
311local function vpack_quality ( how , n , detail , first , last )
312 if last < = 0 then
313 report_vpack ( " %s vbox " , how )
314 elseif first > 0 and first < last then
315 report_vpack ( " %s vbox at line %i - %i " , how , first , last )
316 else
317 report_vpack ( " %s vbox at line %i " , how , last )
318 end
319end
320
321trackers . register ( " builders.vpack.quality " , function ( v )
322 registercallback ( " vpack_quality " , v and report_vpack_quality or nil , " check vpack quality " )
323end )
324
325local report , show = false , false
326
327local function hpack_quality ( how , detail , n , first , last )
328 n = tonut ( n )
329 if report then
330 local str = listtoutf ( getlist ( n ) , " " , true , nil , true )
331 if last < = 0 then
332 report_hpack ( " %s hbox: %s " , how , str )
333 elseif first > 0 and first < last then
334 report_hpack ( " %s hbox at line %i - %i: %s " , how , first , last , str )
335 else
336 report_hpack ( " %s hbox at line %i: %s " , how , last , str )
337 end
338 end
339 if show then
340 local width = 2 * 65536
341 local height = getheight ( n )
342 local depth = getdepth ( n )
343 local direction = getdirection ( n )
344 if height < 4 * 65526 then
345 height = 4 * 65526
346 end
347 if depth < 2 * 65526 then
348 depth = 2 * 65526
349 end
350 local rule = new_rule ( width , height , depth )
351 setdirection ( rule , direction )
352 if how = = " overfull " then
353 setcolor ( rule , " red " )
354 local kern = new_kern ( - detail )
355 setlink ( kern , rule )
356 rule = kern
357 elseif how = = " underfull " then
358 setcolor ( rule , " blue " )
359 elseif how = = " loose " then
360 setcolor ( rule , " magenta " )
361 elseif how = = " tight " then
362 setcolor ( rule , " cyan " )
363 end
364 rule = hpack ( rule )
365 setwidth ( rule , 0 )
366 setdirection ( rule , direction )
367 return tonode ( rule )
368 end
369end
370
371trackers . register ( " builders.hpack.quality " , function ( v )
372 report = v
373 registercallback ( " hpack_quality " , ( report or show ) and hpack_quality or nil , " check hpack quality " )
374end )
375
376trackers . register ( " builders.hpack.overflow " , function ( v )
377 show = v
378 registercallback ( " hpack_quality " , ( report or show ) and hpack_quality or nil , " check hpack quality " )
379end )
380 |