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