typo-bld.lua /size: 12 Kb    last modification: 2020-07-01 14:35
1
if
modules
then
modules
=
{
}
end
modules
[
'
typo-bld
'
]
=
{
-- was node-par
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
-- no need for nuts in the one-line demo (that might move anyway)
10 11
local
insert
,
remove
=
table
.
insert
,
table
.
remove
12 13
builders
=
builders
or
{
}
14
local
builders
=
builders
15 16
builders
.
paragraphs
=
builders
.
paragraphs
or
{
}
17
local
parbuilders
=
builders
.
paragraphs
18 19
parbuilders
.
constructors
=
parbuilders
.
constructors
or
{
}
20
local
constructors
=
parbuilders
.
constructors
21 22
constructors
.
names
=
constructors
.
names
or
{
}
23
local
names
=
constructors
.
names
24 25
constructors
.
numbers
=
constructors
.
numbers
or
{
}
26
local
numbers
=
constructors
.
numbers
27 28
constructors
.
methods
=
constructors
.
methods
or
{
}
29
local
methods
=
constructors
.
methods
30 31
local
a_parbuilder
=
attributes
.
numbers
[
'
parbuilder
'
]
or
999
-- why 999
32
constructors
.
attribute
=
a_parbuilder
33 34
local
unsetvalue
=
attributes
.
unsetvalue
35
local
texsetattribute
=
tex
.
setattribute
36
local
texnest
=
tex
.
nest
37
local
texlists
=
tex
.
lists
38 39
local
texget
=
tex
.
get
40
local
texset
=
tex
.
set
41 42
local
texgetdimen
=
tex
.
getdimen
43 44
local
nodes
=
nodes
45
local
nodeidstostring
=
nodes
.
idstostring
46
local
nodepool
=
nodes
.
pool
47
local
new_baselineskip
=
nodepool
.
baselineskip
48
local
new_lineskip
=
nodepool
.
lineskip
49
local
insert_node_before
=
nodes
.
insert_before
50
local
hpack_node
=
nodes
.
hpack
51 52
local
nuts
=
nodes
.
nuts
53
local
tonode
=
nodes
.
tonode
54
local
tonut
=
nodes
.
tonut
55
local
count_nodes
=
nuts
.
countall
56
local
getattr
=
nuts
.
getattr
57 58
local
starttiming
=
statistics
.
starttiming
59
local
stoptiming
=
statistics
.
stoptiming
60 61
local
registercallback
=
callbacks
.
register
62 63
storage
.
register
(
"
builders/paragraphs/constructors/names
"
,
names
,
"
builders.paragraphs.constructors.names
"
)
64
storage
.
register
(
"
builders/paragraphs/constructors/numbers
"
,
numbers
,
"
builders.paragraphs.constructors.numbers
"
)
65 66
local
trace_page_builder
=
false
trackers
.
register
(
"
builders.page
"
,
function
(
v
)
trace_page_builder
=
v
end
)
67
local
trace_vbox_builder
=
false
trackers
.
register
(
"
builders.vbox
"
,
function
(
v
)
trace_vbox_builder
=
v
end
)
68
local
trace_post_builder
=
false
trackers
.
register
(
"
builders.post
"
,
function
(
v
)
trace_post_builder
=
v
end
)
69 70
local
report_page_builder
=
logs
.
reporter
(
"
builders
"
,
"
page
"
)
71
local
report_vbox_builder
=
logs
.
reporter
(
"
builders
"
,
"
vbox
"
)
72
local
report_par_builder
=
logs
.
reporter
(
"
builders
"
,
"
par
"
)
73 74
local
mainconstructor
=
nil
-- not stored in format
75
local
nofconstructors
=
0
76
local
stack
=
{
}
77 78
function
constructors
.
define
(
name
)
79
nofconstructors
=
nofconstructors
+
1
80
names
[
nofconstructors
]
=
name
81
numbers
[
name
]
=
nofconstructors
82
end
83 84
function
constructors
.
set
(
name
)
--- will go
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
94
end
95 96
function
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
-- report_par_builder("start %a",name)
105
end
106 107
function
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
-- report_par_builder("stop")
115
end
116 117
-- return values:
118
--
119
-- true : tex will break itself
120
-- false : idem but dangerous
121
-- head : list of valid vmode nodes with last being hlist
122 123
function
constructors
.
handler
(
head
,
followed_by_display
)
124
if
type
(
head
)
=
=
"
boolean
"
then
125
return
head
126
else
127
local
attribute
=
getattr
(
head
,
a_parbuilder
)
-- or mainconstructor
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
-- let tex break
137
end
138
end
139
end
140
return
true
-- let tex break
141
end
142
end
143 144
-- just for testing
145 146
function
constructors
.
methods
.
default
(
head
,
followed_by_display
)
147
return
true
-- let tex break
148
end
149 150
-- also for testing (now also surrounding spacing done)
151 152
function
parbuilders
.
constructors
.
methods
.
oneline
(
head
,
followed_by_display
)
153
-- when needed we will turn this into a helper
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
)
)
)
-- no stretch etc
161
else
162
return
insert_node_before
(
h
,
h
,
new_baselineskip
(
d
)
)
163
end
164
end
165 166
-- It makes no sense to have a sequence here as we already have
167
-- pre and post hooks and only one parbuilder makes sense, so no:
168
--
169
-- local actions = nodes.tasks.actions("parbuilders")
170
--
171
-- yet ... maybe some day.
172 173
local
actions
=
constructors
.
handler
174
local
enabled
=
false
175 176
local
function
processor
(
head
,
followed_by_display
)
177
-- todo: not again in otr so we need to flag
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
-- let tex do the work
187
end
188
end
189 190
function
constructors
.
enable
(
)
enabled
=
true
end
191
function
constructors
.
disable
(
)
enabled
=
false
end
192 193
registercallback
(
'
linebreak_filter
'
,
processor
,
"
breaking paragraps into lines
"
)
194 195
statistics
.
register
(
"
linebreak processing time
"
,
function
(
)
196
return
statistics
.
elapsedseconds
(
parbuilders
)
197
end
)
198 199
-- todo: move from nodes.builders to builders
200 201
nodes
.
builders
=
nodes
.
builder
or
{
}
202
local
builders
=
nodes
.
builders
203 204
local
vboxactions
=
nodes
.
tasks
.
actions
(
"
vboxbuilders
"
)
205 206
function
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
223
end
224 225
-- This one is special in the sense that it has no head and we operate on the mlv. Also,
226
-- we need to do the vspacing last as it removes items from the mvl.
227 228
local
pageactions
=
nodes
.
tasks
.
actions
(
"
mvlbuilders
"
)
229
----- lineactions = nodes.tasks.actions("linebuilders")
230 231
local
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>
"
)
237
end
238 239
-- check why box is called before after_linebreak .. maybe make categories and
240
-- call 'm less
241 242
-- this will be split into contribute_filter for these 4 so at some point
243
-- the check can go away
244 245
function
builders
.
buildpage_filter
(
groupcode
)
246
-- the next check saves 1% runtime on 1000 tufte pages
247
local
head
=
texlists
.
contrib_head
248
local
done
=
false
249
if
head
then
250
-- called quite often ... maybe time to remove timing
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
-- -- doesn't work here (not passed on?)
258
-- texset("pagegoal,texget("vsize") - texgetdimen("d_page_floats_inserted_top") - texgetdimen("d_page_floats_inserted_bottom")
259
texlists
.
contrib_head
=
head
or
nil
-- needs checking
260
-- tex.setlist("contrib_head",head,head and nodes.tail(head))
261
return
done
and
head
or
true
-- no return value needed
262
else
263
-- happens quite often
264
if
trace_page_builder
then
265
report
(
groupcode
)
266
end
267
-- return nil, false -- no return value needed
268
return
nil
269
end
270
end
271 272
registercallback
(
'
vpack_filter
'
,
builders
.
vpack_filter
,
"
vertical spacing etc
"
)
273
registercallback
(
'
buildpage_filter
'
,
builders
.
buildpage_filter
,
"
vertical spacing etc (mvl)
"
)
274 275
statistics
.
register
(
"
v-node processing time
"
,
function
(
)
276
return
statistics
.
elapsedseconds
(
builders
)
277
end
)
278 279
local
implement
=
interfaces
.
implement
280 281
implement
{
name
=
"
defineparbuilder
"
,
actions
=
constructors
.
define
,
arguments
=
"
string
"
}
282
implement
{
name
=
"
setparbuilder
"
,
actions
=
constructors
.
set
,
arguments
=
"
string
"
}
283
implement
{
name
=
"
startparbuilder
"
,
actions
=
constructors
.
start
,
arguments
=
"
string
"
}
284
implement
{
name
=
"
stopparbuilder
"
,
actions
=
constructors
.
stop
}
285
implement
{
name
=
"
enableparbuilder
"
,
actions
=
constructors
.
enable
}
286
implement
{
name
=
"
disableparbuilder
"
,
actions
=
constructors
.
disable
}
287 288
-- Here are some tracers:
289 290
local
nuts
=
nodes
.
nuts
291
local
tonut
=
nodes
.
tonut
292
local
setcolor
=
nodes
.
tracers
.
colors
.
set
293
local
listtoutf
=
nodes
.
listtoutf
294
local
new_kern
=
nuts
.
pool
.
kern
295
local
new_rule
=
nuts
.
pool
.
rule
296
local
hpack
=
nuts
.
hpack
297
local
getheight
=
nuts
.
getheight
298
local
getdepth
=
nuts
.
getdepth
299
local
getdirection
=
nuts
.
getdirection
300
local
getlist
=
nuts
.
getlist
301
local
setwidth
=
nuts
.
setwidth
302
local
setdirection
=
nuts
.
setdirection
303
local
setlink
=
nuts
.
setlink
304
local
tonode
=
nuts
.
tonode
305 306
local
report_hpack
=
logs
.
reporter
(
"
hpack routine
"
)
307
local
report_vpack
=
logs
.
reporter
(
"
vpack routine
"
)
308 309
-- overflow|badness w h d dir
310 311
local
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
319
end
320 321
trackers
.
register
(
"
builders.vpack.quality
"
,
function
(
v
)
322
registercallback
(
"
vpack_quality
"
,
v
and
report_vpack_quality
or
nil
,
"
check vpack quality
"
)
323
end
)
324 325
local
report
,
show
=
false
,
false
326 327
local
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
)
-- can be a nut
368
end
369
end
370 371
trackers
.
register
(
"
builders.hpack.quality
"
,
function
(
v
)
372
report
=
v
373
registercallback
(
"
hpack_quality
"
,
(
report
or
show
)
and
hpack_quality
or
nil
,
"
check hpack quality
"
)
374
end
)
375 376
trackers
.
register
(
"
builders.hpack.overflow
"
,
function
(
v
)
377
show
=
v
378
registercallback
(
"
hpack_quality
"
,
(
report
or
show
)
and
hpack_quality
or
nil
,
"
check hpack quality
"
)
379
end
)
380