spac-prf.lua /size: 26 Kb    last modification: 2020-07-01 14:35
1
 
if
not
modules
then
modules
=
{
}
end
modules
[
'
spac-prf
'
]
=
{
2
version
=
1
.
001
,
3
comment
=
"
companion to spac-prf.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
-- This is a playground, a byproduct of some experiments in a project where
10
-- we needed something like this where it works ok, but nevertheless it's
11
-- still experimental code. It is very likely to change (or extended).
12 13
local
unpack
,
rawget
=
unpack
,
rawget
14 15
local
formatters
=
string
.
formatters
16 17
local
nodecodes
=
nodes
.
nodecodes
18
local
gluecodes
=
nodes
.
gluecodes
19
local
listcodes
=
nodes
.
listcodes
20
local
leadercodes
=
nodes
.
leadercodes
21 22
local
glyph_code
=
nodecodes
.
glyph
23
local
disc_code
=
nodecodes
.
disc
24
local
kern_code
=
nodecodes
.
kern
25
local
penalty_code
=
nodecodes
.
penalty
26
local
glue_code
=
nodecodes
.
glue
27
local
hlist_code
=
nodecodes
.
hlist
28
local
vlist_code
=
nodecodes
.
vlist
29
local
unset_code
=
nodecodes
.
unset
30
local
math_code
=
nodecodes
.
math
31
local
rule_code
=
nodecodes
.
rule
32
local
marginkern_code
=
nodecodes
.
marginkern
33 34
local
leaders_code
=
leadercodes
.
leaders
35 36
local
lineskip_code
=
gluecodes
.
lineskip
37
local
baselineskip_code
=
gluecodes
.
baselineskip
38 39
local
linelist_code
=
listcodes
.
line
40 41
local
texlists
=
tex
.
lists
42
local
settexattribute
=
tex
.
setattribute
43 44
local
nuts
=
nodes
.
nuts
45
local
tonut
=
nodes
.
tonut
46
local
tonode
=
nuts
.
tonode
47 48
local
getreplace
=
nuts
.
getreplace
49
local
getattr
=
nuts
.
getattr
50
local
getid
=
nuts
.
getid
51
local
getnext
=
nuts
.
getnext
52
local
getprev
=
nuts
.
getprev
53
local
getsubtype
=
nuts
.
getsubtype
54
local
getlist
=
nuts
.
getlist
55
local
gettexbox
=
nuts
.
getbox
56
local
getwhd
=
nuts
.
getwhd
57
local
getglue
=
nuts
.
getglue
58
local
getkern
=
nuts
.
getkern
59
local
getshift
=
nuts
.
getshift
60
local
getwidth
=
nuts
.
getwidth
61
local
getheight
=
nuts
.
getheight
62
local
getdepth
=
nuts
.
getdepth
63
local
getboxglue
=
nuts
.
getboxglue
64 65
local
setlink
=
nuts
.
setlink
66
local
setlist
=
nuts
.
setlist
67
local
setattr
=
nuts
.
setattr
68
local
setwhd
=
nuts
.
setwhd
69
local
setshift
=
nuts
.
setshift
70
local
setwidth
=
nuts
.
setwidth
71
local
setheight
=
nuts
.
setheight
72
local
setdepth
=
nuts
.
setdepth
73 74
local
properties
=
nodes
.
properties
.
data
75
local
setprop
=
nuts
.
setprop
76
local
getprop
=
nuts
.
getprop
77
local
theprop
=
nuts
.
theprop
78 79
local
floor
=
math
.
floor
80
local
ceiling
=
math
.
ceil
81 82
local
new_rule
=
nuts
.
pool
.
rule
83
local
new_glue
=
nuts
.
pool
.
glue
84
local
new_kern
=
nuts
.
pool
.
kern
85
local
hpack_nodes
=
nuts
.
hpack
86
local
find_node_tail
=
nuts
.
tail
87
local
setglue
=
nuts
.
setglue
88 89
local
a_visual
=
attributes
.
private
(
"
visual
"
)
90
local
a_snapmethod
=
attributes
.
private
(
"
snapmethod
"
)
91
local
a_profilemethod
=
attributes
.
private
(
"
profilemethod
"
)
92
----- a_specialcontent = attributes.private("specialcontent")
93 94
local
variables
=
interfaces
.
variables
95
local
v_none
=
variables
.
none
96
local
v_fixed
=
variables
.
fixed
97
local
v_strict
=
variables
.
strict
98 99
local
setcolor
=
nodes
.
tracers
.
colors
.
set
100
local
settransparency
=
nodes
.
tracers
.
transparencies
.
set
101 102
local
enableaction
=
nodes
.
tasks
.
enableaction
103 104
local
profiling
=
{
}
105
builders
.
profiling
=
profiling
106 107
local
report
=
logs
.
reporter
(
"
profiling
"
)
108 109
local
show_profile
=
false
trackers
.
register
(
"
profiling.show
"
,
function
(
v
)
show_profile
=
v
end
)
110
local
trace_profile
=
false
trackers
.
register
(
"
profiling.trace
"
,
function
(
v
)
trace_profile
=
v
end
)
111 112
local
function
getprofile
(
line
,
step
)
113 114
-- only l2r
115
-- no hz yet
116 117
local
line
=
tonut
(
line
)
118
local
current
=
getlist
(
line
)
119 120
if
not
current
then
121
return
122
end
123 124
local
glue_set
,
glue_order
,
glue_sign
=
getboxglue
(
line
)
125 126
local
heights
=
{
}
127
local
depths
=
{
}
128
local
width
=
0
129
local
position
=
0
130
local
step
=
step
or
65536
-- * 2 -- 2pt
131
local
margin
=
step
/
4
132
local
min
=
0
133
local
max
=
ceiling
(
getwidth
(
line
)
/
step
)
+
1
134
local
wd
=
0
135
local
ht
=
0
136
local
dp
=
0
137 138
for
i
=
min
,
max
do
139
heights
[
i
]
=
0
140
depths
[
i
]
=
0
141
end
142 143
-- remember p
144 145
local
function
progress
(
)
146
position
=
width
147
width
=
position
+
wd
148
p
=
floor
(
(
position
-
margin
)
/
step
+
0
.
5
)
149
w
=
floor
(
(
width
+
margin
)
/
step
-
0
.
5
)
150
if
p
<
0
then
151
p
=
0
152
end
153
if
w
<
0
then
154
w
=
0
155
end
156
if
p
>
w
then
157
w
,
p
=
p
,
w
158
end
159
if
w
>
max
then
160
for
i
=
max
+
1
,
w
+
1
do
161
heights
[
i
]
=
0
162
depths
[
i
]
=
0
163
end
164
max
=
w
165
end
166
for
i
=
p
,
w
do
167
if
ht
>
heights
[
i
]
then
168
heights
[
i
]
=
ht
169
end
170
if
dp
>
depths
[
i
]
then
171
depths
[
i
]
=
dp
172
end
173
end
174
end
175 176
local
function
process
(
current
)
-- called nested in disc replace
177
while
current
do
178
local
id
=
getid
(
current
)
179
if
id
=
=
glyph_code
then
180
wd
,
ht
,
dp
=
getwhd
(
current
)
181
progress
(
)
182
elseif
id
=
=
kern_code
then
183
wd
=
getkern
(
current
)
184
ht
=
0
185
dp
=
0
186
progress
(
)
187
elseif
id
=
=
disc_code
then
188
local
replace
=
getreplace
(
current
)
189
if
replace
then
190
process
(
replace
)
191
end
192
elseif
id
=
=
glue_code
then
193
local
width
,
stretch
,
shrink
,
stretch_order
,
shrink_order
=
getglue
(
current
)
194
if
glue_sign
=
=
1
then
195
if
stretch_order
=
=
glue_order
then
196
wd
=
width
+
stretch
*
glue_set
197
else
198
wd
=
width
199
end
200
elseif
glue_sign
=
=
2
then
201
if
shrink_order
=
=
glue_order
then
202
wd
=
width
-
shrink
*
glue_set
203
else
204
wd
=
width
205
end
206
else
207
wd
=
width
208
end
209
if
getsubtype
(
current
)
>
=
leaders_code
then
210
local
leader
=
getleader
(
current
)
211
local
w
212
w
,
ht
,
dp
=
getwhd
(
leader
)
-- can become getwhd(current) after 1.003
213
else
214
ht
=
0
215
dp
=
0
216
end
217
progress
(
)
218
elseif
id
=
=
hlist_code
then
219
-- we could do a nested check .. but then we need to push / pop glue
220
local
shift
=
getshift
(
current
)
221
local
w
,
h
,
d
=
getwhd
(
current
)
222
-- if getattr(current,a_specialcontent) then
223
if
getprop
(
current
,
"
specialcontent
"
)
then
224
-- like a margin note, maybe check for wd
225
wd
=
w
226
ht
=
0
227
dp
=
0
228
else
229
wd
=
w
230
ht
=
h
-
shift
231
dp
=
d
+
shift
232
end
233
progress
(
)
234
elseif
id
=
=
vlist_code
or
id
=
=
unset_code
then
235
local
shift
=
getshift
(
current
)
-- todo
236
wd
,
ht
,
dp
=
getwhd
(
current
)
237
progress
(
)
238
elseif
id
=
=
rule_code
then
239
wd
,
ht
,
dp
=
getwhd
(
current
)
240
progress
(
)
241
elseif
id
=
=
math_code
then
242
wd
=
getkern
(
current
)
+
getwidth
(
current
)
-- surround
243
ht
=
0
244
dp
=
0
245
progress
(
)
246
elseif
id
=
=
marginkern_code
then
247
-- not in lmtx
248
wd
=
getwidth
(
current
)
249
ht
=
0
250
dp
=
0
251
progress
(
)
252
else
253
-- print(nodecodes[id])
254
end
255
current
=
getnext
(
current
)
256
end
257
end
258 259
process
(
current
)
260 261
return
{
262
heights
=
heights
,
263
depths
=
depths
,
264
min
=
min
,
-- not needed
265
max
=
max
,
266
step
=
step
,
267
}
268 269
end
270 271
profiling
.
get
=
getprofile
272 273
local
function
getpagelist
(
)
274
local
pagehead
=
texlists
.
page_head
275
if
pagehead
then
276
pagehead
=
tonut
(
texlists
.
page_head
)
277
pagetail
=
find_node_tail
(
pagehead
)
278
else
279
pagetail
=
nil
280
end
281
return
pagehead
,
pagetail
282
end
283 284
local
function
setprofile
(
n
,
step
)
285
local
p
=
rawget
(
properties
,
n
)
286
if
p
then
287
local
pp
=
p
.
profile
288
if
not
pp
then
289
pp
=
getprofile
(
n
,
step
)
290
p
.
profile
=
pp
291
end
292
return
pp
293
else
294
local
pp
=
getprofile
(
n
,
step
)
295
properties
[
n
]
=
{
profile
=
pp
}
296
return
pp
297
end
298
end
299 300
local
function
hasprofile
(
n
)
301
local
p
=
rawget
(
properties
,
n
)
302
if
p
then
303
return
p
.
profile
304
end
305
end
306 307
local
function
addstring
(
height
,
depth
)
308
local
typesetters
=
nuts
.
typesetters
309
local
hashes
=
fonts
.
hashes
310
local
infofont
=
fonts
.
infofont
(
)
311
local
emwidth
=
hashes
.
emwidths
[
infofont
]
312
local
exheight
=
hashes
.
exheights
[
infofont
]
313
local
httext
=
height
314
local
dptext
=
depth
315
local
httext
=
typesetters
.
tohpack
(
height
,
infofont
)
316
local
dptext
=
typesetters
.
tohpack
(
depth
,
infofont
)
317
setshift
(
httext
,
-
1
.
2
*
exheight
)
318
setshift
(
dptext
,
0
.
6
*
exheight
)
319
local
text
=
hpack_nodes
(
setlink
(
320
new_kern
(
-
getwidth
(
httext
)
-
emwidth
)
,
321
httext
,
322
new_kern
(
-
getwidth
(
dptext
)
)
,
323
dptext
324
)
)
325
setwhd
(
text
,
0
,
0
,
0
)
326
return
text
327
end
328 329
local
function
addprofile
(
node
,
profile
,
step
)
330 331
local
line
=
tonut
(
node
)
332 333
if
not
profile
then
334
profile
=
setprofile
(
line
,
step
)
335
end
336 337
if
not
profile
then
338
report
(
"
some error
"
)
339
return
node
340
end
341 342
if
profile
.
shown
then
343
return
node
344
end
345 346
local
list
=
getlist
(
line
)
347
profile
.
shown
=
true
348 349
local
heights
=
profile
.
heights
350
local
depths
=
profile
.
depths
351
local
step
=
profile
.
step
352 353
local
head
=
nil
354
local
tail
=
nil
355 356
local
lastht
=
0
357
local
lastdp
=
0
358
local
lastwd
=
0
359 360
local
visual
=
"
f:s:t
"
-- this can change !
361 362
local
function
progress
(
)
363
if
lastwd
=
=
0
then
364
return
365
end
366
local
what
=
nil
367
if
lastht
=
=
0
and
lastdp
=
=
0
then
368
what
=
new_kern
(
lastwd
)
369
else
370
what
=
new_rule
(
lastwd
,
lastht
,
lastdp
)
371
setcolor
(
what
,
visual
)
372
settransparency
(
what
,
visual
)
373
end
374
if
tail
then
375
setlink
(
tail
,
what
)
376
else
377
head
=
what
378
end
379
tail
=
what
380
end
381 382
-- inspect(profile)
383 384
for
i
=
profile
.
min
,
profile
.
max
do
385
local
ht
=
heights
[
i
]
386
local
dp
=
depths
[
i
]
387
if
ht
~
=
lastht
or
dp
~
=
lastdp
and
lastwd
>
0
then
388
progress
(
)
389
lastht
=
ht
390
lastdp
=
dp
391
lastwd
=
step
392
else
393
lastwd
=
lastwd
+
step
394
end
395
end
396
if
lastwd
>
0
then
397
progress
(
)
398
end
399 400
local
rule
=
hpack_nodes
(
head
)
401 402
setwhd
(
rule
,
0
,
0
,
0
)
403 404
-- if texttoo then
405
--
406
-- local text = addstring(
407
-- formatters["%0.4f"](getheight(rule)/65536),
408
-- formatters["%0.4f"](getdepth(rule) /65536)
409
-- )
410
--
411
-- setlink(text,rule)
412
--
413
-- rule = text
414
--
415
-- end
416 417
setlink
(
rule
,
list
)
418
setlist
(
line
,
rule
)
419 420
end
421 422
profiling
.
add
=
addprofile
423 424
local
methods
=
{
}
425 426
local
function
getdelta
(
t_profile
,
b_profile
)
427
local
t_heights
=
t_profile
.
heights
428
local
t_depths
=
t_profile
.
depths
429
local
t_max
=
t_profile
.
max
430
local
b_heights
=
b_profile
.
heights
431
local
b_depths
=
b_profile
.
depths
432
local
b_max
=
b_profile
.
max
433 434
local
max
=
t_max
435
local
delta
=
0
436 437
if
t_max
>
b_max
then
438
for
i
=
b_max
+
1
,
t_max
do
439
b_depths
[
i
]
=
0
440
b_heights
[
i
]
=
0
441
end
442
max
=
t_max
443
elseif
b_max
>
t_max
then
444
for
i
=
t_max
+
1
,
b_max
do
445
t_depths
[
i
]
=
0
446
t_heights
[
i
]
=
0
447
end
448
max
=
b_max
449
end
450 451
for
i
=
0
,
max
do
452
local
ht
=
b_heights
[
i
]
453
local
dp
=
t_depths
[
i
]
454
local
hd
=
ht
+
dp
455
if
hd
>
delta
then
456
delta
=
hd
457
end
458
end
459 460
return
delta
461
end
462 463
-- local properties = theprop(bot)
464
-- local unprofiled = properties.unprofiled
465
-- if not unprofiled then -- experiment
466
-- properties.unprofiled = {
467
-- height = height,
468
-- strutht = strutht,
469
-- }
470
-- end
471 472
-- lineskip | lineskiplimit
473 474
local
function
inject
(
top
,
bot
,
amount
)
-- todo: look at penalties
475
local
glue
=
new_glue
(
amount
)
476
--
477
setattr
(
glue
,
a_profilemethod
,
0
)
478
setattr
(
glue
,
a_visual
,
getattr
(
top
,
a_visual
)
)
479
--
480
setlink
(
top
,
glue
,
bot
)
481
end
482 483
methods
[
v_none
]
=
function
(
)
484
return
false
485
end
486 487
methods
[
v_strict
]
=
function
(
top
,
bot
,
t_profile
,
b_profile
,
specification
)
488 489
local
top
=
tonut
(
top
)
490
local
bot
=
tonut
(
bot
)
491 492
local
strutht
=
specification
.
height
or
texdimen
.
strutht
493
local
strutdp
=
specification
.
depth
or
texdimen
.
strutdp
494
local
lineheight
=
strutht
+
strutdp
495 496
local
depth
=
getdepth
(
top
)
497
local
height
=
getheight
(
bot
)
498
local
total
=
depth
+
height
499
local
distance
=
specification
.
distance
or
0
500
local
delta
=
lineheight
-
total
501 502
-- there is enough room between the lines so we don't need
503
-- to add extra distance
504 505
if
delta
>
=
distance
then
506
inject
(
top
,
bot
,
delta
)
507
return
true
508
end
509 510
local
delta
=
getdelta
(
t_profile
,
b_profile
)
511
local
skip
=
delta
-
total
+
distance
512 513
-- we don't want to be too tight so we limit the skip and
514
-- make sure we have at least lineheight
515 516
inject
(
top
,
bot
,
skip
)
517
return
true
518 519
end
520 521
-- todo: also set ht/dp of first / last (but what is that)
522 523
methods
[
v_fixed
]
=
function
(
top
,
bot
,
t_profile
,
b_profile
,
specification
)
524 525
local
top
=
tonut
(
top
)
526
local
bot
=
tonut
(
bot
)
527 528
local
strutht
=
specification
.
height
or
texdimen
.
strutht
529
local
strutdp
=
specification
.
depth
or
texdimen
.
strutdp
530
local
lineheight
=
strutht
+
strutdp
531 532
local
depth
=
getdepth
(
top
)
533
local
height
=
getheight
(
bot
)
534
local
total
=
depth
+
height
535
local
distance
=
specification
.
distance
or
0
536
local
delta
=
lineheight
-
total
537 538
local
snapmethod
=
getattr
(
top
,
a_snapmethod
)
539 540
if
snapmethod
then
541 542
-- no distance (yet)
543 544
if
delta
<
lineheight
then
545
setdepth
(
top
,
strutdp
)
546
setheight
(
bot
,
strutht
)
547
return
true
548
end
549 550
local
delta
=
getdelta
(
t_profile
,
b_profile
)
551 552
local
dp
=
strutdp
553
while
depth
>
lineheight
-
strutdp
do
554
depth
=
depth
-
lineheight
555
dp
=
dp
+
lineheight
556
end
557
setdepth
(
top
,
dp
)
558
local
ht
=
strutht
559
while
height
>
lineheight
-
strutht
do
560
height
=
height
-
lineheight
561
ht
=
ht
+
lineheight
562
end
563
setheight
(
bot
,
ht
)
564
local
lines
=
floor
(
delta
/
lineheight
)
565
if
lines
>
0
then
566
inject
(
top
,
bot
,
-
lines
*
lineheight
)
567
end
568 569
return
true
570 571
end
572 573
if
total
<
lineheight
then
574
setdepth
(
top
,
strutdp
)
575
setheight
(
bot
,
strutht
)
576
return
true
577
end
578 579
if
depth
<
strutdp
then
580
setdepth
(
top
,
strutdp
)
581
total
=
total
-
depth
+
strutdp
582
end
583
if
height
<
strutht
then
584
setheight
(
bot
,
strutht
)
585
total
=
total
-
height
+
strutht
586
end
587 588
local
delta
=
getdelta
(
t_profile
,
b_profile
)
589 590
local
target
=
total
-
delta
591
local
factor
=
specification
.
factor
or
1
592
local
step
=
lineheight
/
factor
593
local
correction
=
0
594
local
nofsteps
=
0
595
while
correction
<
target
-
step
-
distance
do
-- a loop is more accurate, for now
596
correction
=
correction
+
step
597
nofsteps
=
nofsteps
+
1
598
end
599 600
if
trace_profile
then
601
report
(
"
top line : %s %05i > %s
"
,
t_profile
.
shown
and
"
+
"
or
"
-
"
,
top
,
nodes
.
toutf
(
getlist
(
top
)
)
)
602
report
(
"
bottom line : %s %05i > %s
"
,
b_profile
.
shown
and
"
+
"
or
"
-
"
,
bot
,
nodes
.
toutf
(
getlist
(
bot
)
)
)
603
report
(
"
depth : %p
"
,
depth
)
604
report
(
"
height : %p
"
,
height
)
605
report
(
"
total : %p
"
,
total
)
606
report
(
"
lineheight : %p
"
,
lineheight
)
607
report
(
"
delta : %p
"
,
delta
)
608
report
(
"
target : %p
"
,
target
)
609
report
(
"
factor : %i
"
,
factor
)
610
report
(
"
distance : %p
"
,
distance
)
611
report
(
"
step : %p
"
,
step
)
612
report
(
"
nofsteps : %i
"
,
nofsteps
)
613
-- report(" max lines : %s",lines == 0 and "unset" or lines)
614
report
(
"
correction : %p
"
,
correction
)
615
end
616 617
inject
(
top
,
bot
,
-
correction
)
-- we could mess with the present glue (if present)
618 619
return
true
-- remove interlineglue
620 621
end
622 623
function
profiling
.
distance
(
top
,
bot
,
specification
)
624
local
step
=
specification
.
step
625
local
method
=
specification
.
method
626
local
ptop
=
getprofile
(
top
,
step
)
627
local
pbot
=
getprofile
(
bot
,
step
)
628
local
action
=
methods
[
method
or
v_strict
]
or
methods
[
v_strict
]
629
return
action
(
top
,
bot
,
ptop
,
pbot
,
specification
)
630
end
631 632
local
specifications
=
{
}
-- todo: save these !
633 634
function
profiling
.
fixedprofile
(
current
)
635
local
a
=
getattr
(
current
,
a_profilemethod
)
636
if
a
then
637
local
s
=
specifications
[
a
]
638
if
s
then
639
return
s
.
method
=
=
v_fixed
640
end
641
end
642
return
false
643
end
644 645
local
function
profilelist
(
line
,
mvl
)
646 647
local
current
=
line
648 649
local
top
=
nil
650
local
bot
=
nil
651 652
local
t_profile
=
nil
653
local
b_profile
=
nil
654 655
local
specification
=
nil
656
local
lastattr
=
nil
657
local
method
=
nil
658
local
action
=
nil
659 660
local
distance
=
0
661
local
lastglue
=
nil
662 663
local
pagehead
=
nil
664
local
pagetail
=
nil
665 666
if
mvl
then
667 668
pagehead
,
pagetail
=
getpagelist
(
)
669 670
if
pagetail
then
671
local
current
=
pagetail
672
while
current
do
673
local
id
=
getid
(
current
)
674
if
id
=
=
hlist_code
then
675
local
subtype
=
getsubtype
(
current
)
676
if
subtype
=
=
linelist_code
then
677
t_profile
=
hasprofile
(
current
)
678
if
t_profile
then
679
top
=
current
680
end
681
end
682
break
683
elseif
id
=
=
glue_code
then
684
local
wd
=
getwidth
(
current
)
685
if
not
wd
or
wd
=
=
0
then
686
-- go on
687
else
688
break
689
end
690
elseif
id
=
=
penalty_code
then
691
-- ok
692
else
693
break
694
end
695
current
=
getnext
(
current
)
696
end
697
end
698 699
end
700 701
while
current
do
702 703
local
attr
=
getattr
(
current
,
a_profilemethod
)
704 705
if
attr
then
706 707
if
attr
~
=
lastattr
then
708
specification
=
specifications
[
attr
]
709
method
=
specification
and
specification
.
method
710
action
=
method
and
methods
[
method
]
or
methods
[
v_strict
]
711
lastattr
=
attr
712
end
713 714
local
id
=
getid
(
current
)
715 716
if
id
=
=
hlist_code
then
-- check subtype
717
local
subtype
=
getsubtype
(
current
)
718
if
subtype
=
=
linelist_code
then
719
if
top
=
=
current
then
720
-- skip
721
bot
=
nil
-- to be sure
722
elseif
top
then
723
bot
=
current
724
b_profile
=
setprofile
(
bot
)
725
if
show_profile
then
726
addprofile
(
bot
,
b_profile
)
727
end
728
if
not
t_profile
.
done
then
729
if
action
then
730
local
ok
=
action
(
top
,
bot
,
t_profile
,
b_profile
,
specification
)
731
if
ok
and
lastglue
and
distance
~
=
0
then
732
setglue
(
lastglue
)
733
end
734
end
735
t_profile
.
done
=
true
736
end
737
top
=
bot
738
bot
=
nil
739
t_profile
=
b_profile
740
b_profile
=
nil
741
distance
=
0
742
else
743
top
=
current
744
t_profile
=
setprofile
(
top
)
745
bot
=
nil
746
if
show_profile
then
747
addprofile
(
top
,
t_profile
)
748
end
749
end
750
else
751
top
=
nil
752
bot
=
nil
753
end
754
elseif
id
=
=
glue_code
then
755
if
top
then
756
local
subtype
=
getsubtype
(
current
)
757
-- if subtype == lineskip_code or subtype == baselineskip_code then
758
local
wd
=
getwidth
(
current
)
759
if
wd
>
0
then
760
distance
=
wd
761
lastglue
=
current
762
elseif
wd
<
0
then
763
top
=
nil
764
bot
=
nil
765
else
766
-- ok
767
end
768
-- else
769
-- top = nil
770
-- bot = nil
771
-- end
772
else
773
top
=
nil
774
bot
=
nil
775
end
776
elseif
id
=
=
penalty_code
then
777
-- okay
778
else
779
top
=
nil
780
bot
=
nil
781
end
782
else
783
top
=
nil
784
bot
=
nil
785
end
786
current
=
getnext
(
current
)
787
end
788
if
top
then
789
t_profile
=
setprofile
(
top
)
790
if
show_profile
then
791
addprofile
(
top
,
t_profile
)
792
end
793
end
794
end
795 796
profiling
.
list
=
profilelist
797 798
local
enabled
=
false
799 800
function
profiling
.
set
(
specification
)
801
if
not
enabled
then
802
enableaction
(
"
mvlbuilders
"
,
"
builders.profiling.pagehandler
"
)
803
-- too expensive so we expect that this happens explicitly, we keep for reference:
804
-- enableaction("vboxbuilders","builders.profiling.vboxhandler")
805
enabled
=
true
806
end
807
local
n
=
#
specifications
+
1
808
specifications
[
n
]
=
specification
809
settexattribute
(
a_profilemethod
,
n
)
810
end
811 812
function
profiling
.
profilebox
(
specification
)
813
local
boxnumber
=
specification
.
box
814
local
current
=
getlist
(
gettexbox
(
boxnumber
)
)
815
local
top
=
nil
816
local
bot
=
nil
817
local
t_profile
=
nil
818
local
b_profile
=
nil
819
local
method
=
specification
and
specification
.
method
820
local
action
=
method
and
methods
[
method
]
or
methods
[
v_strict
]
821
local
lastglue
=
nil
822
local
distance
=
0
823
while
current
do
824
local
id
=
getid
(
current
)
825
if
id
=
=
hlist_code
then
826
local
subtype
=
getsubtype
(
current
)
827
if
subtype
=
=
linelist_code
then
828
if
top
then
829
bot
=
current
830
b_profile
=
setprofile
(
bot
)
831
if
show_profile
then
832
addprofile
(
bot
,
b_profile
)
833
end
834
if
not
t_profile
.
done
then
835
if
action
then
836
local
ok
=
action
(
top
,
bot
,
t_profile
,
b_profile
,
specification
)
837
if
ok
and
lastglue
and
distance
~
=
0
then
838
setglue
(
lastglue
)
839
end
840
end
841
t_profile
.
done
=
true
842
end
843
top
=
bot
844
t_profile
=
b_profile
845
b_profile
=
nil
846
distance
=
0
847
else
848
top
=
current
849
t_profile
=
setprofile
(
top
)
850
if
show_profile
then
851
addprofile
(
top
,
t_profile
)
852
end
853
bot
=
nil
854
end
855
else
856
top
=
nil
857
bot
=
nil
858
end
859
elseif
id
=
=
glue_code
then
860
local
subtype
=
getsubtype
(
current
)
861
if
subtype
=
=
lineskip_code
or
subtype
=
=
baselineskip_code
then
862
if
top
then
863
local
wd
=
getwidth
(
current
)
864
if
wd
>
0
then
865
distance
=
wd
866
lastglue
=
current
867
elseif
wd
<
0
then
868
top
=
nil
869
bot
=
nil
870
else
871
-- ok
872
end
873
else
874
top
=
nil
875
bot
=
nil
876
end
877
else
878
top
=
nil
879
bot
=
nil
880
end
881
elseif
id
=
=
penalty_code
then
882
-- okay
883
else
884
top
=
nil
885
bot
=
nil
886
end
887
current
=
getnext
(
current
)
888
end
889 890
if
top
then
891
t_profile
=
setprofile
(
top
)
-- not needed
892
if
show_profile
then
893
addprofile
(
top
,
t_profile
)
894
end
895
end
896 897
end
898 899
-- local ignore = table.tohash {
900
-- "split_keep",
901
-- "split_off",
902
-- -- "vbox",
903
-- }
904
--
905
-- function profiling.vboxhandler(head,where)
906
-- if head and not ignore[where] then
907
-- if getnext(head) then
908
-- profilelist(head)
909
-- end
910
-- end
911
-- return head
912
-- end
913 914
function
profiling
.
pagehandler
(
head
)
915
if
head
then
916
profilelist
(
head
,
true
)
917
end
918
return
head
919
end
920 921
interfaces
.
implement
{
922
name
=
"
setprofile
"
,
923
actions
=
profiling
.
set
,
924
arguments
=
{
925
{
926
{
"
name
"
}
,
927
{
"
height
"
,
"
dimen
"
}
,
928
{
"
depth
"
,
"
dimen
"
}
,
929
{
"
distance
"
,
"
dimen
"
}
,
930
{
"
factor
"
,
"
integer
"
}
,
931
{
"
lines
"
,
"
integer
"
}
,
932
{
"
method
"
}
933
}
934
}
935
}
936 937
interfaces
.
implement
{
938
name
=
"
profilebox
"
,
939
actions
=
profiling
.
profilebox
,
940
arguments
=
{
941
{
942
{
"
box
"
,
"
integer
"
}
,
943
{
"
height
"
,
"
dimen
"
}
,
944
{
"
depth
"
,
"
dimen
"
}
,
945
{
"
distance
"
,
"
dimen
"
}
,
946
{
"
factor
"
,
"
integer
"
}
,
947
{
"
lines
"
,
"
integer
"
}
,
948
{
"
method
"
}
949
}
950
}
951
}
952