node-rul.lua /size: 24 Kb    last modification: 2020-07-01 14:35
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
node-rul
'
]
=
{
2
version
=
1
.
001
,
3
comment
=
"
companion to node-rul.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 will go to an auxiliary module
10
-- beware: rules now have a dir field
11
--
12
-- todo: make robust for layers ... order matters
13 14
-- todo: collect successive bit and pieces and combine them
15
--
16
-- path s ; s := shaped(p) ; % p[] has rectangles
17
-- fill s withcolor .5white ;
18
-- draw boundingbox s withcolor yellow;
19 20
local
tonumber
=
tonumber
21 22
local
context
=
context
23
local
attributes
=
attributes
24
local
nodes
=
nodes
25
local
properties
=
nodes
.
properties
.
data
26 27
local
enableaction
=
nodes
.
tasks
.
enableaction
28 29
local
nuts
=
nodes
.
nuts
30
local
tonode
=
nuts
.
tonode
31
local
tonut
=
nuts
.
tonut
32 33
local
setnext
=
nuts
.
setnext
34
local
setprev
=
nuts
.
setprev
35
local
setlink
=
nuts
.
setlink
36
local
getnext
=
nuts
.
getnext
37
local
getprev
=
nuts
.
getprev
38
local
getid
=
nuts
.
getid
39
local
getdirection
=
nuts
.
getdirection
40
local
getattr
=
nuts
.
getattr
41
local
setattr
=
nuts
.
setattr
42
local
getfont
=
nuts
.
getfont
43
local
getsubtype
=
nuts
.
getsubtype
44
local
getlist
=
nuts
.
getlist
45
local
setwhd
=
nuts
.
setwhd
46
local
setattrlist
=
nuts
.
setattrlist
47
local
setshift
=
nuts
.
setshift
48
local
getwidth
=
nuts
.
getwidth
49
local
setwidth
=
nuts
.
setwidth
50
local
setoffsets
=
nuts
.
setoffsets
51
local
setfield
=
nuts
.
setfield
52 53
----- getfield = nuts.getfield
54
----- getdata = nuts.getdata
55
local
getruledata
=
nuts
.
getruledata
56 57
local
isglyph
=
nuts
.
isglyph
58 59
local
flushlist
=
nuts
.
flush_list
60
local
effective_glue
=
nuts
.
effective_glue
61
local
insert_node_after
=
nuts
.
insert_after
62
local
insert_node_before
=
nuts
.
insert_before
63
local
find_tail
=
nuts
.
tail
64
local
setglue
=
nuts
.
setglue
65
local
getrangedimensions
=
nuts
.
rangedimensions
66
local
hpack_nodes
=
nuts
.
hpack
67
local
copy_list
=
nuts
.
copy_list
68 69
local
nexthlist
=
nuts
.
traversers
.
hlist
70 71
local
nodecodes
=
nodes
.
nodecodes
72
local
rulecodes
=
nodes
.
rulecodes
73
local
gluecodes
=
nodes
.
gluecodes
74
local
listcodes
=
nodes
.
listcodes
75 76
local
glyph_code
=
nodecodes
.
glyph
77
local
localpar_code
=
nodecodes
.
localpar
78
local
dir_code
=
nodecodes
.
dir
79
local
glue_code
=
nodecodes
.
glue
80
local
hlist_code
=
nodecodes
.
hlist
81 82
local
indentlist_code
=
listcodes
.
indent
83
local
linelist_code
=
listcodes
.
line
84 85
local
leftskip_code
=
gluecodes
.
leftskip
86
local
rightskip_code
=
gluecodes
.
rightskip
87
local
parfillskip_code
=
gluecodes
.
parfillskip
88 89
local
nodepool
=
nuts
.
pool
90 91
local
new_rule
=
nodepool
.
rule
92
local
new_userrule
=
nodepool
.
userrule
93
local
new_kern
=
nodepool
.
kern
94
local
new_leader
=
nodepool
.
leader
95 96
local
n_tostring
=
nodes
.
idstostring
97
local
n_tosequence
=
nodes
.
tosequence
98 99
local
variables
=
interfaces
.
variables
100
local
implement
=
interfaces
.
implement
101 102
local
privateattributes
=
attributes
.
private
103 104
local
a_ruled
=
privateattributes
(
'
ruled
'
)
105
local
a_runningtext
=
privateattributes
(
'
runningtext
'
)
106
local
a_color
=
privateattributes
(
'
color
'
)
107
local
a_transparency
=
privateattributes
(
'
transparency
'
)
108
local
a_colormodel
=
privateattributes
(
'
colormodel
'
)
109
local
a_linefiller
=
privateattributes
(
"
linefiller
"
)
110
local
a_viewerlayer
=
privateattributes
(
"
viewerlayer
"
)
111 112
local
v_both
=
variables
.
both
113
local
v_left
=
variables
.
left
114
local
v_right
=
variables
.
right
115
local
v_local
=
variables
[
"
local
"
]
116
local
v_yes
=
variables
.
yes
117
local
v_foreground
=
variables
.
foreground
118 119
local
fonthashes
=
fonts
.
hashes
120
local
fontdata
=
fonthashes
.
identifiers
121
local
fontresources
=
fonthashes
.
resources
122 123
local
dimenfactor
=
fonts
.
helpers
.
dimenfactor
124
local
splitdimen
=
number
.
splitdimen
125
local
setmetatableindex
=
table
.
setmetatableindex
126 127
local
magicconstants
=
tex
.
magicconstants
128
local
running
=
magicconstants
.
running
129 130
--
131 132
local
striprange
=
nuts
.
striprange
133
local
processwords
=
nuts
.
processwords
134 135
--
136 137
local
rules
=
nodes
.
rules
or
{
}
138
nodes
.
rules
=
rules
139
rules
.
data
=
rules
.
data
or
{
}
140 141
local
nutrules
=
nuts
.
rules
or
{
}
142
nuts
.
rules
=
nutrules
-- not that many
143 144
storage
.
register
(
"
nodes/rules/data
"
,
rules
.
data
,
"
nodes.rules.data
"
)
145 146
local
data
=
rules
.
data
147 148
-- we implement user rules here as it takes less code this way
149 150
local
function
usernutrule
(
t
,
noattributes
)
151
local
r
=
new_userrule
(
t
.
width
or
0
,
t
.
height
or
0
,
t
.
depth
or
0
)
152
if
noattributes
=
=
false
or
noattributes
=
=
nil
then
153
-- avoid fuzzy ones
154
else
155
setattrlist
(
r
,
true
)
156
end
157
properties
[
r
]
=
t
158
return
r
159
end
160 161
nutrules
.
userrule
=
usernutrule
162 163
local
function
userrule
(
t
,
noattributes
)
164
return
tonode
(
usernutrule
(
t
,
noattributes
)
)
165
end
166 167
rules
.
userrule
=
userrule
168
local
ruleactions
=
{
}
169 170
rules
.
ruleactions
=
ruleactions
171
nutrules
.
ruleactions
=
ruleactions
-- convenient
172 173
local
function
mathaction
(
n
,
h
,
v
,
what
)
174
local
font
=
getruledata
(
n
)
175
local
actions
=
fontresources
[
font
]
.
mathruleactions
176
if
actions
then
177
local
action
=
actions
[
what
]
178
if
action
then
179
action
(
n
,
h
,
v
,
font
)
180
end
181
end
182
end
183 184
local
function
mathradical
(
n
,
h
,
v
)
185
mathaction
(
n
,
h
,
v
,
"
radicalaction
"
)
186
end
187 188
local
function
mathrule
(
n
,
h
,
v
)
189
mathaction
(
n
,
h
,
v
,
"
hruleaction
"
)
190
end
191 192
local
x
193 194
local
function
useraction
(
n
,
h
,
v
)
195
local
p
=
properties
[
n
]
196
if
p
then
197
local
i
=
p
.
type
or
"
draw
"
198
local
a
=
ruleactions
[
i
]
199
if
a
then
200
a
(
p
,
h
,
v
,
i
,
n
)
201
end
202
end
203
end
204 205
local
subtypeactions
=
{
206
[
rulecodes
.
user
]
=
useraction
,
207
[
rulecodes
.
over
]
=
mathrule
,
208
[
rulecodes
.
under
]
=
mathrule
,
209
[
rulecodes
.
fraction
]
=
mathrule
,
210
[
rulecodes
.
radical
]
=
mathradical
,
211
}
212 213
local
function
process_rule
(
n
,
h
,
v
)
214
local
n
=
tonut
(
n
)
215
local
s
=
getsubtype
(
n
)
216
local
a
=
subtypeactions
[
s
]
217
if
a
then
218
a
(
n
,
h
,
v
)
219
end
220
end
221 222
callbacks
.
register
(
"
process_rule
"
,
process_rule
,
"
handle additional user rule features
"
)
223 224
callbacks
.
functions
.
process_rule
=
process_rule
225 226
--
227 228
local
trace_ruled
=
false
trackers
.
register
(
"
nodes.rules
"
,
function
(
v
)
trace_ruled
=
v
end
)
229
local
report_ruled
=
logs
.
reporter
(
"
nodes
"
,
"
rules
"
)
230 231
function
rules
.
define
(
settings
)
232
local
nofdata
=
#
data
+
1
233
data
[
nofdata
]
=
settings
234
local
text
=
settings
.
text
235
if
text
then
236
local
b
=
nuts
.
takebox
(
text
)
237
if
b
then
238
nodepool
.
register
(
b
)
239
settings
.
text
=
getlist
(
b
)
240
else
241
settings
.
text
=
nil
242
end
243
end
244
return
nofdata
245
end
246 247
local
function
flush_ruled
(
head
,
f
,
l
,
d
,
level
,
parent
,
strip
)
-- not that fast but acceptable for this purpose
248
local
font
=
nil
249
local
char
,
id
=
isglyph
(
f
)
250
if
char
then
251
font
=
id
252
elseif
id
=
=
hlist_code
then
253
font
=
getattr
(
f
,
a_runningtext
)
254
end
255
if
not
font
then
256
-- saveguard ... we need to deal with rules and so (math)
257
return
head
258
end
259
local
r
,
m
260
if
strip
then
261
if
trace_ruled
then
262
local
before
=
n_tosequence
(
f
,
l
,
true
)
263
f
,
l
=
striprange
(
f
,
l
)
264
local
after
=
n_tosequence
(
f
,
l
,
true
)
265
report_ruled
(
"
range stripper, before %a, after %a
"
,
before
,
after
)
266
else
267
f
,
l
=
striprange
(
f
,
l
)
268
end
269
end
270
if
not
f
then
271
return
head
272
end
273
local
wd
,
ht
,
dp
=
getrangedimensions
(
parent
,
f
,
getnext
(
l
)
)
274
local
method
=
d
.
method
275
local
empty
=
d
.
empty
=
=
v_yes
276
local
offset
=
d
.
offset
277
local
dy
=
d
.
dy
278
local
order
=
d
.
order
279
local
max
=
d
.
max
280
local
mp
=
d
.
mp
281
local
rulethickness
=
d
.
rulethickness
282
local
unit
=
d
.
unit
283
local
ma
=
d
.
ma
284
local
ca
=
d
.
ca
285
local
ta
=
d
.
ta
286
local
colorspace
=
ma
>
0
and
ma
or
getattr
(
f
,
a_colormodel
)
or
1
287
local
color
=
ca
>
0
and
ca
or
getattr
(
f
,
a_color
)
288
local
transparency
=
ta
>
0
and
ta
or
getattr
(
f
,
a_transparency
)
289
local
foreground
=
order
=
=
v_foreground
290
local
layer
=
getattr
(
f
,
a_viewerlayer
)
291
local
e
=
dimenfactor
(
unit
,
font
)
-- what if no glyph node
292
local
rt
=
tonumber
(
rulethickness
)
293
if
rt
then
294
rulethickness
=
e
*
rulethickness
/
2
295
else
296
local
n
,
u
=
splitdimen
(
rulethickness
)
297
if
n
and
u
then
-- we need to intercept ex and em and % and ...
298
rulethickness
=
n
*
dimenfactor
(
u
,
fontdata
[
font
]
)
/
2
299
else
300
rulethickness
=
1
/
5
301
end
302
end
303
--
304
if
level
>
max
then
305
level
=
max
306
end
307
if
method
=
=
0
then
-- center
308
offset
=
2
*
offset
309
m
=
(
offset
+
(
level
-1
)
*
dy
)
*
e
/
2
+
rulethickness
/
2
310
else
311
m
=
0
312
end
313 314
local
function
inject
(
r
,
wd
,
ht
,
dp
)
315
if
layer
then
316
setattr
(
r
,
a_viewerlayer
,
layer
)
317
end
318
if
empty
then
319
head
=
insert_node_before
(
head
,
f
,
r
)
320
setlink
(
r
,
getnext
(
l
)
)
321
setprev
(
f
)
322
setnext
(
l
)
323
flushlist
(
f
)
324
else
325
local
k
=
new_kern
(
-
wd
)
326
if
foreground
then
327
insert_node_after
(
head
,
l
,
k
)
328
insert_node_after
(
head
,
k
,
r
)
329
l
=
r
330
else
331
head
=
insert_node_before
(
head
,
f
,
r
)
332
insert_node_after
(
head
,
r
,
k
)
333
end
334
end
335
if
trace_ruled
then
336
report_ruled
(
"
level %a, width %p, height %p, depth %p, nodes %a, text %a
"
,
337
level
,
wd
,
ht
,
dp
,
n_tostring
(
f
,
l
)
,
n_tosequence
(
f
,
l
,
true
)
)
338
end
339
end
340
if
mp
and
mp
~
=
"
"
then
341
local
r
=
usernutrule
{
342
width
=
wd
,
343
height
=
ht
,
344
depth
=
dp
,
345
type
=
"
mp
"
,
346
factor
=
e
,
347
offset
=
offset
,
348
line
=
rulethickness
,
349
data
=
mp
,
350
ma
=
colorspace
,
351
ca
=
color
,
352
ta
=
transparency
,
353
}
354
inject
(
r
,
wd
,
ht
,
dp
)
355
else
356
local
tx
=
d
.
text
357
if
tx
then
358
local
l
=
copy_list
(
tx
)
359
if
d
[
"
repeat
"
]
=
=
v_yes
then
360
l
=
new_leader
(
wd
,
l
)
361
setattrlist
(
l
,
tx
)
362
end
363
l
=
hpack_nodes
(
l
,
wd
,
"
exactly
"
)
364
inject
(
l
,
wd
,
ht
,
dp
)
365
else
366
for
i
=
1
,
level
do
367
local
hd
=
(
offset
+
(
i
-1
)
*
dy
)
*
e
-
m
368
-- local ht = hd + rulethickness - m
369
-- local dp = -hd + rulethickness + m
370
local
ht
=
hd
+
rulethickness
371
local
dp
=
-
hd
+
rulethickness
372
local
r
=
new_rule
(
wd
,
ht
,
dp
)
373
-- can be done more efficient
374
if
color
then
375
setattr
(
r
,
a_colormodel
,
colorspace
)
376
setattr
(
r
,
a_color
,
color
)
377
end
378
if
transparency
then
379
setattr
(
r
,
a_transparency
,
transparency
)
380
end
381
inject
(
r
,
wd
,
ht
,
dp
)
382
end
383
end
384
end
385
return
head
386
end
387 388
rules
.
handler
=
function
(
head
)
389
return
processwords
(
a_ruled
,
data
,
flush_ruled
,
head
)
390
end
391 392
function
rules
.
enable
(
)
393
enableaction
(
"
shipouts
"
,
"
nodes.rules.handler
"
)
394
end
395 396
local
trace_shifted
=
false
trackers
.
register
(
"
nodes.shifting
"
,
function
(
v
)
trace_shifted
=
v
end
)
397 398
local
report_shifted
=
logs
.
reporter
(
"
nodes
"
,
"
shifting
"
)
399 400
local
a_shifted
=
attributes
.
private
(
'
shifted
'
)
401 402
local
shifts
=
nodes
.
shifts
or
{
}
403
nodes
.
shifts
=
shifts
404
shifts
.
data
=
shifts
.
data
or
{
}
405 406
storage
.
register
(
"
nodes/shifts/data
"
,
shifts
.
data
,
"
nodes.shifts.data
"
)
407 408
local
data
=
shifts
.
data
409 410
function
shifts
.
define
(
settings
)
411
local
nofdata
=
#
data
+
1
412
data
[
nofdata
]
=
settings
413
return
nofdata
414
end
415 416
local
function
flush_shifted
(
head
,
first
,
last
,
data
,
level
,
parent
,
strip
)
-- not that fast but acceptable for this purpose
417
if
true
then
418
first
,
last
=
striprange
(
first
,
last
)
419
end
420
local
prev
=
getprev
(
first
)
421
local
next
=
getnext
(
last
)
422
setprev
(
first
)
423
setnext
(
last
)
424
local
width
,
height
,
depth
=
getrangedimensions
(
parent
,
first
,
next
)
425
local
list
=
hpack_nodes
(
first
,
width
,
"
exactly
"
)
-- we can use a simple pack
426
if
first
=
=
head
then
427
head
=
list
428
end
429
if
prev
then
430
setlink
(
prev
,
list
)
431
end
432
if
next
then
433
setlink
(
list
,
next
)
434
end
435
local
raise
=
data
.
dy
*
dimenfactor
(
data
.
unit
,
fontdata
[
getfont
(
first
)
]
)
436
setshift
(
list
,
raise
)
437
setwhd
(
list
,
width
,
height
,
depth
)
438
if
trace_shifted
then
439
report_shifted
(
"
width %p, nodes %a, text %a
"
,
width
,
n_tostring
(
first
,
last
)
,
n_tosequence
(
first
,
last
,
true
)
)
440
end
441
return
head
442
end
443 444
shifts
.
handler
=
function
(
head
)
445
return
processwords
(
a_shifted
,
data
,
flush_shifted
,
head
)
446
end
447 448
function
shifts
.
enable
(
)
449
enableaction
(
"
shipouts
"
,
"
nodes.shifts.handler
"
)
450
end
451 452
-- linefillers
453 454
local
linefillers
=
nodes
.
linefillers
or
{
}
455
nodes
.
linefillers
=
linefillers
456
linefillers
.
data
=
linefillers
.
data
or
{
}
457 458
storage
.
register
(
"
nodes/linefillers/data
"
,
linefillers
.
data
,
"
nodes.linefillers.data
"
)
459 460
local
data
=
linefillers
.
data
461 462
function
linefillers
.
define
(
settings
)
463
local
nofdata
=
#
data
+
1
464
data
[
nofdata
]
=
settings
465
return
nofdata
466
end
467 468
local
function
linefiller
(
current
,
data
,
width
,
location
)
469
local
height
=
data
.
height
470
local
depth
=
data
.
depth
471
local
mp
=
data
.
mp
472
local
ma
=
data
.
ma
473
local
ca
=
data
.
ca
474
local
ta
=
data
.
ta
475
if
mp
and
mp
~
=
"
"
then
476
return
usernutrule
{
477
width
=
width
,
478
height
=
height
,
479
depth
=
depth
,
480
type
=
"
mp
"
,
481
line
=
data
.
rulethickness
,
482
data
=
mp
,
483
ma
=
ma
,
484
ca
=
ca
,
485
ta
=
ta
,
486
option
=
location
,
487
direction
=
getdirection
(
current
)
,
488
}
489
else
490
local
rule
=
new_rule
(
width
,
height
,
depth
)
491
if
ca
then
492
setattr
(
rule
,
a_colorspace
,
ma
)
493
setattr
(
rule
,
a_color
,
ca
)
494
end
495
if
ta
then
496
setattr
(
rule
,
a_transparency
,
ta
)
497
end
498
return
rule
499
end
500
end
501 502
function
linefillers
.
filler
(
current
,
data
,
width
,
height
,
depth
)
503
if
width
and
width
>
0
then
504
local
height
=
height
or
data
.
height
or
0
505
local
depth
=
depth
or
data
.
depth
or
0
506
if
(
height
+
depth
)
~
=
0
then
507
local
mp
=
data
.
mp
508
local
ma
=
data
.
ma
509
local
ca
=
data
.
ca
510
local
ta
=
data
.
ta
511
if
mp
and
mp
~
=
"
"
then
512
return
usernutrule
{
513
width
=
width
,
514
height
=
height
,
515
depth
=
depth
,
516
type
=
"
mp
"
,
517
line
=
data
.
rulethickness
,
518
data
=
mp
,
519
ma
=
ma
,
520
ca
=
ca
,
521
ta
=
ta
,
522
option
=
location
,
523
direction
=
getdirection
(
current
)
,
524
}
525
else
526
local
rule
=
new_rule
(
width
,
height
,
depth
)
527
if
ca
then
528
setattr
(
rule
,
a_colorspace
,
ma
)
529
setattr
(
rule
,
a_color
,
ca
)
530
end
531
if
ta
then
532
setattr
(
rule
,
a_transparency
,
ta
)
533
end
534
return
rule
535
end
536
end
537
end
538
end
539 540
local
function
find_attr
(
head
,
attr
)
541
while
head
do
542
local
a
=
head
[
attr
]
543
if
a
then
544
return
a
,
head
545
end
546
head
=
getnext
(
head
)
547
end
548
end
549 550
function
linefillers
.
handler
(
head
)
551
for
current
,
subtype
in
nexthlist
,
head
do
552
if
current
and
subtype
=
=
linelist_code
then
553
-- why doesn't leftskip take the attributes
554
-- or list[linefiller] or maybe first match (maybe we need a fast helper for that)
555
local
a
=
getattr
(
current
,
a_linefiller
)
556
if
a
then
557
local
class
=
a
%
1000
558
local
data
=
data
[
class
]
559
if
data
then
560
local
location
=
data
.
location
561
local
scope
=
data
.
scope
562
local
distance
=
data
.
distance
563
local
threshold
=
data
.
threshold
564
local
leftlocal
=
false
565
local
rightlocal
=
false
566
--
567
if
scope
=
=
v_right
then
568
leftlocal
=
true
569
elseif
scope
=
=
v_left
then
570
rightlocal
=
true
571
elseif
scope
=
=
v_local
then
572
leftlocal
=
true
573
rightlocal
=
true
574
end
575
--
576
local
list
=
getlist
(
current
)
577
--
578
if
location
=
=
v_left
or
location
=
=
v_both
then
579
local
lskip
=
nil
-- leftskip
580
local
iskip
=
nil
-- indentation
581
local
head
=
list
582
while
head
do
583
local
id
=
getid
(
head
)
584
if
id
=
=
glue_code
then
585
if
getsubtype
(
head
)
=
=
leftskip_code
then
586
lskip
=
head
587
else
588
break
589
end
590
elseif
id
=
=
localpar_code
or
id
=
=
dir_code
then
591
-- go on
592
elseif
id
=
=
hlist_code
then
593
if
getsubtype
(
head
)
=
=
indentlist_code
then
594
iskip
=
head
595
end
596
break
597
else
598
break
599
end
600
head
=
getnext
(
head
)
601
end
602
if
head
then
603
local
indentation
=
iskip
and
getwidth
(
iskip
)
or
0
604
local
leftfixed
=
lskip
and
getwidth
(
lskip
)
or
0
605
local
lefttotal
=
lskip
and
effective_glue
(
lskip
,
current
)
or
0
606
local
width
=
lefttotal
-
(
leftlocal
and
leftfixed
or
0
)
+
indentation
-
distance
607
if
width
>
threshold
then
608
if
iskip
then
609
setwidth
(
iskip
,
0
)
610
end
611
if
lskip
then
612
setglue
(
lskip
,
leftlocal
and
getwidth
(
lskip
)
or
nil
)
613
if
distance
>
0
then
614
insert_node_after
(
list
,
lskip
,
new_kern
(
distance
)
)
615
end
616
insert_node_after
(
list
,
lskip
,
linefiller
(
current
,
data
,
width
,
"
left
"
)
)
617
else
618
insert_node_before
(
list
,
head
,
linefiller
(
current
,
data
,
width
,
"
left
"
)
)
619
if
distance
>
0
then
620
insert_node_before
(
list
,
head
,
new_kern
(
distance
)
)
621
end
622
end
623
end
624
end
625
end
626
--
627
if
location
=
=
v_right
or
location
=
=
v_both
then
628
local
pskip
=
nil
-- parfillskip
629
local
rskip
=
nil
-- rightskip
630
local
tail
=
find_tail
(
list
)
631
while
tail
and
getid
(
tail
)
=
=
glue_code
do
632
local
subtype
=
getsubtype
(
tail
)
633
if
subtype
=
=
rightskip_code
then
634
rskip
=
tail
635
elseif
subtype
=
=
parfillskip_code
then
636
pskip
=
tail
637
else
638
break
639
end
640
tail
=
getprev
(
tail
)
641
end
642
if
tail
then
643
local
rightfixed
=
rskip
and
getwidth
(
rskip
)
or
0
644
local
righttotal
=
rskip
and
effective_glue
(
rskip
,
current
)
or
0
645
local
parfixed
=
pskip
and
getwidth
(
pskip
)
or
0
646
local
partotal
=
pskip
and
effective_glue
(
pskip
,
current
)
or
0
647
local
width
=
righttotal
-
(
rightlocal
and
rightfixed
or
0
)
+
partotal
-
distance
648
if
width
>
threshold
then
649
if
pskip
then
650
setglue
(
pskip
)
651
end
652
if
rskip
then
653
setglue
(
rskip
,
rightlocal
and
getwidth
(
rskip
)
or
nil
)
654
if
distance
>
0
then
655
insert_node_before
(
list
,
rskip
,
new_kern
(
distance
)
)
656
end
657
insert_node_before
(
list
,
rskip
,
linefiller
(
current
,
data
,
width
,
"
right
"
)
)
658
else
659
insert_node_after
(
list
,
tail
,
linefiller
(
current
,
data
,
width
,
"
right
"
)
)
660
if
distance
>
0
then
661
insert_node_after
(
list
,
tail
,
new_kern
(
distance
)
)
662
end
663
end
664
end
665
end
666
end
667
end
668
end
669
end
670
end
671
return
head
672
end
673 674
local
enable
=
false
675 676
function
linefillers
.
enable
(
)
677
if
not
enable
then
678
-- we could now nil it
679
enableaction
(
"
finalizers
"
,
"
nodes.linefillers.handler
"
)
680
enable
=
true
681
end
682
end
683 684
-- interface
685 686
implement
{
687
name
=
"
definerule
"
,
688
actions
=
{
rules
.
define
,
context
}
,
689
arguments
=
{
690
{
691
{
"
continue
"
}
,
692
{
"
unit
"
}
,
693
{
"
order
"
}
,
694
{
"
method
"
,
"
integer
"
}
,
695
{
"
offset
"
,
"
number
"
}
,
696
{
"
rulethickness
"
}
,
697
{
"
dy
"
,
"
number
"
}
,
698
{
"
max
"
,
"
number
"
}
,
699
{
"
ma
"
,
"
integer
"
}
,
700
{
"
ca
"
,
"
integer
"
}
,
701
{
"
ta
"
,
"
integer
"
}
,
702
{
"
mp
"
}
,
703
{
"
empty
"
}
,
704
{
"
text
"
,
"
integer
"
}
,
705
{
"
repeat
"
}
,
706
}
707
}
708
}
709 710
implement
{
711
name
=
"
enablerules
"
,
712
onlyonce
=
true
,
713
actions
=
rules
.
enable
714
}
715 716
implement
{
717
name
=
"
defineshift
"
,
718
actions
=
{
shifts
.
define
,
context
}
,
719
arguments
=
{
720
{
721
{
"
continue
"
}
,
722
{
"
unit
"
}
,
723
{
"
method
"
,
"
integer
"
}
,
724
{
"
dy
"
,
"
number
"
}
,
725
}
726
}
727
}
728 729
implement
{
730
name
=
"
enableshifts
"
,
731
onlyonce
=
true
,
732
actions
=
shifts
.
enable
733
}
734 735
implement
{
736
name
=
"
definelinefiller
"
,
737
actions
=
{
linefillers
.
define
,
context
}
,
738
arguments
=
{
739
{
740
{
"
method
"
,
"
integer
"
}
,
741
{
"
location
"
,
"
string
"
}
,
742
{
"
scope
"
,
"
string
"
}
,
743
{
"
mp
"
,
"
string
"
}
,
744
{
"
ma
"
,
"
integer
"
}
,
745
{
"
ca
"
,
"
integer
"
}
,
746
{
"
ta
"
,
"
integer
"
}
,
747
{
"
depth
"
,
"
dimension
"
}
,
748
{
"
height
"
,
"
dimension
"
}
,
749
{
"
distance
"
,
"
dimension
"
}
,
750
{
"
threshold
"
,
"
dimension
"
}
,
751
{
"
rulethickness
"
,
"
dimension
"
}
,
752
}
753
}
754
}
755 756
implement
{
757
name
=
"
enablelinefillers
"
,
758
onlyonce
=
true
,
759
actions
=
linefillers
.
enable
760
}
761 762
-- We add a bonus feature here (experiment):
763 764
interfaces
.
implement
{
765
name
=
"
autorule
"
,
766
arguments
=
{
767
{
768
{
"
width
"
,
"
dimension
"
}
,
769
{
"
height
"
,
"
dimension
"
}
,
770
{
"
depth
"
,
"
dimension
"
}
,
771
{
"
xoffset
"
,
"
dimension
"
}
,
772
{
"
yoffset
"
,
"
dimension
"
}
,
773
{
"
left
"
,
"
dimension
"
}
,
774
{
"
right
"
,
"
dimension
"
}
,
775
}
,
776
}
,
777
actions
=
function
(
t
)
778
local
n
=
new_rule
(
779
t
.
width
or
running
,
780
t
.
height
or
running
,
781
t
.
depth
or
running
782
)
783
setattrlist
(
n
,
true
)
784
setoffsets
(
n
,
t
.
xoffset
,
t
.
yoffset
)
-- ,t.left, t.right
785
local
l
=
t
.
left
786
local
r
=
t
.
right
787
if
l
then
788
setfield
(
n
,
"
left
"
,
l
)
789
end
790
if
r
then
791
setfield
(
n
,
"
right
"
,
r
)
792
end
793
context
(
tonode
(
n
)
)
794
end
795
}
796