good-ini.lua /size: 11 Kb    last modification: 2020-07-01 14:35
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
good-ini
'
]
=
{
2
version
=
1
.
000
,
3
comment
=
"
companion to font-lib.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
-- depends on ctx
10 11
local
type
,
next
=
type
,
next
12
local
gmatch
=
string
.
gmatch
13
local
sortedhash
,
insert
=
table
.
sortedhash
,
table
.
insert
14 15
local
fonts
=
fonts
16 17
local
trace_goodies
=
false
trackers
.
register
(
"
fonts.goodies
"
,
function
(
v
)
trace_goodies
=
v
end
)
18
local
report_goodies
=
logs
.
reporter
(
"
fonts
"
,
"
goodies
"
)
19 20
local
allocate
=
utilities
.
storage
.
allocate
21
local
implement
=
interfaces
.
implement
22
local
findfile
=
resolvers
.
findfile
23
local
formatters
=
string
.
formatters
24 25
local
otf
=
fonts
.
handlers
.
otf
26
local
afm
=
fonts
.
handlers
.
afm
27
local
tfm
=
fonts
.
handlers
.
tfm
28 29
local
registerotffeature
=
otf
.
features
.
register
30
local
registerafmfeature
=
afm
.
features
.
register
31
local
registertfmfeature
=
tfm
.
features
.
register
32 33
local
addotffeature
=
otf
.
enhancers
.
addfeature
34 35
local
fontgoodies
=
fonts
.
goodies
or
{
}
36
fonts
.
goodies
=
fontgoodies
37 38
local
data
=
fontgoodies
.
data
or
{
}
39
fontgoodies
.
data
=
data
-- no allocate as we want to see what is there
40 41
local
list
=
fontgoodies
.
list
or
{
}
42
fontgoodies
.
list
=
list
-- no allocate as we want to see what is there
43 44
fontgoodies
.
suffixes
=
{
"
lfg
"
,
"
lua
"
}
-- lfg is context specific and should not be used elsewhere
45 46
local
contextsetups
=
fonts
.
specifiers
.
contextsetups
47 48
function
fontgoodies
.
report
(
what
,
trace
,
goodies
)
49
if
trace_goodies
or
trace
then
50
local
whatever
=
goodies
[
what
]
51
if
whatever
then
52
report_goodies
(
"
goodie %a found in %a
"
,
what
,
goodies
.
name
)
53
end
54
end
55
end
56 57
local
function
locate
(
filename
)
58
local
suffixes
=
fontgoodies
.
suffixes
59
for
i
=
1
,
#
suffixes
do
60
local
suffix
=
suffixes
[
i
]
61
local
fullname
=
findfile
(
file
.
addsuffix
(
filename
,
suffix
)
)
62
if
fullname
and
fullname
~
=
"
"
then
63
return
fullname
64
end
65
end
66
end
67 68
local
function
loadgoodies
(
filename
)
-- maybe a merge is better
69
local
goodies
=
data
[
filename
]
-- we assume no suffix is given
70
if
goodies
~
=
nil
then
71
-- found or tagged unfound
72
elseif
type
(
filename
)
=
=
"
string
"
then
73
local
fullname
=
locate
(
filename
)
74
if
not
fullname
or
fullname
=
=
"
"
then
75
report_goodies
(
"
goodie file %a is not found (suffixes: % t)
"
,
filename
,
fontgoodies
.
suffixes
)
76
data
[
filename
]
=
false
-- signal for not found
77
else
78
goodies
=
dofile
(
fullname
)
or
false
79
if
not
goodies
then
80
report_goodies
(
"
goodie file %a is invalid
"
,
fullname
)
81
return
nil
82
elseif
trace_goodies
then
83
report_goodies
(
"
goodie file %a is loaded
"
,
fullname
)
84
end
85
goodies
.
name
=
goodies
.
name
or
"
no name
"
86
for
i
=
1
,
#
list
do
87
local
g
=
list
[
i
]
88
if
trace_goodies
then
89
report_goodies
(
"
handling goodie %a
"
,
g
[
1
]
)
90
end
91
g
[
2
]
(
goodies
)
92
end
93
goodies
.
initialized
=
true
94
data
[
filename
]
=
goodies
95
end
96
end
97
return
goodies
98
end
99 100
function
fontgoodies
.
register
(
name
,
fnc
,
prepend
)
-- will be a proper sequencer
101
for
i
=
1
,
#
list
do
102
local
g
=
list
[
i
]
103
if
g
[
1
]
=
=
name
then
104
g
[
2
]
=
fnc
--overload
105
return
106
end
107
end
108
local
g
=
{
name
,
fnc
}
109
if
prepend
then
110
insert
(
list
,
g
,
prepend
=
=
true
and
1
or
prepend
)
111
else
112
insert
(
list
,
g
)
113
end
114
end
115 116
fontgoodies
.
load
=
loadgoodies
117 118
if
implement
then
119 120
implement
{
121
name
=
"
loadfontgoodies
"
,
122
actions
=
loadgoodies
,
123
arguments
=
"
string
"
,
124
overload
=
true
,
-- for now, permits new font loader
125
}
126 127
end
128 129
-- register goodies file
130 131
local
function
setgoodies
(
tfmdata
,
value
)
132
local
goodies
=
tfmdata
.
goodies
133
if
not
goodies
then
-- actually an error
134
goodies
=
{
}
135
tfmdata
.
goodies
=
goodies
136
end
137
for
filename
in
gmatch
(
value
,
"
[^, ]+
"
)
do
138
-- we need to check for duplicates
139
local
ok
=
loadgoodies
(
filename
)
140
if
ok
then
141
if
trace_goodies
then
142
report_goodies
(
"
assigning goodie %a
"
,
filename
)
143
end
144
goodies
[
#
goodies
+
1
]
=
ok
145
end
146
end
147
end
148 149
-- featuresets
150 151
local
function
flattenedfeatures
(
t
,
tt
)
152
-- first set value dominates
153
local
tt
=
tt
or
{
}
154
for
i
=
1
,
#
t
do
155
local
ti
=
t
[
i
]
156
local
ty
=
type
(
ti
)
157
if
ty
=
=
"
table
"
then
158
flattenedfeatures
(
ti
,
tt
)
159
elseif
ty
=
=
"
string
"
then
160
local
set
=
contextsetups
[
ti
]
161
if
set
then
162
for
k
,
v
in
next
,
set
do
163
if
k
~
=
"
number
"
then
164
tt
[
k
]
=
v
or
nil
165
end
166
end
167
else
168
-- bad
169
end
170
elseif
tt
[
ti
]
=
=
nil
then
171
tt
[
ti
]
=
true
172
end
173
end
174
for
k
,
v
in
next
,
t
do
175
if
type
(
k
)
~
=
"
number
"
then
-- not tonumber(k)
176
if
type
(
v
)
=
=
"
table
"
then
177
flattenedfeatures
(
v
,
tt
)
178
elseif
tt
[
k
]
=
=
nil
then
179
tt
[
k
]
=
v
180
end
181
end
182
end
183
return
tt
184
end
185 186
-- fonts.features.flattened = flattenedfeatures
187 188
local
function
prepare_features
(
goodies
,
name
,
set
)
189
if
set
then
190
local
ff
=
flattenedfeatures
(
set
)
191
local
fullname
=
goodies
.
name
.
.
"
::
"
.
.
name
192
local
n
,
s
=
fonts
.
specifiers
.
presetcontext
(
fullname
,
"
"
,
ff
)
193
goodies
.
featuresets
[
name
]
=
s
-- set
194
if
trace_goodies
then
195
report_goodies
(
"
feature set %a gets number %a and name %a
"
,
name
,
n
,
fullname
)
196
end
197
return
n
198
end
199
end
200 201
fontgoodies
.
prepare_features
=
prepare_features
202 203
local
function
initialize
(
goodies
)
204
local
featuresets
=
goodies
.
featuresets
205
if
featuresets
then
206
if
trace_goodies
then
207
report_goodies
(
"
checking featuresets in %a
"
,
goodies
.
name
)
208
end
209
for
name
,
set
in
next
,
featuresets
do
210
prepare_features
(
goodies
,
name
,
set
)
211
end
212
end
213
end
214 215
fontgoodies
.
register
(
"
featureset
"
,
initialize
)
216 217
local
function
setfeatureset
(
tfmdata
,
set
,
features
)
218
local
goodies
=
tfmdata
.
goodies
-- shared ?
219
if
goodies
then
220
local
properties
=
tfmdata
.
properties
221
local
what
222
for
i
=
1
,
#
goodies
do
223
-- last one wins
224
local
g
=
goodies
[
i
]
225
what
=
g
.
featuresets
and
g
.
featuresets
[
set
]
or
what
226
end
227
if
what
then
228
for
feature
,
value
in
next
,
what
do
229
if
features
[
feature
]
=
=
nil
then
230
features
[
feature
]
=
value
231
end
232
end
233
properties
.
mode
=
what
.
mode
or
properties
.
mode
234
end
235
end
236
end
237 238
-- postprocessors (we could hash processor and share code)
239 240
function
fontgoodies
.
registerpostprocessor
(
tfmdata
,
f
,
prepend
)
241
local
postprocessors
=
tfmdata
.
postprocessors
242
if
not
postprocessors
then
243
tfmdata
.
postprocessors
=
{
f
}
244
elseif
prepend
then
245
insert
(
postprocessors
,
f
,
prepend
=
=
true
and
1
or
prepend
)
246
else
247
insert
(
postprocessors
,
f
)
248
end
249
end
250 251
local
function
setpostprocessor
(
tfmdata
,
processor
)
252
local
goodies
=
tfmdata
.
goodies
253
if
goodies
and
type
(
processor
)
=
=
"
string
"
then
254
local
found
=
{
}
255
local
asked
=
utilities
.
parsers
.
settings_to_array
(
processor
)
256
for
i
=
1
,
#
goodies
do
257
local
g
=
goodies
[
i
]
258
local
p
=
g
.
postprocessors
259
if
p
then
260
for
i
=
1
,
#
asked
do
261
local
a
=
asked
[
i
]
262
local
f
=
p
[
a
]
263
if
type
(
f
)
=
=
"
function
"
then
264
found
[
a
]
=
f
265
end
266
end
267
end
268
end
269
local
postprocessors
=
tfmdata
.
postprocessors
or
{
}
270
for
i
=
1
,
#
asked
do
271
local
a
=
asked
[
i
]
272
local
f
=
found
[
a
]
273
if
f
then
274
postprocessors
[
#
postprocessors
+
1
]
=
f
275
end
276
end
277
if
#
postprocessors
>
0
then
278
tfmdata
.
postprocessors
=
postprocessors
279
end
280
end
281
end
282 283
local
function
setextrafeatures
(
tfmdata
)
284
local
goodies
=
tfmdata
.
goodies
285
if
goodies
then
286
for
i
=
1
,
#
goodies
do
287
local
g
=
goodies
[
i
]
288
local
f
=
g
.
features
289
if
f
then
290
local
rawdata
=
tfmdata
.
shared
.
rawdata
291
local
done
=
{
}
292
-- indexed
293
for
i
=
1
,
#
f
do
294
local
specification
=
f
[
i
]
295
local
feature
=
specification
.
name
296
if
feature
then
297
addotffeature
(
rawdata
,
feature
,
specification
)
298
registerotffeature
{
299
name
=
feature
,
300
description
=
formatters
[
"
extra: %s
"
]
(
feature
)
301
}
302
end
303
done
[
i
]
=
true
304
end
305
-- hashed
306
for
feature
,
specification
in
sortedhash
(
f
)
do
307
if
not
done
[
feature
]
then
308
feature
=
specification
.
name
or
feature
309
specification
.
name
=
feature
310
addotffeature
(
rawdata
,
feature
,
specification
)
311
registerotffeature
{
312
name
=
feature
,
313
description
=
formatters
[
"
extra: %s
"
]
(
feature
)
314
}
315
end
316
end
317
end
318
end
319
end
320
end
321 322
local
function
setextensions
(
tfmdata
)
323
local
goodies
=
tfmdata
.
goodies
324
if
goodies
then
325
for
i
=
1
,
#
goodies
do
326
local
g
=
goodies
[
i
]
327
local
e
=
g
.
extensions
328
if
e
then
329
local
goodie
=
g
.
name
or
"
unknown
"
330
for
i
=
1
,
#
e
do
331
local
name
=
"
extension-
"
.
.
i
332
-- report_goodies("adding extension %s from %s",name,goodie)
333
otf
.
enhancers
.
addfeature
(
tfmdata
.
shared
.
rawdata
,
name
,
e
[
i
]
)
334
end
335
end
336
end
337
end
338
end
339 340
-- installation
341 342
local
goodies_specification
=
{
343
name
=
"
goodies
"
,
344
description
=
"
goodies on top of built in features
"
,
345
initializers
=
{
346
position
=
1
,
347
base
=
setgoodies
,
348
node
=
setgoodies
,
349
}
350
}
351 352
registerotffeature
(
goodies_specification
)
353
registerafmfeature
(
goodies_specification
)
354
registertfmfeature
(
goodies_specification
)
355 356
-- maybe more of the following could be for type one too
357 358
registerotffeature
{
359
name
=
"
extrafeatures
"
,
360
description
=
"
extra features
"
,
361
default
=
true
,
362
initializers
=
{
363
position
=
2
,
364
base
=
setextrafeatures
,
365
node
=
setextrafeatures
,
366
}
367
}
368 369
registerotffeature
{
370
name
=
"
extensions
"
,
371
description
=
"
extensions to features
"
,
372
default
=
true
,
373
initializers
=
{
374
position
=
2
,
375
base
=
setextensions
,
376
node
=
setextensions
,
377
}
378
}
379 380
registerotffeature
{
381
name
=
"
featureset
"
,
382
description
=
"
goodie feature set
"
,
383
initializers
=
{
384
position
=
3
,
385
base
=
setfeatureset
,
386
node
=
setfeatureset
,
387
}
388
}
389 390
registerotffeature
{
391
name
=
"
postprocessor
"
,
392
description
=
"
goodie postprocessor
"
,
393
initializers
=
{
394
base
=
setpostprocessor
,
395
node
=
setpostprocessor
,
396
}
397
}
398