trac-vis.lmt /size: 61 Kb    last modification: 2021-10-28 13:51
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
trac-vis
'
]
=
{
2
version
=
1
.
001
,
3
optimize
=
true
,
4
comment
=
"
companion to trac-vis.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
local
node
,
nodes
,
attributes
,
tex
=
node
,
nodes
,
attributes
,
tex
11
local
type
,
tonumber
,
next
,
rawget
=
type
,
tonumber
,
next
,
rawget
12
local
gmatch
,
gsub
=
string
.
gmatch
,
string
.
gsub
13
local
formatters
=
string
.
formatters
14
local
round
=
math
.
round
15 16
-- This module started out in the early days of mkiv and luatex with visualizing
17
-- kerns related to fonts. In the process of cleaning up the visual debugger code it
18
-- made sense to integrate some other code that I had laying around and replace the
19
-- old supp-vis debugging code. As only a subset of the old visual debugger makes
20
-- sense it has become a different implementation. Soms of the m-visual
21
-- functionality will also be ported. The code is rather trivial. The caching is not
22
-- really needed but saves upto 50% of the time needed to add visualization. Of
23
-- course the overall runtime is larger because of color and layer processing in the
24
-- backend (can be times as much) so the runtime is somewhat larger with full
25
-- visualization enabled. In practice this will never happen unless one is demoing.
26 27
-- todo: global switch (so no attributes)
28
-- todo: maybe also xoffset, yoffset of glyph
29
-- todo: inline concat (more efficient)
30
-- todo: tags can also be numbers (just add to hash)
31
-- todo: make a lmtx variant (a few more efficient fetchers)
32 33
local
nuts
=
nodes
.
nuts
34
local
tonut
=
nuts
.
tonut
35 36
local
setboth
=
nuts
.
setboth
37
local
setlink
=
nuts
.
setlink
38
local
setlist
=
nuts
.
setlist
39
local
setsubtype
=
nuts
.
setsubtype
40
local
setattr
=
nuts
.
setattr
41
local
setwidth
=
nuts
.
setwidth
42
local
setshift
=
nuts
.
setshift
43 44
local
getid
=
nuts
.
getid
45
local
getfont
=
nuts
.
getfont
46
local
getattr
=
nuts
.
getattr
47
local
getsubtype
=
nuts
.
getsubtype
48
local
getbox
=
nuts
.
getbox
49
local
getlist
=
nuts
.
getlist
50
local
getnext
=
nuts
.
getnext
51
local
getboth
=
nuts
.
getboth
52
local
getwhd
=
nuts
.
getwhd
53
local
getkern
=
nuts
.
getkern
54
local
getwidth
=
nuts
.
getwidth
55
local
getdepth
=
nuts
.
getdepth
56
local
getexpansion
=
nuts
.
getexpansion
57
local
getstate
=
nuts
.
getstate
58
local
getoffsets
=
nuts
.
getoffsets
59
local
getindex
=
nuts
.
getindex
60 61
local
isglyph
=
nuts
.
isglyph
62 63
local
hpack_nodes
=
nuts
.
hpack
64
local
vpack_nodes
=
nuts
.
vpack
65
local
copylist
=
nuts
.
copylist
66
local
copy_node
=
nuts
.
copy
67
local
insertnodebefore
=
nuts
.
insertbefore
68
local
insertnodeafter
=
nuts
.
insertafter
69
local
apply_to_nodes
=
nuts
.
apply
70
local
flushnodelist
=
nuts
.
flushlist
71 72
local
hpack_string
=
nuts
.
typesetters
.
tohpack
73 74
local
texgetattribute
=
tex
.
getattribute
75
local
texsetattribute
=
tex
.
setattribute
76 77
local
setmetatableindex
=
table
.
setmetatableindex
78 79
local
unsetvalue
=
attributes
.
unsetvalue
80 81
local
current_font
=
font
.
current
82 83
local
fonthashes
=
fonts
.
hashes
84
local
chardata
=
fonthashes
.
characters
85
local
exheights
=
fonthashes
.
exheights
86
local
emwidths
=
fonthashes
.
emwidths
87
local
pt_factor
=
number
.
dimenfactors
.
pt
88 89
local
nodepool
=
nuts
.
pool
90
local
new_rule
=
nodepool
.
rule
91
local
new_kern
=
nodepool
.
kern
92
local
new_glue
=
nodepool
.
glue
93
local
new_hlist
=
nodepool
.
hlist
94
local
new_vlist
=
nodepool
.
vlist
95 96
local
tracers
=
nodes
.
tracers
97
local
visualizers
=
nodes
.
visualizers
98 99
local
setcolor
=
tracers
.
colors
.
set
100
local
setlistcolor
=
tracers
.
colors
.
setlist
101
local
settransparency
=
tracers
.
transparencies
.
set
102
local
setlisttransparency
=
tracers
.
transparencies
.
setlist
103 104
local
starttiming
=
statistics
.
starttiming
105
local
stoptiming
=
statistics
.
stoptiming
106 107
local
a_visual
=
attributes
.
private
(
"
visual
"
)
108
local
a_layer
=
attributes
.
private
(
"
viewerlayer
"
)
109 110
local
enableaction
=
nodes
.
tasks
.
enableaction
111 112
local
report_visualize
=
logs
.
reporter
(
"
visualize
"
)
113 114
local
modes
=
{
115
hbox
=
0x0000001
,
116
vbox
=
0x0000002
,
117
vtop
=
0x0000004
,
118
kern
=
0x0000008
,
119
glue
=
0x0000010
,
120
penalty
=
0x0000020
,
121
fontkern
=
0x0000040
,
122
strut
=
0x0000080
,
123
whatsit
=
0x0000100
,
124
glyph
=
0x0000200
,
125
simple
=
0x0000400
,
126
simplehbox
=
0x0000401
,
127
simplevbox
=
0x0000402
,
128
simplevtop
=
0x0000404
,
129
user
=
0x0000800
,
130
math
=
0x0001000
,
131
italic
=
0x0002000
,
132
origin
=
0x0004000
,
133
discretionary
=
0x0008000
,
134
expansion
=
0x0010000
,
135
line
=
0x0020000
,
136
space
=
0x0040000
,
137
depth
=
0x0080000
,
138
marginkern
=
0x0100000
,
139
mathlistkern
=
0x0200000
,
140
dir
=
0x0400000
,
141
par
=
0x0800000
,
142
mathglue
=
0x1000000
,
143
mark
=
0x2000000
,
144
insert
=
0x4000000
,
145
}
146 147
visualizers
.
modes
=
modes
148 149
local
usedfont
,
exheight
,
emwidth
150
local
l_penalty
,
l_glue
,
l_kern
,
l_fontkern
,
l_hbox
,
l_vbox
,
l_vtop
,
l_strut
,
l_whatsit
,
l_glyph
,
l_user
,
l_math
,
l_marginkern
,
l_mathlistkern
,
l_italic
,
l_origin
,
l_discretionary
,
l_expansion
,
l_line
,
l_space
,
l_depth
,
151
l_dir
,
l_whatsit
,
l_mark
,
l_insert
152 153
local
enabled
=
false
154
local
layers
=
{
}
155 156
local
preset_boxes
=
modes
.
hbox
+
modes
.
vbox
+
modes
.
vtop
+
modes
.
origin
157
local
preset_makeup
=
preset_boxes
158
+
modes
.
kern
+
modes
.
glue
+
modes
.
penalty
159
local
preset_all
=
preset_makeup
160
+
modes
.
fontkern
+
modes
.
marginkern
+
modes
.
mathlistkern
161
+
modes
.
whatsit
+
modes
.
glyph
+
modes
.
user
+
modes
.
math
162
+
modes
.
dir
+
modes
.
whatsit
+
modes
.
mathglue
163
+
modes
.
mark
+
modes
.
insert
164 165
function
visualizers
.
setfont
(
id
)
166
usedfont
=
id
or
current_font
(
)
167
exheight
=
exheights
[
usedfont
]
168
emwidth
=
emwidths
[
usedfont
]
169
end
170 171
-- we can preset a bunch of bits
172 173
local
userrule
-- bah, not yet defined: todo, delayed(nuts.rules,"userrule")
174
local
outlinerule
-- bah, not yet defined: todo, delayed(nuts.rules,"userrule")
175
local
emptyrule
-- bah, not yet defined: todo, delayed(nuts.rules,"userrule")
176 177
local
function
initialize
(
)
178
--
179
if
not
usedfont
then
180
-- we use a narrow monospaced font -- infofont ?
181
visualizers
.
setfont
(
fonts
.
definers
.
define
{
name
=
"
lmmonoltcond10regular
"
,
size
=
tex
.
sp
(
"
4pt
"
)
}
)
182
end
183
--
184
for
mode
,
value
in
next
,
modes
do
185
local
tag
=
formatters
[
"
v_%s
"
]
(
mode
)
186
attributes
.
viewerlayers
.
define
{
187
tag
=
tag
,
188
title
=
formatters
[
"
visualizer %s
"
]
(
mode
)
,
189
visible
=
"
start
"
,
190
editable
=
"
yes
"
,
191
printable
=
"
yes
"
192
}
193
layers
[
mode
]
=
attributes
.
viewerlayers
.
register
(
tag
,
true
)
194
end
195
l_hbox
=
layers
.
hbox
196
l_vbox
=
layers
.
vbox
197
l_vtop
=
layers
.
vtop
198
l_glue
=
layers
.
glue
199
l_kern
=
layers
.
kern
200
l_penalty
=
layers
.
penalty
201
l_fontkern
=
layers
.
fontkern
202
l_strut
=
layers
.
strut
203
l_whatsit
=
layers
.
whatsit
204
l_glyph
=
layers
.
glyph
205
l_user
=
layers
.
user
206
l_math
=
layers
.
math
207
l_italic
=
layers
.
italic
208
l_marginkern
=
layers
.
marginkern
209
l_mathlistkern
=
layers
.
mathlistkern
210
l_origin
=
layers
.
origin
211
l_discretionary
=
layers
.
discretionary
212
l_expansion
=
layers
.
expansion
213
l_line
=
layers
.
line
214
l_space
=
layers
.
space
215
l_depth
=
layers
.
depth
216
l_dir
=
layers
.
dir
217
l_par
=
layers
.
par
218
l_mark
=
layers
.
mark
219
l_insert
=
layers
.
insert
220
--
221
if
not
userrule
then
222
userrule
=
nuts
.
rules
.
userrule
223
end
224
--
225
if
not
outlinerule
then
226
outlinerule
=
nuts
.
pool
.
outlinerule
227
end
228
--
229
if
not
emptyrule
then
230
emptyrule
=
nuts
.
pool
.
emptyrule
231
end
232
initialize
=
false
233
end
234 235
local
function
enable
(
)
236
if
initialize
then
237
initialize
(
)
238
end
239
enableaction
(
"
shipouts
"
,
"
nodes.visualizers.handler
"
)
240
report_visualize
(
"
enabled
"
)
241
enabled
=
true
242
tex
.
setcount
(
"
global
"
,
"
c_syst_visualizers_state
"
,
1
)
-- so that we can optimize at the tex end
243
end
244 245
local
function
setvisual
(
n
,
a
,
what
,
list
)
-- this will become more efficient when we have the bit lib linked in
246
if
not
n
or
n
=
=
"
reset
"
then
247
return
unsetvalue
248
elseif
n
=
=
true
or
n
=
=
"
makeup
"
then
249
if
not
a
or
a
=
=
0
or
a
=
=
unsetvalue
then
250
a
=
preset_makeup
251
else
252
a
=
a
|
preset_makeup
253
end
254
elseif
n
=
=
"
boxes
"
then
255
if
not
a
or
a
=
=
0
or
a
=
=
unsetvalue
then
256
a
=
preset_boxes
257
else
258
a
=
a
|
preset_boxes
259
end
260
elseif
n
=
=
"
all
"
then
261
if
what
=
=
false
then
262
return
unsetvalue
263
elseif
not
a
or
a
=
=
0
or
a
=
=
unsetvalue
then
264
a
=
preset_all
265
else
266
a
=
a
|
preset_all
267
end
268
elseif
type
(
n
)
=
=
"
string
"
then
269
for
s
in
gmatch
(
n
,
"
[a-z]+
"
)
do
270
local
m
=
modes
[
s
]
271
if
not
m
then
272
-- go on
273
elseif
not
a
or
a
=
=
0
or
a
=
=
unsetvalue
then
274
a
=
m
275
else
276
a
=
a
|
m
277
end
278
end
279
elseif
type
(
n
)
=
=
"
number
"
then
280
if
not
a
or
a
=
=
0
or
a
=
=
unsetvalue
then
281
a
=
n
282
else
283
a
=
a
|
n
284
end
285
end
286
if
not
a
or
a
=
=
0
or
a
=
=
unsetvalue
then
287
return
unsetvalue
288
elseif
not
enabled
then
-- must happen at runtime (as we don't store layers yet)
289
enable
(
)
290
end
291
return
a
292
end
293 294
function
nuts
.
setvisual
(
n
,
mode
)
295
setattr
(
n
,
a_visual
,
setvisual
(
mode
,
getattr
(
n
,
a_visual
)
,
true
)
)
296
end
297 298
function
nuts
.
setvisuals
(
n
,
mode
)
-- currently the same
299
setattr
(
n
,
a_visual
,
setvisual
(
mode
,
getattr
(
n
,
a_visual
)
,
true
,
true
)
)
300
end
301 302
-- fast setters
303 304
do
305 306
local
cached
=
setmetatableindex
(
function
(
t
,
k
)
307
if
k
=
=
true
then
308
return
texgetattribute
(
a_visual
)
309
elseif
not
k
then
310
t
[
k
]
=
unsetvalue
311
return
unsetvalue
312
else
313
local
v
=
setvisual
(
k
)
314
t
[
k
]
=
v
315
return
v
316
end
317
end
)
318 319
-- local function applyvisuals(n,mode)
320
-- local a = cached[mode]
321
-- apply_to_nodes(n,function(n) setattr(n,a_visual,a) end)
322
-- end
323 324
local
a
=
unsetvalue
325 326
local
f
=
function
(
n
)
setattr
(
n
,
a_visual
,
a
)
end
327 328
local
function
applyvisuals
(
n
,
mode
)
329
a
=
cached
[
mode
]
330
apply_to_nodes
(
n
,
f
)
331
end
332 333
nuts
.
applyvisuals
=
applyvisuals
334 335
function
nodes
.
applyvisuals
(
n
,
mode
)
336
applyvisuals
(
tonut
(
n
)
,
mode
)
337
end
338 339
function
visualizers
.
attribute
(
mode
)
340
return
cached
[
mode
]
341
end
342 343
visualizers
.
attributes
=
cached
344 345
end
346 347
function
nuts
.
copyvisual
(
n
,
m
)
348
setattr
(
n
,
a_visual
,
getattr
(
m
,
a_visual
)
)
349
end
350 351
function
visualizers
.
setvisual
(
n
)
352
texsetattribute
(
a_visual
,
setvisual
(
n
,
texgetattribute
(
a_visual
)
)
)
353
end
354 355
function
visualizers
.
setlayer
(
n
)
356
texsetattribute
(
a_layer
,
layers
[
n
]
or
unsetvalue
)
357
end
358 359
local
function
set
(
mode
,
v
)
360
texsetattribute
(
a_visual
,
setvisual
(
mode
,
texgetattribute
(
a_visual
)
,
v
)
)
361
end
362 363
for
mode
,
value
in
next
,
modes
do
364
trackers
.
register
(
formatters
[
"
visualizers.%s
"
]
(
mode
)
,
function
(
v
)
set
(
mode
,
v
)
end
)
365
end
366 367
local
fraction
=
10
368
local
normalize
=
true
369 370
trackers
.
register
(
"
visualizers.reset
"
,
function
(
v
)
set
(
"
reset
"
,
v
)
end
)
371
trackers
.
register
(
"
visualizers.all
"
,
function
(
v
)
set
(
"
all
"
,
v
)
end
)
372
trackers
.
register
(
"
visualizers.makeup
"
,
function
(
v
)
set
(
"
makeup
"
,
v
)
end
)
373
trackers
.
register
(
"
visualizers.boxes
"
,
function
(
v
)
set
(
"
boxes
"
,
v
)
end
)
374
directives
.
register
(
"
visualizers.fraction
"
,
function
(
v
)
fraction
=
(
v
and
tonumber
(
v
)
)
or
(
v
=
=
"
more
"
and
5
)
or
10
end
)
375 376
-- we can just paste verbatim together .. no typesetting needed
377 378
local
function
sometext
(
str
,
layer
,
color
,
textcolor
,
lap
,
variant
)
379
local
text
=
hpack_string
(
str
,
usedfont
)
380
local
size
=
getwidth
(
text
)
381
local
rule
=
new_rule
(
size
,
2
*
exheight
,
exheight
/
2
)
382
local
kern
=
new_kern
(
-
size
)
383
if
color
then
384
setcolor
(
rule
,
color
)
385
end
386
if
textcolor
then
387
setlistcolor
(
getlist
(
text
)
,
textcolor
)
388
end
389
local
info
=
setlink
(
rule
,
kern
,
text
)
390
setlisttransparency
(
info
,
"
trace:g
"
)
391
info
=
hpack_nodes
(
info
)
392
local
width
=
getwidth
(
info
)
393
if
variant
then
394
nuts
.
setoffsets
(
info
,
0
,
variant
*
exheight
)
395
end
396
if
lap
then
397
info
=
new_hlist
(
setlink
(
new_kern
(
-
width
)
,
info
)
)
398
else
399
info
=
new_hlist
(
info
)
-- a bit overkill: double wrapped
400
end
401
if
layer
then
402
setattr
(
info
,
a_layer
,
layer
)
403
end
404
return
info
,
width
405
end
406 407
local
function
someblob
(
str
,
layer
,
color
,
textcolor
,
width
)
408
local
text
=
hpack_string
(
str
,
usedfont
)
409
local
size
=
getwidth
(
text
)
410
local
rule
=
new_rule
(
width
,
2
*
exheight
,
exheight
/
2
)
411
local
kern
=
new_kern
(
-
width
+
(
width
-
size
)
/
2
)
412
if
color
then
413
setcolor
(
rule
,
color
)
414
end
415
if
textcolor
then
416
setlistcolor
(
getlist
(
text
)
,
textcolor
)
417
end
418
local
info
=
setlink
(
rule
,
kern
,
text
)
419
setlisttransparency
(
info
,
"
trace:g
"
)
420
info
=
hpack_nodes
(
info
)
421
local
width
=
getwidth
(
info
)
422
info
=
new_hlist
(
info
)
423
if
layer
then
424
setattr
(
info
,
a_layer
,
layer
)
425
end
426
return
info
,
width
427
end
428 429
local
caches
=
setmetatableindex
(
"
table
"
)
430 431
local
fontkern
,
italickern
,
marginkern
,
mathlistkern
do
432 433
local
f_cache
=
caches
[
"
fontkern
"
]
434
local
i_cache
=
caches
[
"
italickern
"
]
435
local
m_cache
=
caches
[
"
marginkern
"
]
436
local
l_cache
=
caches
[
"
mathlistkern
"
]
437 438
local
function
somekern
(
head
,
current
,
cache
,
color
,
layer
)
439
local
width
=
getkern
(
current
)
440
local
extra
=
getexpansion
(
current
)
441
local
kern
=
width
+
extra
442
local
info
=
cache
[
kern
]
443
if
not
info
then
444
local
text
=
hpack_string
(
formatters
[
"
%0.3f
"
]
(
kern
*
pt_factor
)
,
usedfont
)
445
local
rule
=
new_rule
(
emwidth
/
fraction
,
6
*
exheight
,
2
*
exheight
)
446
local
list
=
getlist
(
text
)
447
if
kern
>
0
then
448
setlistcolor
(
list
,
"
trace:db
"
)
449
elseif
kern
<
0
then
450
setlistcolor
(
list
,
"
trace:dr
"
)
451
else
452
setlistcolor
(
list
,
"
trace:dg
"
)
453
end
454
setlisttransparency
(
list
,
color
)
455
setcolor
(
rule
,
color
)
456
settransparency
(
rule
,
color
)
457
setshift
(
text
,
-5
*
exheight
)
458
info
=
new_hlist
(
setlink
(
rule
,
text
)
)
459
setattr
(
info
,
a_layer
,
layer
)
460
f_cache
[
kern
]
=
info
461
end
462
head
=
insertnodebefore
(
head
,
current
,
copylist
(
info
)
)
463
return
head
,
current
464
end
465 466
fontkern
=
function
(
head
,
current
)
467
return
somekern
(
head
,
current
,
f_cache
,
"
trace:ds
"
,
l_fontkern
)
468
end
469 470
italickern
=
function
(
head
,
current
)
471
return
somekern
(
head
,
current
,
i_cache
,
"
trace:do
"
,
l_italic
)
472
end
473 474
marginkern
=
function
(
head
,
current
)
475
return
somekern
(
head
,
current
,
m_cache
,
"
trace:do
"
,
l_marginkern
)
476
end
477 478
mathlistkern
=
function
(
head
,
current
)
479
return
somekern
(
head
,
current
,
l_cache
,
"
trace:do
"
,
l_mathlistkern
)
480
end
481 482
end
483 484
local
ruledglyphexpansion
do
485 486
local
f_cache
=
caches
[
"
glyphexpansion
"
]
487 488
ruledglyphexpansion
=
function
(
head
,
current
)
489
local
extra
=
getexpansion
(
current
)
490
if
extra
and
extra
~
=
0
then
491
extra
=
extra
/
1000
492
local
info
=
f_cache
[
extra
]
493
if
not
info
then
494
local
text
=
hpack_string
(
round
(
extra
)
,
usedfont
)
495
local
rule
=
new_rule
(
emwidth
/
fraction
,
exheight
,
2
*
exheight
)
496
local
list
=
getlist
(
text
)
497
if
extra
>
0
then
498
setlistcolor
(
list
,
"
trace:db
"
)
499
elseif
extra
<
0
then
500
setlistcolor
(
list
,
"
trace:dr
"
)
501
end
502
setlisttransparency
(
list
,
"
trace:ds
"
)
503
setcolor
(
rule
,
"
trace:ds
"
)
504
settransparency
(
rule
,
"
trace:ds
"
)
505
setshift
(
text
,
1
.
5
*
exheight
)
506
info
=
new_hlist
(
setlink
(
rule
,
text
)
)
507
setattr
(
info
,
a_layer
,
l_expansion
)
508
f_cache
[
extra
]
=
info
509
end
510
head
=
insertnodebefore
(
head
,
current
,
copylist
(
info
)
)
511
return
head
,
current
512
end
513
return
head
,
current
514
end
515 516
end
517 518
local
kernexpansion
do
519 520
local
f_cache
=
caches
[
"
kernexpansion
"
]
521 522
-- in mkiv we actually need to reconstruct but let's not do that now
523 524
kernexpansion
=
function
(
head
,
current
)
525
local
extra
=
getexpansion
(
current
)
526
if
extra
~
=
0
then
527
extra
=
extra
/
1000
528
local
info
=
f_cache
[
extra
]
529
if
not
info
then
530
local
text
=
hpack_string
(
round
(
extra
)
,
usedfont
)
531
local
rule
=
new_rule
(
emwidth
/
fraction
,
exheight
,
4
*
exheight
)
532
local
list
=
getlist
(
text
)
533
if
extra
>
0
then
534
setlistcolor
(
list
,
"
trace:db
"
)
535
elseif
extra
<
0
then
536
setlistcolor
(
list
,
"
trace:dr
"
)
537
end
538
setlisttransparency
(
list
,
"
trace:ds
"
)
539
setcolor
(
rule
,
"
trace:ds
"
)
540
settransparency
(
rule
,
"
trace:ds
"
)
541
setshift
(
text
,
3
.
5
*
exheight
)
542
info
=
new_hlist
(
setlink
(
rule
,
text
)
)
543
setattr
(
info
,
a_layer
,
l_expansion
)
544
f_cache
[
extra
]
=
info
545
end
546
head
=
insertnodebefore
(
head
,
current
,
copylist
(
info
)
)
547
return
head
,
current
548
end
549
return
head
,
current
550
end
551 552
end
553 554
local
ruledmark
do
555 556
local
set_code
=
nodes
.
markcodes
.
set
557 558
local
sm_cache
=
setmetatableindex
(
caches
[
"
setmark
"
]
,
function
(
t
,
index
)
559
local
info
=
sometext
(
formatters
[
"
SM:%i
"
]
(
index
)
,
usedfont
,
nil
,
"
trace:w
"
)
-- whatsit
560
setattr
(
info
,
a_layer
,
l_mark
)
561
t
[
index
]
=
info
562
return
info
563
end
)
564 565
local
rm_cache
=
setmetatableindex
(
caches
[
"
resetmark
"
]
,
function
(
t
,
index
)
566
local
info
=
sometext
(
formatters
[
"
RM:%i
"
]
(
index
)
,
usedfont
,
nil
,
"
trace:w
"
)
-- whatsit
567
setattr
(
info
,
a_layer
,
l_mark
)
568
t
[
index
]
=
info
569
return
info
570
end
)
571 572
ruledmark
=
function
(
head
,
current
)
573
local
index
=
getindex
(
current
)
574
local
info
=
getsubtype
(
current
)
=
=
set_code
and
sm_cache
[
index
]
or
rm_cache
[
index
]
575
head
,
current
=
insertnodeafter
(
head
,
current
,
copylist
(
info
)
)
576
return
head
,
current
577
end
578 579
end
580 581
local
ruledinsert
do
582 583
local
si_cache
=
setmetatableindex
(
caches
[
"
insert
"
]
,
function
(
f
,
index
)
584
local
info
=
sometext
(
formatters
[
"
SI:%i
"
]
(
index
)
,
usedfont
,
nil
,
"
trace:w
"
)
-- whatsit
585
setattr
(
info
,
a_layer
,
l_insert
)
586
i_cache
[
index
]
=
info
587
end
)
588 589
ruledinsert
=
function
(
head
,
current
)
590
local
info
=
si_cache
[
getindex
(
current
)
]
591
head
,
current
=
insertnodeafter
(
head
,
current
,
copylist
(
info
)
)
592
return
head
,
current
593
end
594 595
end
596 597
local
ruledwhatsit
do
598 599
local
whatsitcodes
=
nodes
.
whatsitcodes
600
local
w_cache
=
caches
[
"
whatsit
"
]
601 602
local
tags
=
{
603
[
whatsitcodes
.
open
]
=
"
OPN
"
,
604
[
whatsitcodes
.
write
]
=
"
WRI
"
,
605
[
whatsitcodes
.
close
]
=
"
CLS
"
,
606
-- [whatsitcodes.special] = "SPE",
607
[
whatsitcodes
.
latelua
]
=
"
LUA
"
,
608
[
whatsitcodes
.
savepos
]
=
"
POS
"
,
609
[
whatsitcodes
.
userdefined
]
=
"
USR
"
,
610
[
whatsitcodes
.
literal
]
=
"
LIT
"
,
611
[
whatsitcodes
.
setmatrix
]
=
"
MAT
"
,
612
[
whatsitcodes
.
save
]
=
"
SAV
"
,
613
[
whatsitcodes
.
restore
]
=
"
RES
"
,
614
[
whatsitcodes
.
startscaling
]
=
"
+SCA
"
,
615
[
whatsitcodes
.
stopscaling
]
=
"
-SCA
"
,
616
[
whatsitcodes
.
startrotation
]
=
"
+ROT
"
,
617
[
whatsitcodes
.
stoprotation
]
=
"
-ROT
"
,
618
[
whatsitcodes
.
startmirroring
]
=
"
+MIR
"
,
619
[
whatsitcodes
.
stopmirroring
]
=
"
-MIR
"
,
620
[
whatsitcodes
.
startclipping
]
=
"
+CLP
"
,
621
[
whatsitcodes
.
stopclipping
]
=
"
-CLP
"
,
622
[
whatsitcodes
.
startmatrix
]
=
"
+MAT
"
,
623
[
whatsitcodes
.
stopmatrix
]
=
"
-MAT
"
,
624
[
whatsitcodes
.
setstate
]
=
"
SET
"
,
-- can't happen because these are added after visualizing
625
}
626 627
ruledwhatsit
=
function
(
head
,
current
)
628
local
what
=
getsubtype
(
current
)
629
local
info
=
w_cache
[
what
]
630
if
info
then
631
-- print("hit whatsit")
632
else
633
info
=
sometext
(
formatters
[
"
W:%s
"
]
(
tags
[
what
]
or
what
)
,
usedfont
,
nil
,
"
trace:w
"
)
634
setattr
(
info
,
a_layer
,
l_whatsit
)
635
w_cache
[
what
]
=
info
636
end
637
head
,
current
=
insertnodeafter
(
head
,
current
,
copylist
(
info
)
)
638
return
head
,
current
639
end
640 641
end
642 643
local
ruleddir
,
ruledpar
do
644 645
local
dircodes
=
nodes
.
dircodes
646
local
dirvalues
=
nodes
.
dirvalues
647 648
local
cancel_code
=
dircodes
.
cancel
649
local
l2r_code
=
dirvalues
.
l2r
650
local
r2l_code
=
dirvalues
.
r2l
651 652
local
d_cache
=
caches
[
"
dir
"
]
653 654
local
getdirection
=
nuts
.
getdirection
655 656
local
tags
=
{
657
l2r
=
"
L2R
"
,
658
r2l
=
"
R2L
"
,
659
cancel
=
"
CAN
"
,
660
par
=
"
PAR
"
,
661
}
662 663
ruledpar
=
function
(
head
,
current
)
664
local
what
=
"
par
"
-- getsubtype(current)
665
local
info
=
d_cache
[
what
]
666
if
info
then
667
-- print("hit par")
668
else
669
info
=
sometext
(
formatters
[
"
L:%s
"
]
(
what
)
,
usedfont
,
nil
,
"
trace:w
"
)
670
setattr
(
info
,
a_layer
,
l_dir
)
671
d_cache
[
what
]
=
info
672
end
673
head
,
current
=
insertnodeafter
(
head
,
current
,
copylist
(
info
)
)
674
return
head
,
current
675
end
676 677
ruleddir
=
function
(
head
,
current
)
678
local
what
=
getsubtype
(
current
)
679
if
what
=
=
cancel_code
then
680
what
=
"
cancel
"
681
elseif
getdirection
(
current
)
=
=
r2l_code
then
682
what
=
"
r2l
"
683
else
684
what
=
"
l2r
"
685
end
686
local
info
=
d_cache
[
what
]
687
if
info
then
688
-- print("hit dir")
689
else
690
info
=
sometext
(
formatters
[
"
D:%s
"
]
(
what
)
,
usedfont
,
nil
,
"
trace:w
"
)
691
setattr
(
info
,
a_layer
,
l_dir
)
692
d_cache
[
what
]
=
info
693
end
694
head
,
current
=
insertnodeafter
(
head
,
current
,
copylist
(
info
)
)
695
return
head
,
current
696
end
697 698
end
699 700
local
ruleduser
do
701 702
local
u_cache
=
caches
[
"
user
"
]
703 704
ruleduser
=
function
(
head
,
current
)
705
local
what
=
getsubtype
(
current
)
706
local
info
=
u_cache
[
what
]
707
if
info
then
708
-- print("hit user")
709
else
710
info
=
sometext
(
formatters
[
"
U:%s
"
]
(
what
)
,
usedfont
)
711
setattr
(
info
,
a_layer
,
l_user
)
712
u_cache
[
what
]
=
info
713
end
714
head
,
current
=
insertnodeafter
(
head
,
current
,
copylist
(
info
)
)
715
return
head
,
current
716
end
717 718
end
719 720
local
ruledmath
do
721 722
local
mathcodes
=
nodes
.
mathcodes
723
local
m_cache
=
{
724
beginmath
=
caches
[
"
bmath
"
]
,
725
endmath
=
caches
[
"
emath
"
]
,
726
}
727
local
tags
=
{
728
beginmath
=
"
B
"
,
729
endmath
=
"
E
"
,
730
}
731 732
ruledmath
=
function
(
head
,
current
)
733
local
what
=
getsubtype
(
current
)
734
local
tag
=
mathcodes
[
what
]
735
local
skip
=
getkern
(
current
)
+
getwidth
(
current
)
-- surround
736
local
info
=
m_cache
[
tag
]
[
skip
]
737
if
info
then
738
-- print("hit math")
739
else
740
local
text
,
width
=
sometext
(
formatters
[
"
M:%s
"
]
(
tag
and
tags
[
tag
]
or
what
)
,
usedfont
,
nil
,
"
trace:dr
"
)
741
local
rule
=
new_rule
(
skip
,
-655360
/
fraction
,
2
*
655360
/
fraction
)
742
local
dist
=
tag
=
=
"
beginmath
"
and
width
or
skip
743
setcolor
(
rule
,
"
trace:dr
"
)
744
settransparency
(
rule
,
"
trace:dr
"
)
745
setattr
(
rule
,
a_layer
,
l_math
)
746
info
=
new_hlist
(
setlink
(
new_glue
(
-
skip
)
,
rule
,
new_glue
(
-
dist
)
,
text
)
)
747
setattr
(
info
,
a_layer
,
l_math
)
748
m_cache
[
tag
]
[
skip
]
=
info
749
end
750
head
,
current
=
insertnodeafter
(
head
,
current
,
copylist
(
info
)
)
751
return
head
,
current
752
end
753 754
end
755 756
local
ruleddepth
do
757 758
ruleddepth
=
function
(
current
,
wd
,
ht
,
dp
)
759
local
wd
,
ht
,
dp
=
getwhd
(
current
)
760
if
dp
~
=
0
then
761
local
rule
=
new_rule
(
wd
,
0
,
dp
)
762
setcolor
(
rule
,
"
trace:o
"
)
763
settransparency
(
rule
,
"
trace:g
"
)
764
setattr
(
rule
,
a_layer
,
l_depth
)
765
setlist
(
current
,
setlink
(
rule
,
new_kern
(
-
wd
)
,
getlist
(
current
)
)
)
766
end
767
end
768 769
end
770 771
local
ruledbox
do
772 773
local
b_cache
=
caches
[
"
box
"
]
774
local
o_cache
=
caches
[
"
origin
"
]
775 776
local
getshift
=
nuts
.
getshift
777 778
setmetatableindex
(
o_cache
,
function
(
t
,
size
)
779
local
rule
=
new_rule
(
2
*
size
,
size
,
size
)
780
local
origin
=
hpack_nodes
(
rule
)
781
setcolor
(
rule
,
"
trace:do
"
)
782
settransparency
(
rule
,
"
trace:do
"
)
783
setattr
(
rule
,
a_layer
,
l_origin
)
784
t
[
size
]
=
origin
785
return
origin
786
end
)
787 788
ruledbox
=
function
(
head
,
current
,
vertical
,
layer
,
what
,
simple
,
previous
,
trace_origin
,
parent
)
789
local
wd
,
ht
,
dp
=
getwhd
(
current
)
790
local
force_origin
=
wd
=
=
0
or
(
dp
+
ht
)
=
=
0
791
local
shift
=
getshift
(
current
)
792
local
next
=
getnext
(
current
)
793
local
prev
=
previous
794
setboth
(
current
)
795
local
linewidth
=
emwidth
/
fraction
796
local
size
=
2
*
linewidth
797
local
this
798
if
not
simple
then
799
this
=
b_cache
[
what
]
800
if
not
this
then
801
local
text
=
hpack_string
(
what
,
usedfont
)
802
this
=
setlink
(
new_kern
(
-
getwidth
(
text
)
)
,
text
)
803
setlisttransparency
(
this
,
"
trace:s
"
)
804
this
=
new_hlist
(
this
)
805
b_cache
[
what
]
=
this
806
end
807
end
808
-- we need to trigger the right mode (else sometimes no whatits)
809
local
info
=
setlink
(
810
this
and
copylist
(
this
)
or
nil
,
811
(
force_origin
and
emptyrule
(
wd
,
ht
,
dp
)
)
-- we accept some overhead
812
or
(
dp
=
=
0
and
outlinerule
and
outlinerule
(
wd
,
ht
,
dp
,
linewidth
)
)
813
or
userrule
{
814
width
=
wd
,
815
height
=
ht
,
816
depth
=
dp
,
817
line
=
linewidth
,
818
type
=
"
box
"
,
819
dashed
=
3
*
size
,
820
}
821
)
822
--
823
setlisttransparency
(
info
,
"
trace:s
"
)
824
info
=
new_hlist
(
info
)
-- important
825
--
826
setattr
(
info
,
a_layer
,
layer
)
827
if
vertical
then
828
if
not
force_origin
and
shift
=
=
0
then
829
info
=
setlink
(
current
,
dp
~
=
0
and
new_kern
(
-
dp
)
or
nil
,
info
)
830
elseif
trace_origin
or
force_origin
then
831
local
size
=
2
*
size
832
local
origin
=
o_cache
[
size
]
833
origin
=
copylist
(
origin
)
834
if
getid
(
parent
)
=
=
vlist_code
then
835
setshift
(
origin
,
-
shift
)
836
info
=
setlink
(
current
,
new_kern
(
-
size
)
,
origin
,
new_kern
(
-
size
-
dp
)
,
info
)
837
else
838
-- todo .. i need an example
839
info
=
setlink
(
current
,
dp
~
=
0
and
new_kern
(
-
dp
)
or
nil
,
info
)
840
end
841
setshift
(
current
,
0
)
842
else
843
info
=
setlink
(
current
,
new_dp
~
=
0
and
new_kern
(
-
dp
)
or
nil
,
info
)
844
setshift
(
current
,
0
)
845
end
846
info
=
new_vlist
(
info
,
wd
,
ht
,
dp
,
shift
)
847
else
848
if
not
force_origin
and
shift
=
=
0
then
849
info
=
setlink
(
current
,
new_kern
(
-
wd
)
,
info
)
850
elseif
trace_origin
or
force_origin
then
851
local
size
=
2
*
size
852
local
origin
=
o_cache
[
size
]
853
origin
=
copylist
(
origin
)
854
if
getid
(
parent
)
=
=
vlist_code
then
855
info
=
setlink
(
current
,
new_kern
(
-
wd
-
size
-
shift
)
,
origin
,
new_kern
(
-
size
+
shift
)
,
info
)
856
else
857
setshift
(
origin
,
-
shift
)
858
info
=
setlink
(
current
,
new_kern
(
-
wd
-
size
)
,
origin
,
new_kern
(
-
size
)
,
info
)
859
end
860
setshift
(
current
,
0
)
861
else
862
info
=
setlink
(
current
,
new_kern
(
-
wd
)
,
info
)
863
setshift
(
current
,
0
)
864
end
865
info
=
new_hlist
(
info
,
wd
,
ht
,
dp
,
shift
)
866
end
867
if
next
then
868
setlink
(
info
,
next
)
869
end
870
if
prev
and
prev
>
0
then
871
setlink
(
prev
,
info
)
872
end
873
if
head
=
=
current
then
874
return
info
,
info
875
else
876
return
head
,
info
877
end
878
-- else
879
-- return head, current
880
-- end
881
end
882 883
end
884 885
local
ruledglyph
do
886 887
-- see boundingbox feature .. maybe a pdf stream is more efficient, after all we
888
-- have a frozen color anyway or i need a more detailed cache .. below is a more
889
-- texie approach
890 891
-- local ligature_code = 0x8000 + nodes.glyphcodes.ligature
892 893
ruledglyph
=
function
(
head
,
current
,
previous
)
-- wrong for vertical glyphs
894
local
wd
=
getwidth
(
current
)
895
if
wd
~
=
0
then
896
local
wd
,
ht
,
dp
=
getwhd
(
current
)
897
local
next
=
getnext
(
current
)
898
local
prev
=
previous
899
setboth
(
current
)
900
local
linewidth
=
emwidth
/
(
2
*
fraction
)
901
local
x_offset
,
y_offset
,
l_margin
,
r_margin
,
raise
=
getoffsets
(
current
)
902
local
info
=
setlink
(
(
dp
=
=
0
and
outlinerule
and
outlinerule
(
wd
,
ht
,
dp
,
linewidth
)
)
or
userrule
{
903
width
=
wd
,
904
height
=
ht
,
905
depth
=
dp
,
906
line
=
linewidth
,
907
type
=
"
box
"
,
908
}
,
new_kern
(
-
wd
)
)
909
-- if getsubtype(n) == ligature_code then
910
local
c
,
f
=
isglyph
(
current
)
911
local
char
=
chardata
[
f
]
[
c
]
912
if
char
and
type
(
char
.
unicode
)
=
=
"
table
"
then
-- hackery test
913
setlistcolor
(
info
,
"
trace:s
"
)
914
setlisttransparency
(
info
,
"
trace:ds
"
)
915
else
916
setlistcolor
(
info
,
"
trace:o
"
)
917
setlisttransparency
(
info
,
"
trace:do
"
)
918
end
919
info
=
new_hlist
(
info
)
920
setattr
(
info
,
a_layer
,
l_glyph
)
921
local
info
=
setlink
(
current
,
new_kern
(
-
wd
)
,
info
)
922
info
=
hpack_nodes
(
info
)
923
setwidth
(
info
,
wd
)
924
if
next
then
925
setlink
(
info
,
next
)
926
end
927
if
prev
then
928
setlink
(
prev
,
info
)
929
end
930
if
head
=
=
current
then
931
return
info
,
info
932
else
933
return
head
,
info
934
end
935
else
936
return
head
,
current
937
end
938
end
939 940
function
visualizers
.
setruledglyph
(
f
)
941
ruledglyph
=
f
or
ruledglyph
942
end
943 944
end
945 946
local
ruledglue
,
ruledmathglue
do
947 948
local
effectiveglue
=
nuts
.
effectiveglue
949 950
local
gluecodes
=
nodes
.
gluecodes
951 952
local
userskip_code
=
gluecodes
.
userskip
953
local
spaceskip_code
=
gluecodes
.
spaceskip
954
local
xspaceskip_code
=
gluecodes
.
xspaceskip
955
local
zerospaceskip_code
=
gluecodes
.
zerospaceskip
or
gluecodes
.
userskip
956
-- local keepskip_code = gluecodes.keepskip or gluecodes.userskip
957
local
leftskip_code
=
gluecodes
.
leftskip
958
local
rightskip_code
=
gluecodes
.
rightskip
959
local
lefthangskip_code
=
gluecodes
.
lefthangskip
960
local
righthangskip_code
=
gluecodes
.
righthangskip
961
local
parfillleftskip_code
=
gluecodes
.
parfillleftskip
or
parfillskip_code
962
local
parfillrightskip_code
=
gluecodes
.
parfillrightskip
or
parfillskip_code
963
local
indentskip_code
=
gluecodes
.
indentskip
964
local
intermathskip_code
=
gluecodes
.
intermathskip
965
local
correctionskip_code
=
gluecodes
.
correctionskip
966
local
tabskip_code
=
gluecodes
.
tabskip
967 968
local
g_cache_v
=
caches
[
"
vglue
"
]
969
local
g_cache_h
=
caches
[
"
hglue
"
]
970
local
g_cache_ls
=
caches
[
"
leftskip
"
]
971
local
g_cache_rs
=
caches
[
"
rightskip
"
]
972
local
g_cache_lh
=
caches
[
"
lefthang
"
]
973
local
g_cache_rh
=
caches
[
"
righthang
"
]
974
local
g_cache_lp
=
caches
[
"
parfillleftskip
"
]
975
local
g_cache_rp
=
caches
[
"
parfillrightskip
"
]
976
local
g_cache_is
=
caches
[
"
indentskip
"
]
977
local
g_cache_cs
=
caches
[
"
correctionskip
"
]
978
local
g_cache_gn
=
caches
[
"
gluename
"
]
979 980
local
tags
=
{
981
-- [userskip_code] = "US",
982
[
gluecodes
.
lineskip
]
=
"
LI
"
,
983
[
gluecodes
.
baselineskip
]
=
"
BS
"
,
984
[
gluecodes
.
parskip
]
=
"
PS
"
,
985
[
gluecodes
.
abovedisplayskip
]
=
"
DA
"
,
986
[
gluecodes
.
belowdisplayskip
]
=
"
DB
"
,
987
[
gluecodes
.
abovedisplayshortskip
]
=
"
SA
"
,
988
[
gluecodes
.
belowdisplayshortskip
]
=
"
SB
"
,
989
[
gluecodes
.
topskip
]
=
"
TS
"
,
990
[
gluecodes
.
splittopskip
]
=
"
ST
"
,
991
[
tabskip_code
]
=
"
TB
"
,
992
[
gluecodes
.
thinmuskip
]
=
"
MS
"
,
993
[
gluecodes
.
medmuskip
]
=
"
MM
"
,
994
[
gluecodes
.
thickmuskip
]
=
"
ML
"
,
995
[
intermathskip_code
]
=
"
IM
"
,
996
[
gluecodes
.
keepskip
or
99
]
=
"
KS
"
,
997
[
gluecodes
.
mathskip
]
=
"
MT
"
,
998
[
gluecodes
.
leaders
]
=
"
NL
"
,
999
[
gluecodes
.
cleaders
]
=
"
CL
"
,
1000
[
gluecodes
.
xleaders
]
=
"
XL
"
,
1001
[
gluecodes
.
gleaders
]
=
"
GL
"
,
1002
-- true = "VS",
1003
-- false = "HS",
1004
[
leftskip_code
]
=
"
LS
"
,
1005
[
rightskip_code
]
=
"
RS
"
,
1006
[
lefthangskip_code
]
=
"
LH
"
,
1007
[
righthangskip_code
]
=
"
RH
"
,
1008
[
spaceskip_code
]
=
"
SP
"
,
1009
[
xspaceskip_code
]
=
"
XS
"
,
1010
[
zerospaceskip_code
]
=
"
ZS
"
,
1011
[
parfillleftskip_code
]
=
"
PL
"
,
1012
[
parfillrightskip_code
]
=
"
PR
"
,
1013
[
indentskip_code
]
=
"
IN
"
,
1014
[
correctionskip_code
]
=
"
CS
"
,
1015
}
1016 1017
local
stags
=
{
1018
[
lefthangskip_code
]
=
0
.
5
,
1019
[
righthangskip_code
]
=
0
.
5
,
1020
[
leftskip_code
]
=
-2
,
1021
[
rightskip_code
]
=
-2
,
1022
[
parfillleftskip_code
]
=
-0
.
75
,
1023
[
parfillrightskip_code
]
=
-0
.
75
,
1024
}
1025 1026
-- we sometimes pass previous as we can have issues in math (not watertight for all)
1027 1028
local
f_amount
=
formatters
[
"
%s:%0.3f
"
]
1029
local
mathvalues
=
nodes
.
mathvalues
1030 1031
local
function
gluename
(
name
,
layer
,
color
)
1032
local
info
=
g_cache_gn
[
name
]
1033
if
not
info
then
1034
local
text
=
hpack_string
(
(
gsub
(
mathvalues
[
name
]
,
"
spacing
"
,
"
"
)
)
,
usedfont
)
1035
local
rule
=
new_rule
(
emwidth
/
fraction
,
2
*
exheight
,
2
.
75
*
exheight
)
1036
local
list
=
getlist
(
text
)
1037
setlisttransparency
(
list
,
color
)
1038
settransparency
(
rule
,
color
)
1039
setshift
(
text
,
2
*
exheight
)
1040
info
=
new_hlist
(
setlink
(
rule
,
text
)
)
1041
setattr
(
info
,
a_layer
,
layer
)
1042
g_cache_gn
[
name
]
=
info
1043
end
1044
return
copylist
(
info
)
1045
end
1046 1047
ruledmathglue
=
function
(
head
,
current
)
1048
return
insertnodebefore
(
head
,
current
,
gluename
(
getfont
(
current
)
,
l_glue
,
"
trace:m
"
)
)
1049
end
1050 1051
ruledglue
=
function
(
head
,
current
,
vertical
,
parent
)
1052
local
subtype
=
getsubtype
(
current
)
1053
local
width
=
effectiveglue
(
current
,
parent
)
1054
local
stag
=
normalize
and
stags
[
subtype
]
1055
local
amount
=
f_amount
(
tags
[
subtype
]
or
(
vertical
and
"
VS
"
)
or
"
HS
"
,
width
*
pt_factor
)
-- can be sped up
1056
local
info
=
(
vertical
and
g_cache_v
or
g_cache_h
)
[
amount
]
1057
if
subtype
=
=
intermathskip_code
then
1058
head
=
ruledmathglue
(
head
,
current
)
1059
end
1060
if
info
then
1061
-- print("glue hit")
1062
else
1063
if
subtype
=
=
spaceskip_code
or
subtype
=
=
xspaceskip_code
or
subtype
=
=
zerospaceskip_code
then
1064
info
=
sometext
(
amount
,
l_glue
,
"
trace:y
"
)
1065
elseif
subtype
=
=
userskip_code
then
1066
if
width
>
0
then
1067
info
=
sometext
(
amount
,
l_glue
,
"
trace:b
"
)
1068
elseif
width
<
0
then
1069
info
=
sometext
(
amount
,
l_glue
,
"
trace:r
"
)
1070
else
1071
info
=
sometext
(
amount
,
l_glue
,
"
trace:g
"
)
1072
end
1073
elseif
subtype
=
=
tabskip_code
then
1074
info
=
sometext
(
amount
,
l_glue
,
"
trace:s
"
)
1075
elseif
subtype
=
=
indentskip_code
or
subtype
=
=
correctionskip_code
then
1076
info
=
sometext
(
amount
,
l_glue
,
"
trace:s
"
)
1077
elseif
subtype
=
=
leftskip_code
then
1078
info
=
sometext
(
amount
,
l_glue
,
normalize
and
"
trace:y
"
or
"
trace:c
"
,
false
,
true
,
stag
)
1079
elseif
subtype
=
=
rightskip_code
then
1080
info
=
sometext
(
amount
,
l_glue
,
normalize
and
"
trace:y
"
or
"
trace:c
"
,
false
,
false
,
stag
)
1081
elseif
subtype
=
=
lefthangskip_code
then
1082
info
=
sometext
(
amount
,
l_glue
,
normalize
and
"
trace:y
"
or
"
trace:m
"
,
false
,
true
,
stag
)
1083
elseif
subtype
=
=
righthangskip_code
then
1084
info
=
sometext
(
amount
,
l_glue
,
normalize
and
"
trace:y
"
or
"
trace:m
"
,
false
,
false
,
stag
)
1085
elseif
subtype
=
=
parfillleftskip_code
then
1086
info
=
sometext
(
amount
,
l_glue
,
"
trace:s
"
,
false
,
true
,
stag
)
1087
elseif
subtype
=
=
parfillrightskip_code
then
1088
info
=
sometext
(
amount
,
l_glue
,
"
trace:s
"
,
false
,
false
,
stag
)
1089
else
1090
info
=
sometext
(
amount
,
l_glue
,
"
trace:m
"
)
1091
end
1092
(
vertical
and
g_cache_v
or
g_cache_h
)
[
amount
]
=
info
1093
end
1094
info
=
copylist
(
info
)
1095
if
vertical
then
1096
info
=
vpack_nodes
(
info
)
1097
end
1098
head
,
current
=
insertnodebefore
(
head
,
current
,
info
)
1099
return
head
,
getnext
(
current
)
1100
end
1101 1102
local
g_cache_s
=
caches
[
"
space
"
]
1103
local
g_cache_x
=
caches
[
"
xspace
"
]
1104 1105
ruledspace
=
function
(
head
,
current
,
parent
)
1106
local
subtype
=
getsubtype
(
current
)
1107
local
width
=
effectiveglue
(
current
,
parent
)
1108
local
info
1109
if
subtype
=
=
spaceskip_code
then
1110
info
=
g_cache_s
[
width
]
1111
if
not
info
then
1112
info
=
someblob
(
"
SP
"
,
l_glue
,
"
trace:y
"
,
nil
,
width
)
1113
g_cache_s
[
width
]
=
info
1114
end
1115
else
1116
info
=
g_cache_x
[
width
]
1117
if
not
info
then
1118
info
=
someblob
(
"
XS
"
,
l_glue
,
"
trace:m
"
,
nil
,
width
)
1119
g_cache_x
[
width
]
=
info
1120
end
1121
end
1122
info
=
copylist
(
info
)
1123
head
,
current
=
insertnodebefore
(
head
,
current
,
info
)
1124
return
head
,
getnext
(
current
)
1125
end
1126 1127
end
1128 1129
local
ruledkern
do
1130 1131
local
k_cache_v
=
caches
[
"
vkern
"
]
1132
local
k_cache_h
=
caches
[
"
hkern
"
]
1133 1134
ruledkern
=
function
(
head
,
current
,
vertical
,
mk
)
1135
local
kern
=
getkern
(
current
)
1136
local
cache
=
vertical
and
k_cache_v
or
k_cache_h
1137
local
info
=
cache
[
kern
]
1138
if
not
info
then
1139
local
amount
=
formatters
[
"
%s:%0.3f
"
]
(
vertical
and
"
VK
"
or
(
mk
and
"
MK
"
)
or
"
HK
"
,
kern
*
pt_factor
)
1140
if
kern
>
0
then
1141
info
=
sometext
(
amount
,
l_kern
,
"
trace:b
"
)
1142
elseif
kern
<
0
then
1143
info
=
sometext
(
amount
,
l_kern
,
"
trace:r
"
)
1144
else
1145
info
=
sometext
(
amount
,
l_kern
,
"
trace:g
"
)
1146
end
1147
cache
[
kern
]
=
info
1148
end
1149
info
=
copylist
(
info
)
1150
if
vertical
then
1151
info
=
vpack_nodes
(
info
)
1152
end
1153
head
,
current
=
insertnodebefore
(
head
,
current
,
info
)
1154
return
head
,
getnext
(
current
)
1155
end
1156 1157
end
1158 1159
local
ruleditalic
do
1160 1161
local
i_cache
=
caches
[
"
italic
"
]
1162 1163
ruleditalic
=
function
(
head
,
current
)
1164
local
kern
=
getkern
(
current
)
1165
local
info
=
i_cache
[
kern
]
1166
if
not
info
then
1167
local
amount
=
formatters
[
"
%s:%0.3f
"
]
(
"
IC
"
,
kern
*
pt_factor
)
1168
if
kern
>
0
then
1169
info
=
sometext
(
amount
,
l_kern
,
"
trace:b
"
)
1170
elseif
kern
<
0
then
1171
info
=
sometext
(
amount
,
l_kern
,
"
trace:r
"
)
1172
else
1173
info
=
sometext
(
amount
,
l_kern
,
"
trace:g
"
)
1174
end
1175
i_cache
[
kern
]
=
info
1176
end
1177
info
=
copylist
(
info
)
1178
head
,
current
=
insertnodebefore
(
head
,
current
,
info
)
1179
return
head
,
getnext
(
current
)
1180
end
1181 1182
end
1183 1184
local
ruledmarginkern
do
1185 1186
local
m_cache
=
caches
[
"
marginkern
"
]
1187 1188
ruledmarginkern
=
function
(
head
,
current
)
1189
local
kern
=
getkern
(
current
)
1190
local
info
=
m_cache
[
kern
]
1191
if
not
info
then
1192
local
amount
=
formatters
[
"
%s:%0.3f
"
]
(
"
MK
"
,
kern
*
pt_factor
)
1193
if
kern
>
0
then
1194
info
=
sometext
(
amount
,
l_marginkern
,
"
trace:b
"
)
1195
elseif
kern
<
0
then
1196
info
=
sometext
(
amount
,
l_marginkern
,
"
trace:r
"
)
1197
else
1198
info
=
sometext
(
amount
,
l_marginkern
,
"
trace:g
"
)
1199
end
1200
m_cache
[
kern
]
=
info
1201
end
1202
info
=
copylist
(
info
)
1203
head
,
current
=
insertnodebefore
(
head
,
current
,
info
)
1204
return
head
,
getnext
(
current
)
1205
end
1206 1207
end
1208 1209
local
ruledmathlistkern
do
1210 1211
local
l_cache
=
caches
[
"
mathlistkern
"
]
1212 1213
ruledmathlistkern
=
function
(
head
,
current
)
1214
local
kern
=
getkern
(
current
)
1215
local
info
=
l_cache
[
kern
]
1216
if
not
info
then
1217
local
amount
=
formatters
[
"
%s:%0.3f
"
]
(
"
LK
"
,
kern
*
pt_factor
)
1218
if
kern
>
0
then
1219
info
=
sometext
(
amount
,
l_mathlistkern
,
"
trace:b
"
)
1220
elseif
kern
<
0
then
1221
info
=
sometext
(
amount
,
l_mathlistkern
,
"
trace:r
"
)
1222
else
1223
info
=
sometext
(
amount
,
l_mathlistkern
,
"
trace:g
"
)
1224
end
1225
l_cache
[
kern
]
=
info
1226
end
1227
info
=
copylist
(
info
)
1228
head
,
current
=
insertnodebefore
(
head
,
current
,
info
)
1229
return
head
,
getnext
(
current
)
1230
end
1231 1232
end
1233 1234
local
ruleddiscretionary
do
1235 1236
local
d_cache
=
caches
[
"
discretionary
"
]
1237 1238
ruleddiscretionary
=
function
(
head
,
current
)
1239
local
d
=
d_cache
[
true
]
1240
if
not
the_discretionary
then
1241
local
rule
=
new_rule
(
4
*
emwidth
/
fraction
,
4
*
exheight
,
exheight
)
1242
local
kern
=
new_kern
(
-2
*
emwidth
/
fraction
)
1243
setlink
(
kern
,
rule
)
1244
setcolor
(
rule
,
"
trace:dd
"
)
1245
settransparency
(
rule
,
"
trace:dd
"
)
1246
setattr
(
rule
,
a_layer
,
l_discretionary
)
1247
d
=
new_hlist
(
kern
)
1248
d_cache
[
true
]
=
d
1249
end
1250
insertnodeafter
(
head
,
current
,
copylist
(
d
)
)
1251
return
head
,
current
1252
end
1253 1254
end
1255 1256
local
ruledpenalty
do
1257 1258
local
p_cache_v
=
caches
[
"
vpenalty
"
]
1259
local
p_cache_h
=
caches
[
"
hpenalty
"
]
1260 1261
local
raisepenalties
=
false
1262 1263
local
getpenalty
=
nuts
.
getpenalty
1264 1265
directives
.
register
(
"
visualizers.raisepenalties
"
,
function
(
v
)
raisepenalties
=
v
end
)
1266 1267
ruledpenalty
=
function
(
head
,
current
,
vertical
)
1268
local
penalty
=
getpenalty
(
current
)
1269
local
info
=
(
vertical
and
p_cache_v
or
p_cache_h
)
[
penalty
]
1270
if
info
then
1271
-- print("penalty hit")
1272
else
1273
local
amount
=
formatters
[
"
%s:%s
"
]
(
vertical
and
"
VP
"
or
"
HP
"
,
penalty
)
1274
if
penalty
>
0
then
1275
info
=
sometext
(
amount
,
l_penalty
,
"
trace:b
"
)
1276
elseif
penalty
<
0
then
1277
info
=
sometext
(
amount
,
l_penalty
,
"
trace:r
"
)
1278
else
1279
info
=
sometext
(
amount
,
l_penalty
,
"
trace:g
"
)
1280
end
1281
(
vertical
and
p_cache_v
or
p_cache_h
)
[
penalty
]
=
info
1282
end
1283
info
=
copylist
(
info
)
1284
if
vertical
then
1285
info
=
vpack_nodes
(
info
)
1286
elseif
raisepenalties
then
1287
setshift
(
info
,
-65536
*
4
)
1288
end
1289
head
,
current
=
insertnodebefore
(
head
,
current
,
info
)
1290
return
head
,
getnext
(
current
)
1291
end
1292 1293
end
1294 1295
do
1296 1297
local
nodecodes
=
nodes
.
nodecodes
1298
local
disc_code
=
nodecodes
.
disc
1299
local
kern_code
=
nodecodes
.
kern
1300
local
glyph_code
=
nodecodes
.
glyph
1301
local
glue_code
=
nodecodes
.
glue
1302
local
penalty_code
=
nodecodes
.
penalty
1303
local
whatsit_code
=
nodecodes
.
whatsit
1304
local
user_code
=
nodecodes
.
user
1305
local
math_code
=
nodecodes
.
math
1306
local
hlist_code
=
nodecodes
.
hlist
1307
local
vlist_code
=
nodecodes
.
vlist
1308
local
marginkern_code
=
nodecodes
.
marginkern
1309
local
mathlistkern_code
=
nodecodes
.
mathlistkern
1310
local
dir_code
=
nodecodes
.
dir
1311
local
par_code
=
nodecodes
.
par
1312
local
mark_code
=
nodecodes
.
mark
1313
local
insert_code
=
nodecodes
.
insert
1314 1315
local
kerncodes
=
nodes
.
kerncodes
1316
local
fontkern_code
=
kerncodes
.
fontkern
1317
local
italickern_code
=
kerncodes
.
italiccorrection
1318
local
leftmarginkern_code
=
kerncodes
.
leftmarginkern
1319
local
rightmarginkern_code
=
kerncodes
.
rightmarginkern
1320
local
mathlistkern_code
=
kerncodes
.
mathlistkern
1321
----- userkern_code = kerncodes.userkern
1322 1323
local
skipcodes
=
nodes
.
skipcodes
1324
local
spaceskip_code
=
skipcodes
.
spaceskip
1325
local
xspaceskip_code
=
skipcodes
.
xspaceskip
1326
local
zerospaceskip_code
=
skipcodes
.
zerospaceskip
1327
local
intermathskip_code
=
skipcodes
.
intermathskip
1328 1329
local
listcodes
=
nodes
.
listcodes
1330
local
linelist_code
=
listcodes
.
line
1331 1332
local
vtop_package_state
=
3
-- todo: symbolic
1333 1334
local
getleader
=
nuts
.
getleader
1335
local
getdisc
=
nuts
.
getdisc
1336 1337
local
setleader
=
nuts
.
setleader
1338
local
setdisc
=
nuts
.
setdisc
1339 1340
-- local cache
1341 1342
local
function
visualize
(
head
,
vertical
,
forced
,
parent
)
1343
local
trace_hbox
=
false
1344
local
trace_vbox
=
false
1345
local
trace_vtop
=
false
1346
local
trace_kern
=
false
1347
local
trace_glue
=
false
1348
local
trace_penalty
=
false
1349
local
trace_fontkern
=
false
1350
local
trace_strut
=
false
1351
local
trace_whatsit
=
false
1352
local
trace_glyph
=
false
1353
local
trace_simple
=
false
1354
local
trace_user
=
false
1355
local
trace_math
=
false
1356
local
trace_italic
=
false
1357
local
trace_origin
=
false
1358
local
trace_discretionary
=
false
1359
local
trace_expansion
=
false
1360
local
trace_line
=
false
1361
local
trace_space
=
false
1362
local
trace_depth
=
false
1363
local
trace_dir
=
false
1364
local
trace_par
=
false
1365
local
trace_math_glue
=
false
1366
local
trace_mark
=
false
1367
local
trace_insert
=
false
1368
local
current
=
head
1369
local
previous
=
nil
1370
local
attr
=
unsetvalue
1371
local
prev_trace_fontkern
=
nil
1372
local
prev_trace_italic
=
nil
1373
local
prev_trace_marginkern
=
nil
1374
-- local prev_trace_mathlist = nil
1375
local
prev_trace_expansion
=
nil
1376 1377
while
current
do
1378
local
id
=
getid
(
current
)
1379
local
a
=
forced
or
getattr
(
current
,
a_visual
)
or
unsetvalue
1380
local
subtype
,
content
1381
if
a
~
=
attr
then
1382
prev_trace_fontkern
=
trace_fontkern
1383
prev_trace_italic
=
trace_italic
1384
prev_trace_marginkern
=
trace_marginkern
1385
-- prev_trace_mathlistkern = trace_mathlistkern
1386
prev_trace_expansion
=
trace_expansion
1387
attr
=
a
1388
if
a
=
=
unsetvalue
then
1389
trace_hbox
=
false
1390
trace_vbox
=
false
1391
trace_vtop
=
false
1392
trace_kern
=
false
1393
trace_glue
=
false
1394
trace_penalty
=
false
1395
trace_fontkern
=
false
1396
trace_strut
=
false
1397
trace_whatsit
=
false
1398
trace_glyph
=
false
1399
trace_simple
=
false
1400
trace_user
=
false
1401
trace_math
=
false
1402
trace_italic
=
false
1403
trace_origin
=
false
1404
trace_discretionary
=
false
1405
trace_expansion
=
false
1406
trace_line
=
false
1407
trace_space
=
false
1408
trace_depth
=
false
1409
trace_marginkern
=
false
1410
trace_mathlistkern
=
false
1411
trace_dir
=
false
1412
trace_par
=
false
1413
trace_math_glue
=
false
1414
trace_mark
=
false
1415
trace_insert
=
false
1416
if
id
=
=
kern_code
then
1417
goto
kern
1418
else
1419
goto
list
1420
end
1421
else
-- we need them to be booleans
1422
-- cache[a]()
1423
trace_hbox
=
a
&
0x0000001
~
=
0
1424
trace_vbox
=
a
&
0x0000002
~
=
0
1425
trace_vtop
=
a
&
0x0000004
~
=
0
1426
trace_kern
=
a
&
0x0000008
~
=
0
1427
trace_glue
=
a
&
0x0000010
~
=
0
1428
trace_penalty
=
a
&
0x0000020
~
=
0
1429
trace_fontkern
=
a
&
0x0000040
~
=
0
1430
trace_strut
=
a
&
0x0000080
~
=
0
1431
trace_whatsit
=
a
&
0x0000100
~
=
0
1432
trace_glyph
=
a
&
0x0000200
~
=
0
1433
trace_simple
=
a
&
0x0000400
~
=
0
1434
trace_user
=
a
&
0x0000800
~
=
0
1435
trace_math
=
a
&
0x0001000
~
=
0
1436
trace_italic
=
a
&
0x0002000
~
=
0
1437
trace_origin
=
a
&
0x0004000
~
=
0
1438
trace_discretionary
=
a
&
0x0008000
~
=
0
1439
trace_expansion
=
a
&
0x0010000
~
=
0
1440
trace_line
=
a
&
0x0020000
~
=
0
1441
trace_space
=
a
&
0x0040000
~
=
0
1442
trace_depth
=
a
&
0x0080000
~
=
0
1443
trace_marginkern
=
a
&
0x0100000
~
=
0
1444
trace_mathlistkern
=
a
&
0x0200000
~
=
0
1445
trace_dir
=
a
&
0x0400000
~
=
0
1446
trace_par
=
a
&
0x0800000
~
=
0
1447
trace_math_glue
=
a
&
0x1000000
~
=
0
1448
trace_mark
=
a
&
0x2000000
~
=
0
1449
trace_insert
=
a
&
0x4000000
~
=
0
1450
end
1451
elseif
a
=
=
unsetvalue
then
1452
goto
list
1453
end
1454
if
trace_strut
then
1455
setattr
(
current
,
a_layer
,
l_strut
)
1456
elseif
id
=
=
glyph_code
then
1457
if
trace_glyph
then
1458
head
,
current
=
ruledglyph
(
head
,
current
,
previous
)
1459
end
1460
if
trace_expansion
then
1461
head
,
current
=
ruledglyphexpansion
(
head
,
current
)
1462
end
1463
elseif
id
=
=
disc_code
then
1464
if
trace_discretionary
then
1465
head
,
current
=
ruleddiscretionary
(
head
,
current
)
1466
end
1467
local
pre
,
post
,
replace
=
getdisc
(
current
)
1468
if
pre
then
1469
pre
=
visualize
(
pre
,
false
,
a
,
parent
)
1470
end
1471
if
post
then
1472
post
=
visualize
(
post
,
false
,
a
,
parent
)
1473
end
1474
if
replace
then
1475
replace
=
visualize
(
replace
,
false
,
a
,
parent
)
1476
end
1477
setdisc
(
current
,
pre
,
post
,
replace
)
1478
elseif
id
=
=
kern_code
then
1479
goto
kern
1480
elseif
id
=
=
glue_code
then
1481
goto
glue
1482
elseif
id
=
=
penalty_code
then
1483
if
trace_penalty
then
1484
head
,
current
=
ruledpenalty
(
head
,
current
,
vertical
)
1485
end
1486
elseif
id
=
=
hlist_code
or
id
=
=
vlist_code
then
1487
goto
list
1488
elseif
id
=
=
whatsit_code
then
1489
if
trace_whatsit
then
1490
head
,
current
=
ruledwhatsit
(
head
,
current
)
1491
end
1492
elseif
id
=
=
user_code
then
1493
if
trace_user
then
1494
head
,
current
=
ruleduser
(
head
,
current
)
1495
end
1496
elseif
id
=
=
math_code
then
1497
if
trace_math
then
1498
head
,
current
=
ruledmath
(
head
,
current
)
1499
end
1500
elseif
id
=
=
marginkern_code
then
1501
if
trace_kern
then
1502
head
,
current
=
ruledkern
(
head
,
current
,
vertical
,
true
)
1503
end
1504
elseif
id
=
=
dir_code
then
1505
if
trace_dir
then
1506
head
,
current
=
ruleddir
(
head
,
current
)
1507
end
1508
elseif
id
=
=
par_code
then
1509
if
trace_par
then
1510
head
,
current
=
ruledpar
(
head
,
current
)
1511
end
1512
elseif
id
=
=
mark_code
then
1513
if
trace_mark
then
1514
head
,
current
=
ruledmark
(
head
,
current
)
1515
end
1516
elseif
id
=
=
insert_code
then
1517
if
trace_insert
then
1518
head
,
current
=
ruledinsert
(
head
,
current
)
1519
end
1520
end
1521
goto
next
1522
::
glue
::
1523
content
=
getleader
(
current
)
1524
if
content
then
1525
setleader
(
current
,
visualize
(
content
,
false
,
nil
,
parent
)
)
1526
elseif
trace_glue
then
1527
head
,
current
=
ruledglue
(
head
,
current
,
vertical
,
parent
)
1528
else
1529
subtype
=
getsubtype
(
current
)
1530
if
subtype
=
=
spaceskip_code
or
subtype
=
=
xspaceskip_code
or
subtype
=
=
zerospaceskip_code
then
-- not yet all space
1531
if
trace_space
then
1532
head
,
current
=
ruledspace
(
head
,
current
,
parent
)
1533
end
1534
elseif
subtype
=
=
intermathskip_code
then
1535
if
trace_math
or
trace_math_glue
then
1536
head
=
ruledmathglue
(
head
,
current
,
parent
)
1537
end
1538
end
1539
end
1540
goto
next
1541
::
kern
::
1542
subtype
=
getsubtype
(
current
)
1543
if
subtype
=
=
fontkern_code
then
1544
if
trace_fontkern
or
prev_trace_fontkern
then
1545
head
,
current
=
fontkern
(
head
,
current
)
1546
end
1547
if
trace_expansion
or
prev_trace_expansion
then
1548
head
,
current
=
kernexpansion
(
head
,
current
)
1549
end
1550
elseif
subtype
=
=
italickern_code
then
1551
if
trace_italic
or
prev_trace_italic
then
1552
head
,
current
=
italickern
(
head
,
current
)
1553
elseif
trace_kern
then
1554
head
,
current
=
ruleditalic
(
head
,
current
)
1555
end
1556
elseif
subtype
=
=
leftmarginkern_code
or
subtype
=
=
rightmarginkern_code
then
1557
if
trace_marginkern
or
prev_trace_marginkern
then
1558
head
,
current
=
marginkern
(
head
,
current
)
1559
elseif
trace_kern
then
1560
head
,
current
=
ruledmarginkern
(
head
,
current
)
1561
end
1562
elseif
subtype
=
=
mathlistkern_code
then
1563
if
trace_mathlist
then
-- or prev_trace_mathlist then
1564
head
,
current
=
mathlistkern
(
head
,
current
)
1565
elseif
trace_kern
then
1566
head
,
current
=
ruledmathlistkern
(
head
,
current
)
1567
end
1568
else
1569
if
trace_kern
then
1570
head
,
current
=
ruledkern
(
head
,
current
,
vertical
)
1571
end
1572
end
1573
goto
next
;
1574
::
list
::
1575
if
id
=
=
hlist_code
then
1576
local
content
=
getlist
(
current
)
1577
if
content
then
1578
setlist
(
current
,
visualize
(
content
,
false
,
nil
,
current
)
)
1579
end
1580
if
trace_depth
then
1581
ruleddepth
(
current
)
1582
end
1583
if
trace_line
and
getsubtype
(
current
)
=
=
linelist_code
then
1584
head
,
current
=
ruledbox
(
head
,
current
,
false
,
l_line
,
"
L__
"
,
trace_simple
,
previous
,
trace_origin
,
parent
)
1585
elseif
trace_hbox
then
1586
head
,
current
=
ruledbox
(
head
,
current
,
false
,
l_hbox
,
"
H__
"
,
trace_simple
,
previous
,
trace_origin
,
parent
)
1587
end
1588
elseif
id
=
=
vlist_code
then
1589
local
content
=
getlist
(
current
)
1590
local
isvtop
=
getstate
(
current
)
=
=
vtop_package_state
1591
local
tag
=
nil
1592
local
layer
=
nil
1593
if
content
then
1594
setlist
(
current
,
visualize
(
content
,
true
,
nil
,
current
)
)
1595
end
1596
if
trace_vtop
then
1597
if
isvtop
then
1598
tag
=
"
_T_
"
1599
layer
=
l_vtop
1600
elseif
trace_vbox
then
1601
tag
=
"
__V
"
1602
layer
=
l_vbox
1603
end
1604
elseif
trace_vbox
then
1605
if
not
isvtop
then
1606
tag
=
"
__V
"
1607
layer
=
l_vbox
1608
end
1609
end
1610
if
tag
then
1611
head
,
current
=
ruledbox
(
head
,
current
,
true
,
layer
,
tag
,
trace_simple
,
previous
,
trace_origin
,
parent
)
1612
end
1613
end
1614
::
next
::
1615
previous
=
current
1616
current
=
getnext
(
current
)
1617
end
1618
return
head
1619
end
1620 1621
local
function
cleanup
(
)
1622
for
tag
,
cache
in
next
,
caches
do
1623
for
k
,
v
in
next
,
cache
do
1624
flushnodelist
(
v
)
1625
end
1626
end
1627
cleanup
=
function
(
)
1628
report_visualize
(
"
error, duplicate cleanup
"
)
1629
end
1630
end
1631 1632
luatex
.
registerstopactions
(
cleanup
)
1633 1634
function
visualizers
.
handler
(
head
)
1635
if
usedfont
then
1636
starttiming
(
visualizers
)
1637
head
=
visualize
(
head
,
true
)
1638
stoptiming
(
visualizers
)
1639
return
head
,
true
1640
else
1641
return
head
,
false
1642
end
1643
end
1644 1645
function
visualizers
.
box
(
n
)
1646
if
usedfont
then
1647
starttiming
(
visualizers
)
1648
local
box
=
getbox
(
n
)
1649
if
box
then
1650
setlist
(
box
,
visualize
(
getlist
(
box
)
,
getid
(
box
)
=
=
vlist_code
)
)
1651
end
1652
stoptiming
(
visualizers
)
1653
return
head
,
true
1654
else
1655
return
head
,
false
1656
end
1657
end
1658 1659
end
1660 1661
do
1662 1663
local
nodecodes
=
nodes
.
nodecodes
1664
local
hlist_code
=
nodecodes
.
hlist
1665
local
vlist_code
=
nodecodes
.
vlist
1666
local
nextnode
=
nuts
.
traversers
.
node
1667 1668
local
last
=
nil
1669
local
used
=
nil
1670 1671
local
mark
=
{
1672
"
trace:1
"
,
"
trace:2
"
,
"
trace:3
"
,
1673
"
trace:4
"
,
"
trace:5
"
,
"
trace:6
"
,
1674
"
trace:7
"
,
1675
}
1676 1677
local
function
markfonts
(
list
)
1678
for
n
,
id
in
nextnode
,
list
do
1679
if
id
=
=
glyph_code
then
1680
local
font
=
getfont
(
n
)
1681
local
okay
=
used
[
font
]
1682
if
not
okay
then
1683
last
=
last
+
1
1684
okay
=
mark
[
last
]
1685
used
[
font
]
=
okay
1686
end
1687
setcolor
(
n
,
okay
)
1688
elseif
id
=
=
hlist_code
or
id
=
=
vlist_code
then
1689
markfonts
(
getlist
(
n
)
)
1690
end
1691
end
1692
end
1693 1694
function
visualizers
.
markfonts
(
list
)
1695
last
,
used
=
0
,
{
}
1696
markfonts
(
type
(
n
)
=
=
"
number
"
and
getlist
(
getbox
(
n
)
)
or
n
)
1697
end
1698 1699
end
1700 1701
statistics
.
register
(
"
visualization time
"
,
function
(
)
1702
if
enabled
then
1703
-- cleanup() -- in case we don't don't do it each time
1704
return
formatters
[
"
%s seconds
"
]
(
statistics
.
elapsedtime
(
visualizers
)
)
1705
end
1706
end
)
1707 1708
-- interface
1709 1710
do
1711 1712
local
implement
=
interfaces
.
implement
1713 1714
implement
{
1715
name
=
"
setvisual
"
,
1716
arguments
=
"
string
"
,
1717
actions
=
visualizers
.
setvisual
1718
}
1719 1720
implement
{
1721
name
=
"
setvisuals
"
,
1722
arguments
=
"
string
"
,
1723
actions
=
visualizers
.
setvisual
1724
}
1725 1726
implement
{
1727
name
=
"
getvisual
"
,
1728
arguments
=
"
string
"
,
1729
actions
=
{
setvisual
,
context
}
1730
}
1731 1732
implement
{
1733
name
=
"
setvisuallayer
"
,
1734
arguments
=
"
string
"
,
1735
actions
=
visualizers
.
setlayer
1736
}
1737 1738
implement
{
1739
name
=
"
markvisualfonts
"
,
1740
arguments
=
"
integer
"
,
1741
actions
=
visualizers
.
markfonts
1742
}
1743 1744
implement
{
1745
name
=
"
setvisualfont
"
,
1746
arguments
=
"
integer
"
,
1747
actions
=
visualizers
.
setfont
1748
}
1749 1750
end
1751 1752
-- Here for now:
1753 1754
do
1755 1756
local
function
make
(
str
,
forecolor
,
rulecolor
,
layer
)
1757
if
initialize
then
1758
initialize
(
)
1759
end
1760
local
rule
=
new_rule
(
emwidth
/
fraction
,
exheight
,
4
*
exheight
)
1761
setcolor
(
rule
,
rulecolor
)
1762
settransparency
(
rule
,
rulecolor
)
1763
local
info
1764
if
str
=
=
"
"
then
1765
info
=
new_hlist
(
rule
)
1766
else
1767
local
text
=
hpack_string
(
str
,
usedfont
)
1768
local
list
=
getlist
(
text
)
1769
setlistcolor
(
list
,
textcolor
)
1770
setlisttransparency
(
list
,
textcolor
)
1771
setshift
(
text
,
3
.
5
*
exheight
)
1772
info
=
new_hlist
(
setlink
(
rule
,
text
)
)
1773
end
1774
setattr
(
info
,
a_layer
,
layer
)
1775
return
info
1776
end
1777 1778
function
visualizers
.
register
(
name
,
textcolor
,
rulecolor
)
1779
if
rawget
(
layers
,
name
)
then
1780
-- message
1781
return
1782
end
1783
local
cache
=
caches
[
name
]
1784
local
layer
=
layers
[
name
]
1785
if
not
textcolor
then
1786
textcolor
=
"
trace:ds
"
1787
end
1788
if
not
rulecolor
then
1789
rulecolor
=
"
trace:do
"
1790
end
1791
return
function
(
str
)
1792
if
not
str
then
1793
str
=
"
"
1794
end
1795
local
info
=
cache
[
str
]
1796
if
not
info
then
1797
info
=
make
(
str
,
textcolor
,
rulecolor
,
layer
)
1798
cache
[
str
]
=
info
1799
end
1800
return
copy_node
(
info
)
1801
end
1802
end
1803 1804
end
1805