font-imp-quality.lua /size: 20 Kb    last modification: 2020-07-01 14:35
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
font-imp-quality
'
]
=
{
2
version
=
1
.
001
,
3
comment
=
"
companion to font-ini.mkiv and hand-ini.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
if
not
context
then
return
end
10 11
local
next
,
type
,
tonumber
=
next
,
type
,
tonumber
12 13
local
fonts
=
fonts
14
local
utilities
=
utilities
15 16
local
handlers
=
fonts
.
handlers
17
local
otf
=
handlers
.
otf
18
local
afm
=
handlers
.
afm
19
local
registerotffeature
=
otf
.
features
.
register
20
local
registerafmfeature
=
afm
.
features
.
register
21 22
local
allocate
=
utilities
.
storage
.
allocate
23
local
getparameters
=
utilities
.
parsers
.
getparameters
24 25
local
implement
=
interfaces
and
interfaces
.
implement
26 27
local
trace_protrusion
=
false
trackers
.
register
(
"
fonts.protrusion
"
,
function
(
v
)
trace_protrusion
=
v
end
)
28
local
trace_expansion
=
false
trackers
.
register
(
"
fonts.expansion
"
,
function
(
v
)
trace_expansion
=
v
end
)
29 30
local
report_expansions
=
logs
.
reporter
(
"
fonts
"
,
"
expansions
"
)
31
local
report_protrusions
=
logs
.
reporter
(
"
fonts
"
,
"
protrusions
"
)
32 33
-- -- -- -- -- --
34
-- shared
35
-- -- -- -- -- --
36 37
local
function
get_class_and_vector
(
tfmdata
,
value
,
where
)
-- "expansions"
38
local
g_where
=
tfmdata
.
goodies
and
tfmdata
.
goodies
[
where
]
39
local
f_where
=
fonts
[
where
]
40
local
g_classes
=
g_where
and
g_where
.
classes
41
local
f_classes
=
f_where
and
f_where
.
classes
42
local
class
=
(
g_classes
and
g_classes
[
value
]
)
or
(
f_classes
and
f_classes
[
value
]
)
43
if
class
then
44
local
class_vector
=
class
.
vector
45
local
g_vectors
=
g_where
and
g_where
.
vectors
46
local
f_vectors
=
f_where
and
f_where
.
vectors
47
local
vector
=
(
g_vectors
and
g_vectors
[
class_vector
]
)
or
(
f_vectors
and
f_vectors
[
class_vector
]
)
48
return
class
,
vector
49
end
50
end
51 52
-- -- -- -- -- --
53
-- expansion (hz)
54
-- -- -- -- -- --
55 56
local
expansions
=
fonts
.
expansions
or
allocate
(
)
57 58
fonts
.
expansions
=
expansions
59 60
local
classes
=
expansions
.
classes
or
allocate
(
)
61
local
vectors
=
expansions
.
vectors
or
allocate
(
)
62 63
expansions
.
classes
=
classes
64
expansions
.
vectors
=
vectors
65 66
classes
.
preset
=
{
67
stretch
=
2
,
68
shrink
=
2
,
69
step
=
.
5
,
70
factor
=
1
,
71
}
72 73
classes
[
'
quality
'
]
=
{
74
stretch
=
2
,
75
shrink
=
2
,
76
step
=
.
5
,
77
vector
=
'
default
'
,
78
factor
=
1
,
79
}
80 81
vectors
[
'
default
'
]
=
{
82
[
0x0041
]
=
0
.
5
,
-- A
83
[
0x0042
]
=
0
.
7
,
-- B
84
[
0x0043
]
=
0
.
7
,
-- C
85
[
0x0044
]
=
0
.
5
,
-- D
86
[
0x0045
]
=
0
.
7
,
-- E
87
[
0x0046
]
=
0
.
7
,
-- F
88
[
0x0047
]
=
0
.
5
,
-- G
89
[
0x0048
]
=
0
.
7
,
-- H
90
[
0x004B
]
=
0
.
7
,
-- K
91
[
0x004D
]
=
0
.
7
,
-- M
92
[
0x004E
]
=
0
.
7
,
-- N
93
[
0x004F
]
=
0
.
5
,
-- O
94
[
0x0050
]
=
0
.
7
,
-- P
95
[
0x0051
]
=
0
.
5
,
-- Q
96
[
0x0052
]
=
0
.
7
,
-- R
97
[
0x0053
]
=
0
.
7
,
-- S
98
[
0x0055
]
=
0
.
7
,
-- U
99
[
0x0057
]
=
0
.
7
,
-- W
100
[
0x005A
]
=
0
.
7
,
-- Z
101
[
0x0061
]
=
0
.
7
,
-- a
102
[
0x0062
]
=
0
.
7
,
-- b
103
[
0x0063
]
=
0
.
7
,
-- c
104
[
0x0064
]
=
0
.
7
,
-- d
105
[
0x0065
]
=
0
.
7
,
-- e
106
[
0x0067
]
=
0
.
7
,
-- g
107
[
0x0068
]
=
0
.
7
,
-- h
108
[
0x006B
]
=
0
.
7
,
-- k
109
[
0x006D
]
=
0
.
7
,
-- m
110
[
0x006E
]
=
0
.
7
,
-- n
111
[
0x006F
]
=
0
.
7
,
-- o
112
[
0x0070
]
=
0
.
7
,
-- p
113
[
0x0071
]
=
0
.
7
,
-- q
114
[
0x0073
]
=
0
.
7
,
-- s
115
[
0x0075
]
=
0
.
7
,
-- u
116
[
0x0077
]
=
0
.
7
,
-- w
117
[
0x007A
]
=
0
.
7
,
-- z
118
[
0x0032
]
=
0
.
7
,
-- 2
119
[
0x0033
]
=
0
.
7
,
-- 3
120
[
0x0036
]
=
0
.
7
,
-- 6
121
[
0x0038
]
=
0
.
7
,
-- 8
122
[
0x0039
]
=
0
.
7
,
-- 9
123
}
124 125
vectors
[
'
quality
'
]
=
vectors
[
'
default
'
]
-- metatable ?
126 127
local
function
initialize
(
tfmdata
,
value
)
128
if
value
then
129
local
class
,
vector
=
get_class_and_vector
(
tfmdata
,
value
,
"
expansions
"
)
130
if
class
then
131
if
vector
then
132
local
stretch
=
class
.
stretch
or
0
133
local
shrink
=
class
.
shrink
or
0
134
local
step
=
class
.
step
or
0
135
local
factor
=
class
.
factor
or
1
136
if
trace_expansion
then
137
report_expansions
(
"
setting class %a, vector %a, factor %a, stretch %a, shrink %a, step %a
"
,
138
value
,
class
.
vector
,
factor
,
stretch
,
shrink
,
step
)
139
end
140
tfmdata
.
parameters
.
expansion
=
{
141
stretch
=
10
*
stretch
,
142
shrink
=
10
*
shrink
,
143
step
=
10
*
step
,
144
factor
=
factor
,
145
}
146
local
data
=
characters
and
characters
.
data
147
for
i
,
chr
in
next
,
tfmdata
.
characters
do
148
local
v
=
vector
[
i
]
149
if
data
and
not
v
then
-- we could move the data test outside (needed for plain)
150
local
d
=
data
[
i
]
151
if
d
then
152
local
s
=
d
.
shcode
153
if
not
s
then
154
-- sorry
155
elseif
type
(
s
)
=
=
"
table
"
then
156
v
=
(
(
vector
[
s
[
1
]
]
or
0
)
+
(
vector
[
s
[
#
s
]
]
or
0
)
)
/
2
157
else
158
v
=
vector
[
s
]
or
0
159
end
160
end
161
end
162
if
v
and
v
~
=
0
then
163
chr
.
expansion_factor
=
v
*
factor
164
else
-- can be option
165
chr
.
expansion_factor
=
factor
166
end
167
end
168
elseif
trace_expansion
then
169
report_expansions
(
"
unknown vector %a in class %a
"
,
class
.
vector
,
value
)
170
end
171
elseif
trace_expansion
then
172
report_expansions
(
"
unknown class %a
"
,
value
)
173
end
174
end
175
end
176 177
local
specification
=
{
178
name
=
"
expansion
"
,
179
description
=
"
apply hz optimization
"
,
180
initializers
=
{
181
base
=
initialize
,
182
node
=
initialize
,
183
}
184
}
185 186
registerotffeature
(
specification
)
187
registerafmfeature
(
specification
)
188 189
fonts
.
goodies
.
register
(
"
expansions
"
,
function
(
...
)
return
fonts
.
goodies
.
report
(
"
expansions
"
,
trace_expansion
,
...
)
end
)
190 191
implement
{
192
name
=
"
setupfontexpansion
"
,
193
arguments
=
"
2 strings
"
,
194
actions
=
function
(
class
,
settings
)
getparameters
(
classes
,
class
,
'
preset
'
,
settings
)
end
195
}
196 197
-- -- -- -- -- --
198
-- protrusion
199
-- -- -- -- -- --
200 201
fonts
.
protrusions
=
allocate
(
)
202
local
protrusions
=
fonts
.
protrusions
203 204
protrusions
.
classes
=
allocate
(
)
205
protrusions
.
vectors
=
allocate
(
)
206 207
local
classes
=
protrusions
.
classes
208
local
vectors
=
protrusions
.
vectors
209 210
-- the values need to be revisioned
211 212
classes
.
preset
=
{
213
factor
=
1
,
214
left
=
1
,
215
right
=
1
,
216
}
217 218
classes
[
'
pure
'
]
=
{
vector
=
'
pure
'
,
factor
=
1
}
219
classes
[
'
punctuation
'
]
=
{
vector
=
'
punctuation
'
,
factor
=
1
}
220
classes
[
'
alpha
'
]
=
{
vector
=
'
alpha
'
,
factor
=
1
}
221
classes
[
'
quality
'
]
=
{
vector
=
'
quality
'
,
factor
=
1
}
222 223
vectors
[
'
pure
'
]
=
{
224 225
[
0x002C
]
=
{
0
,
1
}
,
-- comma
226
[
0x002E
]
=
{
0
,
1
}
,
-- period
227
[
0x003A
]
=
{
0
,
1
}
,
-- colon
228
[
0x003B
]
=
{
0
,
1
}
,
-- semicolon
229
[
0x002D
]
=
{
0
,
1
}
,
-- hyphen
230
[
0x00AD
]
=
{
0
,
1
}
,
-- also hyphen
231
[
0x2013
]
=
{
0
,
0
.
50
}
,
-- endash
232
[
0x2014
]
=
{
0
,
0
.
33
}
,
-- emdash
233
[
0x3001
]
=
{
0
,
1
}
,
-- ideographic comma 、
234
[
0x3002
]
=
{
0
,
1
}
,
-- ideographic full stop 。
235
[
0x060C
]
=
{
0
,
1
}
,
-- arabic comma ،
236
[
0x061B
]
=
{
0
,
1
}
,
-- arabic semicolon ؛
237
[
0x06D4
]
=
{
0
,
1
}
,
-- arabic full stop ۔
238 239
}
240 241
vectors
[
'
punctuation
'
]
=
{
242 243
[
0x003F
]
=
{
0
,
0
.
20
}
,
-- ?
244
[
0x00BF
]
=
{
0
.
20
,
0
}
,
-- ¿
245
[
0x0021
]
=
{
0
,
0
.
20
}
,
-- !
246
[
0x00A1
]
=
{
0
.
20
,
0
,
}
,
-- ¡
247
[
0x0028
]
=
{
0
.
05
,
0
}
,
-- (
248
[
0x0029
]
=
{
0
,
0
.
05
}
,
-- )
249
[
0x005B
]
=
{
0
.
05
,
0
}
,
-- [
250
[
0x005D
]
=
{
0
,
0
.
05
}
,
-- ]
251
[
0x002C
]
=
{
0
,
0
.
70
}
,
-- comma
252
[
0x002E
]
=
{
0
,
0
.
70
}
,
-- period
253
[
0x003A
]
=
{
0
,
0
.
50
}
,
-- colon
254
[
0x003B
]
=
{
0
,
0
.
50
}
,
-- semicolon
255
[
0x002D
]
=
{
0
,
0
.
70
}
,
-- hyphen
256
[
0x00AD
]
=
{
0
,
0
.
70
}
,
-- also hyphen
257
[
0x2013
]
=
{
0
,
0
.
30
}
,
-- endash
258
[
0x2014
]
=
{
0
,
0
.
20
}
,
-- emdash
259
[
0x060C
]
=
{
0
,
0
.
70
}
,
-- arabic comma
260
[
0x061B
]
=
{
0
,
0
.
50
}
,
-- arabic semicolon
261
[
0x06D4
]
=
{
0
,
0
.
70
}
,
-- arabic full stop
262
[
0x061F
]
=
{
0
,
0
.
20
}
,
-- ؟
263 264
-- todo: left and right quotes: .5 double, .7 single
265 266
[
0x2039
]
=
{
0
.
70
,
0
.
70
}
,
-- left single guillemet ‹
267
[
0x203A
]
=
{
0
.
70
,
0
.
70
}
,
-- right single guillemet ›
268
[
0x00AB
]
=
{
0
.
50
,
0
.
50
}
,
-- left guillemet «
269
[
0x00BB
]
=
{
0
.
50
,
0
.
50
}
,
-- right guillemet »
270 271
[
0x2018
]
=
{
0
.
70
,
0
.
70
}
,
-- left single quotation mark ‘
272
[
0x2019
]
=
{
0
,
0
.
70
}
,
-- right single quotation mark ’
273
[
0x201A
]
=
{
0
.
70
,
0
}
,
-- single low-9 quotation mark ,
274
[
0x201B
]
=
{
0
.
70
,
0
}
,
-- single high-reversed-9 quotation mark ‛
275
[
0x201C
]
=
{
0
.
50
,
0
.
50
}
,
-- left double quotation mark “
276
[
0x201D
]
=
{
0
,
0
.
50
}
,
-- right double quotation mark ”
277
[
0x201E
]
=
{
0
.
50
,
0
}
,
-- double low-9 quotation mark „
278
[
0x201F
]
=
{
0
.
50
,
0
}
,
-- double high-reversed-9 quotation mark ‟
279 280
}
281 282
vectors
[
'
alpha
'
]
=
{
283 284
[
0x0041
]
=
{
.
05
,
.
05
}
,
-- A
285
[
0x0046
]
=
{
0
,
.
05
}
,
-- F
286
[
0x004A
]
=
{
.
05
,
0
}
,
-- J
287
[
0x004B
]
=
{
0
,
.
05
}
,
-- K
288
[
0x004C
]
=
{
0
,
.
05
}
,
-- L
289
[
0x0054
]
=
{
.
05
,
.
05
}
,
-- T
290
[
0x0056
]
=
{
.
05
,
.
05
}
,
-- V
291
[
0x0057
]
=
{
.
05
,
.
05
}
,
-- W
292
[
0x0058
]
=
{
.
05
,
.
05
}
,
-- X
293
[
0x0059
]
=
{
.
05
,
.
05
}
,
-- Y
294 295
[
0x006B
]
=
{
0
,
.
05
}
,
-- k
296
[
0x0072
]
=
{
0
,
.
05
}
,
-- r
297
[
0x0074
]
=
{
0
,
.
05
}
,
-- t
298
[
0x0076
]
=
{
.
05
,
.
05
}
,
-- v
299
[
0x0077
]
=
{
.
05
,
.
05
}
,
-- w
300
[
0x0078
]
=
{
.
05
,
.
05
}
,
-- x
301
[
0x0079
]
=
{
.
05
,
.
05
}
,
-- y
302 303
}
304 305
vectors
[
'
quality
'
]
=
table
.
merged
(
306
vectors
[
'
punctuation
'
]
,
307
vectors
[
'
alpha
'
]
308
)
309 310
-- As this is experimental code, users should not depend on it. The implications are still
311
-- discussed on the ConTeXt Dev List and we're not sure yet what exactly the spec is (the
312
-- next code is tested with a gyre font patched by / fea file made by Khaled Hosny). The
313
-- double trick should not be needed it proper hanging punctuation is used in which case
314
-- values < 1 can be used.
315
--
316
-- preferred (in context, usine vectors):
317
--
318
-- \definefontfeature[whatever][default][mode=node,protrusion=quality]
319
--
320
-- using lfbd and rtbd, with possibibility to enable only one side :
321
--
322
-- \definefontfeature[whocares][default][mode=node,protrusion=yes, opbd=yes,script=latn]
323
-- \definefontfeature[whocares][default][mode=node,protrusion=right,opbd=yes,script=latn]
324
--
325
-- idem, using multiplier
326
--
327
-- \definefontfeature[whocares][default][mode=node,protrusion=2,opbd=yes,script=latn]
328
-- \definefontfeature[whocares][default][mode=node,protrusion=double,opbd=yes,script=latn]
329
--
330
-- idem, using named feature file (less frozen):
331
--
332
-- \definefontfeature[whocares][default][mode=node,protrusion=2,opbd=yes,script=latn,featurefile=texgyrepagella-regularxx.fea]
333 334
classes
[
'
double
'
]
=
{
-- for testing opbd
335
factor
=
2
,
336
left
=
1
,
337
right
=
1
,
338
}
339 340
local
function
map_opbd_onto_protrusion
(
tfmdata
,
value
,
opbd
)
341
local
characters
=
tfmdata
.
characters
342
local
descriptions
=
tfmdata
.
descriptions
343
local
properties
=
tfmdata
.
properties
344
local
parameters
=
tfmdata
.
parameters
345
local
resources
=
tfmdata
.
resources
346
local
rawdata
=
tfmdata
.
shared
.
rawdata
347
local
lookuphash
=
rawdata
.
lookuphash
348
local
lookuptags
=
resources
.
lookuptags
349
local
script
=
properties
.
script
350
local
language
=
properties
.
language
351
local
units
=
parameters
.
units
352
local
done
,
factor
,
left
,
right
=
false
,
1
,
1
,
1
353
local
class
=
classes
[
value
]
354
if
class
then
355
factor
=
class
.
factor
or
1
356
left
=
class
.
left
or
1
357
right
=
class
.
right
or
1
358
else
359
factor
=
tonumber
(
value
)
or
1
360
end
361
local
lfactor
=
left
*
factor
362
local
rfactor
=
right
*
factor
363
if
trace_protrusion
then
364
report_protrusions
(
"
left factor %0.3F, right factor %0.3F
"
,
lfactor
,
rfactor
)
365
end
366
tfmdata
.
parameters
.
protrusion
=
{
367
factor
=
factor
,
368
left
=
left
,
369
right
=
right
,
370
}
371
if
opbd
~
=
"
right
"
then
372
local
validlookups
,
lookuplist
=
otf
.
collectlookups
(
rawdata
,
"
lfbd
"
,
script
,
language
)
373
if
validlookups
then
374
for
i
=
1
,
#
lookuplist
do
375
local
lookup
=
lookuplist
[
i
]
376
local
steps
=
lookup
.
steps
377
if
steps
then
378
if
trace_protrusion
then
379
report_protrusions
(
"
setting left using lfbd
"
)
380
end
381
for
i
=
1
,
#
steps
do
382
local
step
=
steps
[
i
]
383
local
coverage
=
step
.
coverage
384
if
coverage
then
385
for
k
,
v
in
next
,
coverage
do
386
if
v
=
=
true
then
387
-- zero
388
else
389
local
w
=
descriptions
[
k
]
.
width
390
local
d
=
-
v
[
1
]
391
if
w
=
=
0
or
d
=
=
0
then
392
-- ignored
393
else
394
local
p
=
lfactor
*
d
/
units
395
characters
[
k
]
.
left_protruding
=
p
396
if
trace_protrusion
then
397
report_protrusions
(
"
lfbd -> %0.3F %C
"
,
p
,
k
)
398
end
399
end
400
end
401
end
402
end
403
end
404
done
=
true
405
end
406
end
407
end
408
end
409
if
opbd
~
=
"
left
"
then
410
local
validlookups
,
lookuplist
=
otf
.
collectlookups
(
rawdata
,
"
rtbd
"
,
script
,
language
)
411
if
validlookups
then
412
for
i
=
1
,
#
lookuplist
do
413
local
lookup
=
lookuplist
[
i
]
414
local
steps
=
lookup
.
steps
415
if
steps
then
416
if
trace_protrusion
then
417
report_protrusions
(
"
setting right using rtbd
"
)
418
end
419
for
i
=
1
,
#
steps
do
420
local
step
=
steps
[
i
]
421
local
coverage
=
step
.
coverage
422
if
coverage
then
423
for
k
,
v
in
next
,
coverage
do
424
if
v
=
=
true
then
425
-- zero
426
else
427
local
w
=
descriptions
[
k
]
.
width
428
local
d
=
-
v
[
3
]
429
if
w
=
=
0
or
d
=
=
0
then
430
-- ignored
431
else
432
local
p
=
rfactor
*
d
/
units
433
characters
[
k
]
.
right_protruding
=
p
434
if
trace_protrusion
then
435
report_protrusions
(
"
rtbd -> %0.3F %C
"
,
p
,
k
)
436
end
437
end
438
end
439
end
440
end
441
end
442
end
443
done
=
true
444
end
445
end
446
end
447
end
448 449
-- The opbd test is just there because it was discussed on the context development list. However,
450
-- the mentioned fxlbi.otf font only has some kerns for digits. So, consider this feature not supported
451
-- till we have a proper test font.
452 453
local
function
initialize
(
tfmdata
,
value
)
454
if
value
then
455
local
opbd
=
tfmdata
.
shared
.
features
.
opbd
456
if
opbd
then
457
-- possible values: left right both yes no (experimental)
458
map_opbd_onto_protrusion
(
tfmdata
,
value
,
opbd
)
459
else
460
local
class
,
vector
=
get_class_and_vector
(
tfmdata
,
value
,
"
protrusions
"
)
461
if
class
then
462
if
vector
then
463
local
factor
=
class
.
factor
or
1
464
local
left
=
class
.
left
or
1
465
local
right
=
class
.
right
or
1
466
if
trace_protrusion
then
467
report_protrusions
(
"
setting class %a, vector %a, factor %a, left %a, right %a
"
,
468
value
,
class
.
vector
,
factor
,
left
,
right
)
469
end
470
local
data
=
characters
.
data
471
local
lfactor
=
left
*
factor
472
local
rfactor
=
right
*
factor
473
if
trace_protrusion
then
474
report_protrusions
(
"
left factor %0.3F, right factor %0.3F
"
,
lfactor
,
rfactor
)
475
end
476
tfmdata
.
parameters
.
protrusion
=
{
477
factor
=
factor
,
478
left
=
left
,
479
right
=
right
,
480
}
481
for
i
,
chr
in
next
,
tfmdata
.
characters
do
482
local
v
=
vector
[
i
]
483
local
pl
=
nil
484
local
pr
=
nil
485
if
v
then
486
pl
=
v
[
1
]
487
pr
=
v
[
2
]
488
else
489
local
d
=
data
[
i
]
490
if
d
then
491
local
s
=
d
.
shcode
492
if
not
s
then
493
-- sorry
494
elseif
type
(
s
)
=
=
"
table
"
then
495
local
vl
=
vector
[
s
[
1
]
]
496
local
vr
=
vector
[
s
[
#
s
]
]
497
if
vl
then
pl
=
vl
[
1
]
end
498
if
vr
then
pr
=
vr
[
2
]
end
499
else
500
v
=
vector
[
s
]
501
if
v
then
502
pl
=
v
[
1
]
503
pr
=
v
[
2
]
504
end
505
end
506
end
507
end
508
if
pl
and
pl
~
=
0
then
509
local
p
=
pl
*
lfactor
510
chr
.
left_protruding
=
p
511
if
trace_protrusion
then
512
report_protrusions
(
"
left -> %0.3F %C
"
,
p
,
i
)
513
end
514
end
515
if
pr
and
pr
~
=
0
then
516
local
p
=
pr
*
rfactor
517
chr
.
right_protruding
=
p
518
if
trace_protrusion
then
519
report_protrusions
(
"
right -> %0.3F %C
"
,
p
,
i
)
520
end
521
end
522
end
523
elseif
trace_protrusion
then
524
report_protrusions
(
"
unknown vector %a in class %a
"
,
class
.
vector
,
value
)
525
end
526
elseif
trace_protrusion
then
527
report_protrusions
(
"
unknown class %a
"
,
value
)
528
end
529
end
530
end
531
end
532 533
local
specification
=
{
534
name
=
"
protrusion
"
,
535
description
=
"
l/r margin character protrusion
"
,
536
initializers
=
{
537
base
=
initialize
,
538
node
=
initialize
,
539
}
540
}
541 542
registerotffeature
(
specification
)
543
registerafmfeature
(
specification
)
544 545
fonts
.
goodies
.
register
(
"
protrusions
"
,
function
(
...
)
return
fonts
.
goodies
.
report
(
"
protrusions
"
,
trace_protrusion
,
...
)
end
)
546 547
implement
{
548
name
=
"
setupfontprotrusion
"
,
549
arguments
=
"
2 strings
"
,
550
actions
=
function
(
class
,
settings
)
getparameters
(
classes
,
class
,
'
preset
'
,
settings
)
end
551
}
552 553
local
function
initialize
(
tfmdata
,
value
)
554
local
properties
=
tfmdata
.
properties
555
local
parameters
=
tfmdata
.
parameters
556
if
properties
then
557
value
=
tonumber
(
value
)
558
if
value
then
559
if
value
<
0
then
560
value
=
0
561
elseif
value
>
10
then
562
report_expansions
(
"
threshold for %a @ %p limited to 10 pct
"
,
properties
.
fontname
,
parameters
.
size
)
563
value
=
10
564
end
565
if
value
>
5
then
566
report_expansions
(
"
threshold for %a @ %p exceeds 5 pct
"
,
properties
.
fontname
,
parameters
.
size
)
567
end
568
end
569
properties
.
threshold
=
value
or
nil
-- nil enforces default
570
end
571
end
572 573
local
specification
=
{
574
name
=
"
threshold
"
,
575
description
=
"
threshold for quality features
"
,
576
initializers
=
{
577
base
=
initialize
,
578
node
=
initialize
,
579
}
580
}
581 582
registerotffeature
(
specification
)
583
registerafmfeature
(
specification
)
584