typo-spa.lua /size: 8856 b    last modification: 2020-07-01 14:35
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
typo-spa
'
]
=
{
2
version
=
1
.
001
,
3
comment
=
"
companion to typo-spa.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
local
next
,
type
=
next
,
type
10 11
local
trace_spacing
=
false
trackers
.
register
(
"
typesetters.spacing
"
,
function
(
v
)
trace_spacing
=
v
end
)
12 13
local
report_spacing
=
logs
.
reporter
(
"
typesetting
"
,
"
spacing
"
)
14 15
local
nodes
,
fonts
,
node
=
nodes
,
fonts
,
node
16 17
local
fonthashes
=
fonts
.
hashes
18
local
quaddata
=
fonthashes
.
quads
19 20
local
texsetattribute
=
tex
.
setattribute
21
local
unsetvalue
=
attributes
.
unsetvalue
22 23
local
v_reset
=
interfaces
.
variables
.
reset
24 25
local
nuts
=
nodes
.
nuts
26 27
local
getnext
=
nuts
.
getnext
28
local
getprev
=
nuts
.
getprev
29
local
takeattr
=
nuts
.
takeattr
30
local
isglyph
=
nuts
.
isglyph
31 32
local
insert_node_before
=
nuts
.
insert_before
33
local
insert_node_after
=
nuts
.
insert_after
34
local
remove_node
=
nuts
.
remove
35
local
end_of_math
=
nuts
.
end_of_math
36 37
local
nodepool
=
nuts
.
pool
38
local
new_penalty
=
nodepool
.
penalty
39
local
new_glue
=
nodepool
.
glue
40 41
local
nodecodes
=
nodes
.
nodecodes
42
local
math_code
=
nodecodes
.
math
43 44
local
somespace
=
nodes
.
somespace
45
local
somepenalty
=
nodes
.
somepenalty
46 47
local
enableaction
=
nodes
.
tasks
.
enableaction
48 49
typesetters
=
typesetters
or
{
}
50
local
typesetters
=
typesetters
51 52
typesetters
.
spacings
=
typesetters
.
spacings
or
{
}
53
local
spacings
=
typesetters
.
spacings
54 55
spacings
.
mapping
=
spacings
.
mapping
or
{
}
56
spacings
.
numbers
=
spacings
.
numbers
or
{
}
57 58
local
a_spacings
=
attributes
.
private
(
"
spacing
"
)
59 60
storage
.
register
(
"
typesetters/spacings/mapping
"
,
spacings
.
mapping
,
"
typesetters.spacings.mapping
"
)
61 62
local
mapping
=
spacings
.
mapping
63
local
numbers
=
spacings
.
numbers
64 65
for
i
=
1
,
#
mapping
do
66
local
m
=
mapping
[
i
]
67
numbers
[
m
.
name
]
=
m
68
end
69 70
-- todo cache lastattr
71 72
function
spacings
.
handler
(
head
)
73
local
start
=
head
74
-- head is always begin of par (whatsit), so we have at least two prev nodes
75
-- penalty followed by glue
76
while
start
do
77
local
char
,
id
=
isglyph
(
start
)
78
if
char
then
79
local
attr
=
takeattr
(
start
,
a_spacings
)
80
if
attr
and
attr
>
0
then
81
local
data
=
mapping
[
attr
]
82
if
data
then
83
local
map
=
data
.
characters
[
char
]
84
if
map
then
85
local
font
=
id
86
local
left
=
map
.
left
87
local
right
=
map
.
right
88
local
alternative
=
map
.
alternative
89
local
quad
=
quaddata
[
font
]
90
local
prev
=
getprev
(
start
)
91
if
left
and
left
~
=
0
and
prev
then
92
local
ok
=
false
93
local
prevprev
=
getprev
(
prev
)
94
if
alternative
=
=
1
then
95
local
somespace
=
somespace
(
prev
,
true
)
96
if
somespace
then
97
local
somepenalty
=
somepenalty
(
prevprev
,
10000
)
98
if
somepenalty
then
99
if
trace_spacing
then
100
report_spacing
(
"
removing penalty and space before %C (left)
"
,
char
)
101
end
102
head
=
remove_node
(
head
,
prev
,
true
)
103
head
=
remove_node
(
head
,
prevprev
,
true
)
104
else
105
if
trace_spacing
then
106
report_spacing
(
"
removing space before %C (left)
"
,
char
)
107
end
108
head
=
remove_node
(
head
,
prev
,
true
)
109
end
110
end
111
ok
=
true
112
else
113
ok
=
not
(
somespace
(
prev
,
true
)
and
somepenalty
(
prevprev
,
true
)
)
or
somespace
(
prev
,
true
)
114
end
115
if
ok
then
116
if
trace_spacing
then
117
report_spacing
(
"
inserting penalty and space before %C (left)
"
,
char
)
118
end
119
insert_node_before
(
head
,
start
,
new_penalty
(
10000
)
)
120
insert_node_before
(
head
,
start
,
new_glue
(
left
*
quad
)
)
121
end
122
end
123
local
next
=
getnext
(
start
)
124
if
right
and
right
~
=
0
and
next
then
125
local
ok
=
false
126
local
nextnext
=
getnext
(
next
)
127
if
alternative
=
=
1
then
128
local
somepenalty
=
somepenalty
(
next
,
10000
)
129
if
somepenalty
then
130
local
somespace
=
somespace
(
nextnext
,
true
)
131
if
somespace
then
132
if
trace_spacing
then
133
report_spacing
(
"
removing penalty and space after %C right
"
,
char
)
134
end
135
head
=
remove_node
(
head
,
next
,
true
)
136
head
=
remove_node
(
head
,
nextnext
,
true
)
137
end
138
else
139
local
somespace
=
somespace
(
next
,
true
)
140
if
somespace
then
141
if
trace_spacing
then
142
report_spacing
(
"
removing space after %C (right)
"
,
char
)
143
end
144
head
=
remove_node
(
head
,
next
,
true
)
145
end
146
end
147
ok
=
true
148
else
149
ok
=
not
(
somepenalty
(
next
,
10000
)
and
somespace
(
nextnext
,
true
)
)
or
somespace
(
next
,
true
)
150
end
151
if
ok
then
152
if
trace_spacing
then
153
report_spacing
(
"
inserting penalty and space after %C (right)
"
,
char
)
154
end
155
insert_node_after
(
head
,
start
,
new_glue
(
right
*
quad
)
)
156
insert_node_after
(
head
,
start
,
new_penalty
(
10000
)
)
157
end
158
end
159
end
160
end
161
end
162
elseif
id
=
=
math_code
then
163
start
=
end_of_math
(
start
)
-- weird, can return nil .. no math end?
164
end
165
if
start
then
166
start
=
getnext
(
start
)
167
end
168
end
169
return
head
170
end
171 172
local
enabled
=
false
173 174
function
spacings
.
define
(
name
)
175
local
data
=
numbers
[
name
]
176
if
data
then
177
-- error
178
else
179
local
number
=
#
mapping
+
1
180
local
data
=
{
181
name
=
name
,
182
number
=
number
,
183
characters
=
{
}
,
184
}
185
mapping
[
number
]
=
data
186
numbers
[
name
]
=
data
187
end
188
end
189 190
function
spacings
.
setup
(
name
,
char
,
settings
)
191
local
data
=
numbers
[
name
]
192
if
not
data
then
193
-- error
194
else
195
data
.
characters
[
char
]
=
settings
196
end
197
end
198 199
function
spacings
.
set
(
name
)
200
local
n
=
unsetvalue
201
if
name
~
=
v_reset
then
202
local
data
=
numbers
[
name
]
203
if
data
then
204
if
not
enabled
then
205
enableaction
(
"
processors
"
,
"
typesetters.spacings.handler
"
)
206
enabled
=
true
207
end
208
n
=
data
.
number
or
unsetvalue
209
end
210
end
211
texsetattribute
(
a_spacings
,
n
)
212
end
213 214
function
spacings
.
reset
(
)
215
texsetattribute
(
a_spacings
,
unsetvalue
)
216
end
217 218
-- interface
219 220
local
implement
=
interfaces
.
implement
221 222
implement
{
223
name
=
"
definecharacterspacing
"
,
224
actions
=
spacings
.
define
,
225
arguments
=
"
string
"
226
}
227 228
implement
{
229
name
=
"
setupcharacterspacing
"
,
230
actions
=
spacings
.
setup
,
231
arguments
=
{
232
"
string
"
,
233
"
integer
"
,
234
{
235
{
"
left
"
,
"
number
"
}
,
236
{
"
right
"
,
"
number
"
}
,
237
{
"
alternative
"
,
"
integer
"
}
,
238
}
239
}
240
}
241 242
implement
{
243
name
=
"
setcharacterspacing
"
,
244
actions
=
spacings
.
set
,
245
arguments
=
"
string
"
246
}
247