font-sel.lua /size: 33 Kb    last modification: 2020-07-01 14:35
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
font-sel
'
]
=
{
2
version
=
1
.
001
,
3
comment
=
"
companion to font-sel.mkvi
"
,
4
author
=
"
Wolfgang Schuster
"
,
5
copyright
=
"
Wolfgang Schuster
"
,
6
license
=
"
GNU General Public License
"
7
}
8 9
local
next
,
type
=
next
,
type
10 11
local
context
=
context
12
local
cleanname
=
fonts
.
names
.
cleanname
13
local
gsub
,
splitup
,
find
,
lower
=
string
.
gsub
,
string
.
splitup
,
string
.
find
,
string
.
lower
14
local
concat
,
sortedkeys
=
table
.
concat
,
table
.
sortedkeys
15
local
merge
,
remove
=
table
.
merge
,
table
.
remove
16
local
splitbase
,
removesuffix
=
file
.
splitbase
,
file
.
removesuffix
17
local
splitat
,
lpegmatch
=
lpeg
.
splitat
,
lpeg
.
match
18 19
local
formatters
=
string
.
formatters
20
local
settings_to_array
=
utilities
.
parsers
.
settings_to_array
21
local
settings_to_hash
=
utilities
.
parsers
.
settings_to_hash
22
local
allocate
=
utilities
.
storage
.
allocate
23 24
local
v_default
=
interfaces
.
variables
.
default
25 26
local
implement
=
interfaces
.
implement
27 28
local
fonts
=
fonts
29 30
local
getlookups
=
fonts
.
names
.
getlookups
31
local
registerdesignsizes
=
fonts
.
goodies
.
designsizes
.
register
32
local
bodyfontsizes
=
storage
.
shared
.
bodyfontsizes
33 34
fonts
.
select
=
fonts
.
select
or
{
}
35
local
selectfont
=
fonts
.
select
36 37
selectfont
.
data
=
selectfont
.
data
or
allocate
(
)
38
selectfont
.
fallbacks
=
selectfont
.
fallbacks
or
allocate
(
)
39
selectfont
.
methods
=
selectfont
.
methods
or
allocate
(
)
40
selectfont
.
extras
=
selectfont
.
extras
or
allocate
(
)
41
selectfont
.
alternatives
=
selectfont
.
alternatives
or
allocate
(
)
42
selectfont
.
presets
=
selectfont
.
presets
or
allocate
(
)
43
selectfont
.
defaults
=
selectfont
.
defaults
or
allocate
(
)
44 45
storage
.
register
(
"
fonts/select/presets
"
,
selectfont
.
presets
,
"
fonts.select.presets
"
)
46 47
local
data
=
selectfont
.
data
48
local
fallbacks
=
selectfont
.
fallbacks
49
local
methods
=
selectfont
.
methods
50
local
extras
=
selectfont
.
extras
51
local
alternatives
=
selectfont
.
alternatives
52
local
presets
=
selectfont
.
presets
53
local
defaults
=
selectfont
.
defaults
54 55
local
ctx_definefontsynonym
=
context
.
definefontsynonym
56
local
ctx_resetfontfallback
=
context
.
resetfontfallback
57
local
ctx_startfontclass
=
context
.
startfontclass
58
local
ctx_stopfontclass
=
context
.
stopfontclass
59
local
ctx_loadfontgoodies
=
context
.
loadfontgoodies
60
local
ctx_definefontfallback
=
context
.
definefontfallback
61
local
ctx_definetypeface
=
context
.
definetypeface
62
local
ctx_definebodyfont
=
context
.
definebodyfont
63 64
local
trace_register
=
false
trackers
.
register
(
"
selectfont.register
"
,
function
(
v
)
trace_register
=
v
end
)
65
local
trace_files
=
false
trackers
.
register
(
"
selectfont.files
"
,
function
(
v
)
trace_files
=
v
end
)
66
local
trace_features
=
false
trackers
.
register
(
"
selectfont.features
"
,
function
(
v
)
trace_features
=
v
end
)
67
local
trace_goodies
=
false
trackers
.
register
(
"
selectfont.goodies
"
,
function
(
v
)
trace_goodies
=
v
end
)
68
local
trace_alternatives
=
false
trackers
.
register
(
"
selectfont.alternatives
"
,
function
(
v
)
trace_alternatives
=
v
end
)
69
local
trace_typescript
=
false
trackers
.
register
(
"
selectfont.typescripts
"
,
function
(
v
)
trace_typescript
=
v
end
)
70 71
local
report_selectfont
=
logs
.
reporter
(
"
selectfont
"
)
72
local
report_files
=
logs
.
reporter
(
"
selectfont
"
,
"
files
"
)
73
local
report_features
=
logs
.
reporter
(
"
selectfont
"
,
"
features
"
)
74
local
report_goodies
=
logs
.
reporter
(
"
selectfont
"
,
"
goodies
"
)
75
local
report_typescript
=
logs
.
reporter
(
"
selectfont
"
,
"
typescripts
"
)
76 77
defaults
[
"
rm
"
]
=
{
features
=
{
[
"
sc
"
]
=
"
*,f:smallcaps
"
}
}
78
defaults
[
"
ss
"
]
=
{
features
=
{
[
"
sc
"
]
=
"
*,f:smallcaps
"
}
}
79 80
defaults
[
"
asanamath
"
]
=
{
options
=
{
extras
=
"
asana-math
"
,
features
=
"
math\\mathsizesuffix
"
,
goodies
=
"
anana-math
"
}
}
81
defaults
[
"
cambriamath
"
]
=
{
options
=
{
extras
=
"
cambria-math
"
,
features
=
"
math\\mathsizesuffix
"
,
goodies
=
"
cambria-math
"
}
}
82
defaults
[
"
dejavumath
"
]
=
{
options
=
{
extras
=
"
dejavu
"
,
features
=
"
math\\mathsizesuffix
"
}
}
83
defaults
[
"
neoeuler
"
]
=
{
options
=
{
extras
=
"
euler-math
"
,
features
=
"
math\\mathsizesuffix
"
}
}
84
defaults
[
"
latinmodernmath
"
]
=
{
options
=
{
extras
=
"
lm,lm-math
"
,
features
=
"
math\\mathsizesuffix,lm-math
"
,
goodies
=
"
lm
"
}
}
85
defaults
[
"
lucidabrightmathot
"
]
=
{
options
=
{
extras
=
"
lucida-opentype-math
"
,
features
=
"
math\\mathsizesuffix
"
,
goodies
=
"
lucida-opentype-math
"
}
}
86
defaults
[
"
minionmath
"
]
=
{
options
=
{
extras
=
"
minion-math
"
,
features
=
"
math\\mathsizesuffix
"
,
goodies
=
"
minion-math
"
}
}
87
defaults
[
"
texgyredejavumath
"
]
=
{
options
=
{
extras
=
"
dejavu
"
,
features
=
"
math\\mathsizesuffix
"
}
}
88
defaults
[
"
texgyrepagellamath
"
]
=
{
options
=
{
extras
=
"
texgyre
"
,
features
=
"
math\\mathsizesuffix
"
}
}
89
defaults
[
"
texgyrebonummath
"
]
=
{
options
=
{
extras
=
"
texgyre
"
,
features
=
"
math\\mathsizesuffix
"
}
}
90
defaults
[
"
texgyrescholamath
"
]
=
{
options
=
{
extras
=
"
texgyre
"
,
features
=
"
math\\mathsizesuffix
"
}
}
91
defaults
[
"
texgyretermesmath
"
]
=
{
options
=
{
extras
=
"
texgyre
"
,
features
=
"
math\\mathsizesuffix
"
}
}
92
defaults
[
"
xitsmath
"
]
=
{
options
=
{
extras
=
"
xits-math
"
,
features
=
"
math\\mathsizesuffix
"
,
goodies
=
"
xits-math
"
}
}
93 94
extras
[
"
features
"
]
=
function
(
data
,
alternative
,
features
)
95
local
d
=
data
.
options
.
features
96
local
e
=
gsub
(
gsub
(
features
,
"
*
"
,
d
)
,
"
{(.*)}
"
,
"
%1
"
)
97
local
f
=
data
.
features
98
if
trace_features
then
99
report_features
(
"
alternative '%s': saving features '%s'
"
,
alternative
,
e
)
100
end
101
if
not
f
then
102
f
=
{
}
103
data
.
features
=
f
104
end
105
f
[
alternative
]
=
e
106
end
107 108
extras
[
"
goodies
"
]
=
function
(
data
,
alternative
,
goodies
)
109
local
e
=
gsub
(
goodies
,
"
{(.*)}
"
,
"
%1
"
)
110
local
g
=
data
.
goodies
111
if
trace_goodies
then
112
report_goodies
(
"
alternative '%s': saving goodies '%s'
"
,
alternative
,
e
)
113
end
114
if
not
g
then
115
g
=
{
}
116
data
.
goodies
=
g
117
end
118
g
[
alternative
]
=
e
119
end
120 121
local
function
selectfont_savefile
(
data
,
alternative
,
bodyfontsize
,
size
,
file
)
122
local
f
=
data
.
files
123
local
p
,
n
=
splitbase
(
file
[
"
filename
"
]
)
124
local
t
=
file
[
"
format
"
]
125
local
r
=
file
[
"
rawname
"
]
126
if
t
=
=
"
ttc
"
then
127
n
=
formatters
[
"
%s(%s)
"
]
(
n
,
r
)
128
end
129
if
not
f
then
130
f
=
{
}
131
data
.
files
=
f
132
end
133
local
a
=
f
[
alternative
]
134
if
not
a
then
135
a
=
{
}
136
f
[
alternative
]
=
a
137
end
138
a
[
bodyfontsize
]
=
{
size
,
n
}
139
if
trace_files
then
140
report_files
(
"
alternative '%s': saving file '%s' for size '%s'
"
,
alternative
,
n
,
size
)
141
end
142
end
143 144
methods
[
"
name
"
]
=
function
(
data
,
alternative
,
name
)
145
local
family
=
data
.
metadata
.
family
146
local
filename
=
cleanname
(
gsub
(
name
,
"
*
"
,
family
)
)
147
if
trace_alternatives
then
148
report_selectfont
(
"
alternative '%s': using method 'name' with argument '%s'
"
,
alternative
,
filename
)
149
end
150
local
fontname
=
getlookups
{
fontname
=
filename
}
151
local
fullname
=
getlookups
{
fullname
=
filename
}
152
if
#
fontname
>
0
then
153
selectfont_savefile
(
data
,
alternative
,
0
,
"
default
"
,
fontname
[
1
]
)
154
elseif
#
fullname
>
0
then
155
selectfont_savefile
(
data
,
alternative
,
0
,
"
default
"
,
fullname
[
1
]
)
156
else
157
if
trace_alternatives
then
158
report_selectfont
(
"
alternative '%s': no font was found for the requested name '%s'
"
,
alternative
,
filename
)
159
end
160
end
161
end
162 163
methods
[
"
file
"
]
=
function
(
data
,
alternative
,
file
)
164
local
family
=
data
.
metadata
.
family
165
local
filename
=
cleanname
(
gsub
(
removesuffix
(
file
)
,
"
*
"
,
family
)
)
166
if
trace_alternatives
then
167
report_selectfont
(
"
alternative '%s': using method 'file' with argument '%s'
"
,
alternative
,
filename
)
168
end
169
local
filename
=
getlookups
{
cleanfilename
=
cleanname
(
filename
)
}
170
if
#
filename
>
0
then
171
selectfont_savefile
(
data
,
alternative
,
0
,
"
default
"
,
filename
[
1
]
)
172
else
173
if
trace_alternatives
then
174
report_selectfont
(
"
alternative '%s': no font was found for the requested file '%s'
"
,
alternative
,
cleanname
(
gsub
(
removesuffix
(
file
)
,
"
*
"
,
family
)
)
)
175
end
176
end
177
end
178 179
local
m_weight
=
{
180
[
"
thin
"
]
=
100
,
181
[
"
extralight
"
]
=
200
,
182
[
"
light
"
]
=
300
,
183
[
"
regular
"
]
=
400
,
184
[
"
medium
"
]
=
500
,
185
[
"
semibold
"
]
=
600
,
186
[
"
bold
"
]
=
700
,
187
[
"
extrabold
"
]
=
800
,
188
[
"
black
"
]
=
900
189
}
190 191
local
m_width
=
{
192
[
"
ultracondensed
"
]
=
1
,
193
[
"
extracondensed
"
]
=
2
,
194
[
"
condensed
"
]
=
3
,
195
[
"
semicondensed
"
]
=
4
,
196
[
"
normal
"
]
=
5
,
197
[
"
semiexpanded
"
]
=
6
,
198
[
"
expanded
"
]
=
7
,
199
[
"
extraexpanded
"
]
=
8
,
200
[
"
ultraexpanded
"
]
=
9
,
201
}
202 203
local
m_name
=
{
204
[
"
thin
"
]
=
{
weight
=
"
thin
"
}
,
205
[
"
thinitalic
"
]
=
{
weight
=
"
thin
"
,
style
=
"
italic
"
}
,
206
[
"
extralight
"
]
=
{
weight
=
"
extralight
"
}
,
207
[
"
extralightitalic
"
]
=
{
weight
=
"
extralight
"
,
style
=
"
italic
"
}
,
208
[
"
light
"
]
=
{
weight
=
"
light
"
}
,
209
[
"
lightitalic
"
]
=
{
weight
=
"
light
"
,
style
=
"
italic
"
}
,
210
[
"
regular
"
]
=
{
weight
=
{
"
regular
"
,
"
medium
"
}
}
,
211
[
"
italic
"
]
=
{
weight
=
{
"
regular
"
,
"
medium
"
}
,
style
=
"
italic
"
}
,
212
[
"
medium
"
]
=
{
weight
=
"
medium
"
}
,
213
[
"
mediumitalic
"
]
=
{
weight
=
"
medium
"
,
style
=
"
italic
"
}
,
214
[
"
semibold
"
]
=
{
weight
=
"
semibold
"
}
,
215
[
"
semibolditalic
"
]
=
{
weight
=
"
semibold
"
,
style
=
"
italic
"
}
,
216
[
"
bold
"
]
=
{
weight
=
{
"
bold
"
,
"
semibold
"
}
}
,
217
[
"
bolditalic
"
]
=
{
weight
=
{
"
bold
"
,
"
semibold
"
}
,
style
=
"
italic
"
}
,
218
[
"
extrabold
"
]
=
{
weight
=
"
extrabold
"
}
,
219
[
"
extrabolditalic
"
]
=
{
weight
=
"
extrabold
"
,
style
=
"
italic
"
}
,
220
[
"
black
"
]
=
{
weight
=
"
black
"
}
,
221
[
"
blackitalic
"
]
=
{
weight
=
"
black
"
,
style
=
"
italic
"
}
,
222
[
"
smallcaps
"
]
=
{
weight
=
"
regular
"
,
variant
=
"
smallcaps
"
}
,
223
}
224 225
local
m_alternative
=
{
226
[
"
tf
"
]
=
"
regular
"
,
227
[
"
bf
"
]
=
"
bold
"
,
228
[
"
it
"
]
=
"
italic
"
,
229
[
"
sl
"
]
=
"
italic
"
,
230
[
"
bi
"
]
=
"
bolditalic
"
,
231
[
"
bs
"
]
=
"
bolditalic
"
,
232
[
"
sc
"
]
=
"
smallcaps
"
233
}
234 235
local
function
m_style_family
(
family
)
236
local
askedname
=
cleanname
(
family
)
237
local
familyname
=
getlookups
{
familyname
=
askedname
}
238
local
family
=
getlookups
{
family
=
askedname
}
239
local
fontname
=
getlookups
{
fontname
=
askedname
}
240
if
#
familyname
>
0
then
241
return
familyname
242
elseif
#
family
>
0
then
243
return
family
244
elseif
#
fontname
>
0
then
245
local
fontfamily
=
fontname
[
1
]
[
"
familyname
"
]
246
report_selectfont
(
"
the name '%s' is not a proper family name, use '%s' instead.
"
,
askedname
,
fontfamily
)
247
return
nil
248
else
249
return
nil
250
end
251
end
252 253
local
function
m_style_subfamily
(
entries
,
style
,
family
)
254
local
t
=
{
}
255
local
style
=
cleanname
(
style
)
256
local
family
=
cleanname
(
family
)
257
for
index
,
entry
in
next
,
entries
do
258
if
entry
[
"
familyname
"
]
=
=
family
and
entry
[
"
subfamilyname
"
]
=
=
style
then
-- familyname + subfamilyname
259
t
[
#
t
+
1
]
=
entry
260
elseif
entry
[
"
family
"
]
=
=
family
and
entry
[
"
subfamily
"
]
=
=
style
then
-- family + subfamily
261
t
[
#
t
+
1
]
=
entry
262
end
263
end
264
return
#
t
~
=
0
and
t
or
nil
265
end
266 267
local
function
m_style_weight
(
entries
,
style
)
268
local
t
=
{
}
269
local
weight
=
m_name
[
style
]
and
m_name
[
style
]
[
"
weight
"
]
or
"
regular
"
270
if
type
(
weight
)
=
=
"
table
"
then
271
for
_
,
w
in
next
,
weight
do
272
local
found
=
false
273
local
pfmweight
=
m_weight
[
w
]
274
for
index
,
entry
in
next
,
entries
do
275
if
entry
[
"
pfmweight
"
]
=
=
pfmweight
then
276
found
=
true
277
t
[
#
t
+
1
]
=
entry
278
elseif
entry
[
"
weight
"
]
=
=
w
then
279
found
=
true
280
t
[
#
t
+
1
]
=
entry
281
end
282
end
283
if
found
then
break
end
284
end
285
else
286
local
pfmweight
=
m_weight
[
weight
]
287
for
index
,
entry
in
next
,
entries
do
288
if
entry
[
"
pfmweight
"
]
=
=
pfmweight
then
289
t
[
#
t
+
1
]
=
entry
290
elseif
entry
[
"
weight
"
]
=
=
weight
then
291
t
[
#
t
+
1
]
=
entry
292
end
293
end
294
end
295
return
#
t
~
=
0
and
t
or
nil
296
end
297 298
local
function
m_style_style
(
entries
,
style
)
299
local
t
=
{
}
300
local
style
=
m_name
[
style
]
and
m_name
[
style
]
[
"
style
"
]
or
"
normal
"
301
for
index
,
entry
in
next
,
entries
do
302
if
style
=
=
"
italic
"
and
entry
[
"
angle
"
]
and
entry
[
"
angle
"
]
~
=
0
then
303
t
[
#
t
+
1
]
=
entry
304
elseif
style
=
=
"
normal
"
and
entry
[
"
angle
"
]
and
entry
[
"
angle
"
]
~
=
0
then
305
-- Fix needed for fonts with wrong value for the style field
306
elseif
entry
[
"
style
"
]
=
=
style
then
307
t
[
#
t
+
1
]
=
entry
308
end
309
end
310
return
#
t
~
=
0
and
t
or
nil
311
end
312 313
local
function
m_style_variant
(
entries
,
style
)
314
local
t
=
{
}
315
local
variant
=
m_name
[
style
]
and
m_name
[
style
]
[
"
variant
"
]
or
"
normal
"
316
for
index
,
entry
in
next
,
entries
do
317
if
entry
[
"
variant
"
]
=
=
variant
then
318
t
[
#
t
+
1
]
=
entry
319
end
320
end
321
return
#
t
~
=
0
and
t
or
nil
322
end
323 324
local
function
m_style_width
(
entries
,
style
)
325
local
t
=
{
}
326
local
width
=
m_name
[
style
]
and
m_name
[
style
]
[
"
width
"
]
or
"
normal
"
327
local
pfmwidth
=
m_width
[
width
]
328
for
index
,
entry
in
next
,
entries
do
329
if
entry
[
"
pfmwidth
"
]
=
=
pfmwidth
then
330
t
[
#
t
+
1
]
=
entry
331
end
332
end
333
return
#
t
~
=
0
and
t
or
nil
334
end
335 336
local
function
m_style_size
(
data
,
alternative
,
entries
)
337
if
#
entries
=
=
1
then
338
selectfont_savefile
(
data
,
alternative
,
0
,
"
default
"
,
entries
[
1
]
)
339
else
340
for
index
,
entry
in
next
,
entries
do
341
local
minsize
=
entry
[
"
minsize
"
]
342
local
maxsize
=
entry
[
"
maxsize
"
]
343
if
minsize
and
maxsize
then
344
for
size
,
state
in
next
,
bodyfontsizes
do
345
local
bodyfontsize
,
_
=
number
.
splitdimen
(
size
)
346
bodyfontsize
=
bodyfontsize
*
10
347
if
minsize
<
bodyfontsize
and
bodyfontsize
<
maxsize
then
348
if
bodyfontsize
=
=
100
then
349
selectfont_savefile
(
data
,
alternative
,
0
,
"
default
"
,
entry
)
350
end
351
selectfont_savefile
(
data
,
alternative
,
bodyfontsize
,
size
,
entry
)
352
end
353
end
354
else
355
if
trace_alternatives
then
356
report_selectfont
(
"
alternative '%s': multiple files are available for the requested style '%s' from '%s'
"
,
alternative
,
style
,
family
)
357
end
358
end
359
end
360
end
361
end
362 363
methods
[
"
style
"
]
=
function
(
data
,
alternative
,
style
)
364
local
fontfamily
=
data
.
metadata
.
family
365
local
designsize
=
data
.
options
.
designsize
366
local
fontstyle
=
m_alternative
[
style
]
or
style
367
local
entries
=
m_style_family
(
fontfamily
)
368
if
entries
then
369
local
subfamily
=
m_style_subfamily
(
entries
,
fontstyle
,
fontfamily
)
370
if
subfamily
then
371
entries
=
subfamily
372
else
373
entries
=
m_style_weight
(
entries
,
fontstyle
)
374
if
entries
then
375
entries
=
m_style_style
(
entries
,
fontstyle
)
376
if
entries
then
377
entries
=
m_style_variant
(
entries
,
fontstyle
)
378
if
entries
and
#
entries
>
1
and
designsize
=
=
"
default
"
then
379
entries
=
m_style_width
(
entries
,
fontstyle
)
380
end
381
end
382
end
383
end
384
end
385
if
entries
then
386
m_style_size
(
data
,
alternative
,
entries
)
387
else
388
if
trace_alternatives
then
389
report_selectfont
(
"
alternative '%s': no font was found for the requested style '%s' from '%s'
"
,
alternative
,
style
,
family
)
390
end
391
end
392
end
393 394
methods
[
v_default
]
=
function
(
data
,
alternative
)
395
local
family
=
data
.
metadata
.
family
396
if
trace_alternatives
then
397
report_selectfont
(
"
alternative '%s': using method 'default'
"
,
alternative
)
398
end
399
local
result
=
getlookups
{
familyname
=
cleanname
(
family
)
}
400
if
#
result
=
=
1
and
alternative
=
=
"
tf
"
then
401
if
trace_alternatives
then
402
report_selectfont
(
"
alternative '%s': the family '%s' contains only one font
"
,
alternative
,
family
)
403
end
404
selectfont_savefile
(
data
,
alternative
,
0
,
"
default
"
,
result
[
1
]
)
405
-- if trace_alternatives then
406
-- report_selectfont("alternative '%s': changing method 'default' to method 'style'",alternative)
407
-- end
408
-- methods["file"](data,alternative,result[1]["filename"])
409
else
410
if
trace_alternatives
then
411
report_selectfont
(
"
alternative '%s': changing method 'default' to method 'style'
"
,
alternative
)
412
end
413
methods
[
"
style
"
]
(
data
,
alternative
,
alternative
)
414
end
415
end
416 417
local
function
selectfont_savealternative
(
data
,
alternative
,
userdata
)
418
local
a
=
data
.
alternatives
419
local
e
=
userdata
[
alternative
]
420
if
not
a
then
421
a
=
{
}
422
data
.
alternatives
=
a
423
end
424
a
[
alternative
]
=
e
425
end
426 427
function
selectfont
.
fontdata
(
index
)
428
local
data
=
data
[
index
]
429
local
style
=
data
.
metadata
.
style
430
local
defaults
=
defaults
[
style
]
431
if
defaults
then
432
for
category
,
argument
in
next
,
defaults
do
433
local
extra
=
extras
[
category
]
434
if
extra
then
435
for
alternative
,
entry
in
next
,
argument
do
436
extra
(
data
,
alternative
,
entry
)
437
end
438
end
439
end
440
end
441
end
442 443
function
selectfont
.
userdata
(
index
)
444
local
data
=
data
[
index
]
445
local
preset
=
data
.
options
.
preset
446
local
presets
=
presets
[
preset
]
447
local
userdata
=
settings_to_hash
(
data
.
userdata
)
448
if
presets
then
449
merge
(
userdata
,
presets
)
450
end
451
for
alternative
,
_
in
next
,
alternatives
do
452
selectfont_savealternative
(
data
,
alternative
,
userdata
)
453
end
454
end
455 456
function
selectfont
.
registerfiles
(
index
)
457
local
data
=
data
[
index
]
458
local
colon
=
splitat
(
"
:
"
,
true
)
459
for
alternative
,
_
in
next
,
alternatives
do
460
local
arguments
=
data
.
alternatives
[
alternative
]
461
if
arguments
and
arguments
~
=
"
"
then
462
local
entries
=
settings_to_array
(
arguments
)
463
for
index
,
entry
in
next
,
entries
do
464
method
,
argument
=
lpegmatch
(
colon
,
entry
)
465
if
not
argument
then
466
argument
=
method
467
method
=
"
name
"
468
end
469
(
extras
[
method
]
or
methods
[
method
]
or
methods
[
v_default
]
)
(
data
,
alternative
,
argument
)
470
end
471
else
472
methods
[
v_default
]
(
data
,
alternative
)
473
end
474
end
475
end
476 477
function
selectfont
.
registerfontalternative
(
alternative
)
478
local
a
=
alternatives
[
alternative
]
479
if
not
a
then
480
if
trace_register
then
481
report_selectfont
(
"
register alternative '%s'
"
,
alternative
)
482
end
483
a
=
true
484
alternatives
[
alternative
]
=
a
485
end
486
end
487 488
function
selectfont
.
registerfallback
(
index
)
489
local
data
=
data
[
index
]
490
local
fontclass
=
data
.
metadata
.
typeface
491
local
fontstyle
=
data
.
metadata
.
style
492
local
fallback
=
fallbacks
[
fontclass
]
493
if
not
fallback
then
494
fallback
=
{
}
495
fallbacks
[
fontclass
]
=
fallback
496
end
497
local
entries
=
fallback
[
fontstyle
]
498
if
not
entries
then
499
entries
=
{
}
500
fallback
[
fontstyle
]
=
entries
501
end
502
entries
[
#
entries
+
1
]
=
index
503
end
504 505
function
selectfont
.
registerfontfamily
(
settings
)
506
local
index
=
#
data
+
1
507
data
[
index
]
=
settings
508
selectfont
.
fontdata
(
index
)
509
selectfont
.
userdata
(
index
)
510
selectfont
.
registerfiles
(
index
)
511
return
index
512
end
513 514
local
m_synonym
=
{
515
[
"
rm
"
]
=
{
516
[
"
tf
"
]
=
"
Serif
"
,
517
[
"
bf
"
]
=
"
SerifBold
"
,
518
[
"
it
"
]
=
"
SerifItalic
"
,
519
[
"
sl
"
]
=
"
SerifSlanted
"
,
520
[
"
bi
"
]
=
"
SerifBoldItalic
"
,
521
[
"
bs
"
]
=
"
SerifBoldSlanted
"
,
522
[
"
sc
"
]
=
"
SerifCaps
"
,
523
}
,
524
[
"
ss
"
]
=
{
525
[
"
tf
"
]
=
"
Sans
"
,
526
[
"
bf
"
]
=
"
SansBold
"
,
527
[
"
it
"
]
=
"
SansItalic
"
,
528
[
"
sl
"
]
=
"
SansSlanted
"
,
529
[
"
bi
"
]
=
"
SansBoldItalic
"
,
530
[
"
bs
"
]
=
"
SansBoldSlanted
"
,
531
[
"
sc
"
]
=
"
SansCaps
"
,
532
}
,
533
[
"
tt
"
]
=
{
534
[
"
tf
"
]
=
"
Mono
"
,
535
[
"
bf
"
]
=
"
MonoBold
"
,
536
[
"
it
"
]
=
"
MonoItalic
"
,
537
[
"
sl
"
]
=
"
MonoSlanted
"
,
538
[
"
bi
"
]
=
"
MonoBoldItalic
"
,
539
[
"
bs
"
]
=
"
MonoBoldSlanted
"
,
540
[
"
sc
"
]
=
"
MonoCaps
"
,
541
}
,
542
[
"
mm
"
]
=
{
543
[
"
tf
"
]
=
"
MathRoman
"
,
544
[
"
bf
"
]
=
"
MathBold
"
,
545
}
,
546
[
"
hw
"
]
=
{
547
[
"
tf
"
]
=
"
Handwriting
"
,
548
}
,
549
[
"
cg
"
]
=
{
550
[
"
tf
"
]
=
"
Calligraphy
"
,
551
}
,
552
}
553 554
function
selectfont
.
features
(
data
,
style
,
alternative
)
555
local
family
=
data
.
metadata
.
family
556
local
features
=
data
.
features
557
local
options
=
data
.
options
558
local
defaults
=
defaults
[
cleanname
(
family
)
]
559
if
features
and
features
[
alternative
]
then
560
return
features
[
alternative
]
561
elseif
defaults
and
defaults
.
options
and
defaults
.
options
.
features
then
562
return
defaults
.
options
.
features
563
else
564
return
options
.
features
565
end
566
end
567 568
function
selectfont
.
goodies
(
data
,
style
,
alternative
)
569
local
family
=
data
.
metadata
.
family
570
local
goodies
=
data
.
goodies
571
local
options
=
data
.
options
572
local
defaults
=
defaults
[
cleanname
(
family
)
]
573
if
goodies
and
goodies
[
alternative
]
then
574
return
goodies
[
alternative
]
575
elseif
defaults
and
defaults
.
options
and
defaults
.
options
.
goodies
then
576
return
defaults
.
options
.
goodies
577
else
578
return
options
.
goodies
579
end
580
end
581 582
function
selectfont
.
fontsynonym
(
data
,
class
,
style
,
alternative
,
index
)
583
local
fontfiles
=
data
.
files
[
alternative
]
or
data
.
files
[
"
tf
"
]
584
local
fontsizes
=
sortedkeys
(
fontfiles
)
585
local
fallback
=
index
~
=
0
586
local
fontclass
=
lower
(
class
)
587
--local fontfeature = data.features and data.features[alternative] or data.options.features
588
--local fontgoodie = data.goodies and data.goodies [alternative] or data.options.goodies
589
local
fontfeature
=
selectfont
.
features
(
data
,
style
,
alternative
)
590
local
fontgoodie
=
selectfont
.
goodies
(
data
,
style
,
alternative
)
591
local
synonym
=
m_synonym
[
style
]
and
m_synonym
[
style
]
[
alternative
]
592
local
fontfile
=
formatters
[
"
file-%s-%s-%s
"
]
(
fontclass
,
style
,
alternative
)
593
local
fontsynonym
=
formatters
[
"
synonym-%s-%s-%s
"
]
(
fontclass
,
style
,
alternative
)
594
if
fallback
then
595
fontfile
=
formatters
[
"
file-%s-%s-%s-%s
"
]
(
fontclass
,
style
,
alternative
,
index
)
596
fontsynonym
=
formatters
[
"
synonym-%s-%s-%s-%s
"
]
(
fontclass
,
style
,
alternative
,
index
)
597
end
598
local
fontfallback
=
formatters
[
"
fallback-%s-%s-%s
"
]
(
fontclass
,
style
,
alternative
)
599
for
_
,
fontsize
in
next
,
fontsizes
do
600
-- if trace_typescript then
601
-- report_typescript("synonym: '%s', size: '%s', file: '%s'",fontfile,fontfiles[fontsize][1],fontfiles[fontsize][2])
602
-- end
603
registerdesignsizes
(
fontfile
,
fontfiles
[
fontsize
]
[
1
]
,
fontfiles
[
fontsize
]
[
2
]
)
604
end
605
if
fallback
then
606
-- if trace_typescript then
607
-- report_typescript("synonym: '%s', file: '%s', features: '%s'",fontsynonym,fontfile,fontfeature)
608
-- end
609
ctx_definefontsynonym
(
{
fontsynonym
}
,
{
fontfile
}
,
{
features
=
fontfeature
}
)
610
else
611
-- if trace_typescript then
612
-- report_typescript("synonym: '%s', file: '%s', features: '%s', goodies: '%s', fallbacks: '%s'",fontsynonym,fontfile,fontfeature,fontgoodie,fontfallback)
613
-- end
614
ctx_definefontsynonym
(
{
fontsynonym
}
,
{
fontfile
}
,
{
features
=
fontfeature
,
goodies
=
fontgoodie
,
fallbacks
=
fontfallback
}
)
615
if
synonym
then
616
-- if trace_typescript then
617
-- report_typescript("synonym: '%s', file: '%s'",synonym,fontsynonym)
618
-- end
619
ctx_definefontsynonym
(
{
synonym
}
,
{
fontsynonym
}
)
620
end
621
end
622
end
623 624
function
selectfont
.
fontfallback
(
data
,
class
,
style
,
alternative
,
index
)
625
local
range
=
data
.
options
.
range
626
local
scale
=
data
.
options
.
rscale
~
=
"
"
and
data
.
options
.
rscale
or
1
627
local
check
=
data
.
options
.
check
~
=
"
"
and
data
.
options
.
check
or
"
"
628
local
force
=
data
.
options
.
force
~
=
"
"
and
data
.
options
.
force
or
"
"
629
local
fontfeature
=
data
.
features
and
data
.
features
[
alternative
]
or
data
.
options
.
features
630
local
fontclass
=
lower
(
class
)
631
local
fontsynonym
=
formatters
[
"
synonym-%s-%s-%s-%s
"
]
(
fontclass
,
style
,
alternative
,
index
)
632
local
fontfallback
=
formatters
[
"
fallback-%s-%s-%s
"
]
(
fontclass
,
style
,
alternative
)
633
if
index
=
=
1
then
634
ctx_resetfontfallback
(
{
fontfallback
}
)
635
end
636
-- if trace_typescript then
637
-- report_typescript("fallback: '%s', synonym: '%s', range: '%s', scale: '%s', check: '%s', force: '%s'",fontfallback,fontsynonym,range,scale,check,force)
638
-- end
639
ctx_definefontfallback
(
{
fontfallback
}
,
{
fontsynonym
}
,
{
range
}
,
{
rscale
=
scale
,
check
=
check
,
force
=
force
}
)
640
end
641 642
function
selectfont
.
filefallback
(
data
,
class
,
style
,
alternative
,
index
)
643
local
range
=
data
.
options
.
range
644
local
offset
=
data
.
options
.
offset
645
local
scale
=
data
.
options
.
rscale
~
=
"
"
and
data
.
options
.
rscale
or
1
646
local
check
=
data
.
options
.
check
~
=
"
"
and
data
.
options
.
check
or
"
yes
"
647
local
force
=
data
.
options
.
force
~
=
"
"
and
data
.
options
.
force
or
"
yes
"
648
local
fontfile
=
data
.
files
[
alternative
]
and
data
.
files
[
alternative
]
[
0
]
or
data
.
files
[
"
tf
"
]
[
0
]
649
local
fontfeature
=
data
.
features
and
data
.
features
[
alternative
]
or
data
.
options
.
features
650
local
fontclass
=
lower
(
class
)
651
local
fontfallback
=
formatters
[
"
fallback-%s-%s-%s
"
]
(
fontclass
,
style
,
alternative
)
652
if
index
=
=
1
then
653
ctx_resetfontfallback
(
{
fontfallback
}
)
654
end
655
-- if trace_typescript then
656
-- report_typescript("fallback: '%s', file: '%s', features: '%s', range: '%s', scale: '%s', check: '%s', force: '%s', offset: '%s'",fontfallback,fontfile[2],fontfeature,range,scale,check,force,offset)
657
-- end
658
ctx_definefontfallback
(
{
fontfallback
}
,
{
formatters
[
"
file:%s*%s
"
]
(
fontfile
[
2
]
,
fontfeature
)
}
,
{
range
}
,
{
rscale
=
scale
,
check
=
check
,
force
=
force
,
offset
=
offset
}
)
659
end
660 661
function
selectfont
.
mathfallback
(
index
,
entry
,
class
,
style
)
662
local
data
=
data
[
entry
]
663
ctx_startfontclass
(
{
class
}
)
664
for
alternative
,
_
in
next
,
alternatives
do
665
if
alternative
=
=
"
tf
"
or
alternative
=
=
"
bf
"
then
666
selectfont
.
filefallback
(
data
,
class
,
style
,
alternative
,
index
)
667
end
668
end
669
ctx_stopfontclass
(
)
670
end
671 672
function
selectfont
.
textfallback
(
index
,
entry
,
class
,
style
)
673
local
data
=
data
[
entry
]
674
ctx_startfontclass
(
{
class
}
)
675
for
alternative
,
_
in
next
,
alternatives
do
676
selectfont
.
fontsynonym
(
data
,
class
,
style
,
alternative
,
index
)
677
selectfont
.
fontfallback
(
data
,
class
,
style
,
alternative
,
index
)
678
end
679
ctx_stopfontclass
(
)
680
end
681 682
function
selectfont
.
fallback
(
data
)
683
local
fontclass
=
data
.
metadata
.
typeface
684
local
fontstyle
=
data
.
metadata
.
style
685
local
fallbacks
=
fallbacks
[
fontclass
]
and
fallbacks
[
fontclass
]
[
fontstyle
]
686
if
fallbacks
then
687
for
index
,
entry
in
next
,
fallbacks
do
688
-- I need different fallback routines for math and text because
689
-- font synonyms can’t be used with math fonts and I have to apply
690
-- feature settings with the \definefontfallback command.
691
if
fontstyle
=
=
"
mm
"
then
692
selectfont
.
mathfallback
(
index
,
entry
,
fontclass
,
fontstyle
)
693
else
694
selectfont
.
textfallback
(
index
,
entry
,
fontclass
,
fontstyle
)
695
end
696
end
697
end
698
end
699 700
function
selectfont
.
typescript
(
data
)
701
local
class
=
data
.
metadata
.
typeface
702
local
family
=
data
.
metadata
.
family
703
local
style
=
data
.
metadata
.
style
704
local
extras
=
data
.
options
.
extras
705
local
defaults
=
defaults
[
cleanname
(
family
)
]
706
if
extras
=
=
"
"
then
707
extras
=
defaults
and
defaults
.
options
and
defaults
.
options
.
extras
or
"
"
708
end
709
ctx_startfontclass
(
{
class
}
)
710
if
extras
~
=
"
"
then
711
extras
=
settings_to_array
(
extras
)
712
for
_
,
extra
in
next
,
extras
do
713
ctx_loadfontgoodies
(
{
extra
}
)
714
end
715
end
716
for
alternative
,
_
in
next
,
alternatives
do
717
if
style
=
=
"
mm
"
then
718
-- Set math fonts only for upright and bold alternatives
719
if
alternative
=
=
"
tf
"
or
alternative
=
=
"
bf
"
then
720
selectfont
.
fontsynonym
(
data
,
class
,
style
,
alternative
,
0
)
721
end
722
else
723
selectfont
.
fontsynonym
(
data
,
class
,
style
,
alternative
,
0
)
724
end
725
end
726
ctx_stopfontclass
(
)
727
end
728 729
function
selectfont
.
bodyfont
(
data
)
730
local
class
=
data
.
metadata
.
typeface
731
local
fontstyle
=
data
.
metadata
.
style
732
local
fontclass
=
lower
(
class
)
733
local
fontsizes
=
concat
(
sortedkeys
(
bodyfontsizes
)
,
"
,
"
)
734
local
fontsynonym
=
nil
735
local
fontlist
=
{
}
736
for
alternative
,
_
in
next
,
alternatives
do
737
fontsynonym
=
formatters
[
"
synonym-%s-%s-%s
"
]
(
fontclass
,
fontstyle
,
alternative
)
738
fontlist
[
#
fontlist
+
1
]
=
formatters
[
"
%s=%s sa 1
"
]
(
alternative
,
fontsynonym
)
739
-- if trace_typescript then
740
-- report_typescript("alternative '%s': synonym '%s'",alternative,fontsynonym)
741
-- end
742
end
743
fontlist
=
concat
(
fontlist
,
"
,
"
)
744
ctx_definebodyfont
(
{
class
}
,
{
fontsizes
}
,
{
fontstyle
}
,
{
fontlist
}
)
745
end
746 747
local
m_style
=
{
748
[
"
rm
"
]
=
"
serif
"
,
749
[
"
ss
"
]
=
"
sans
"
,
750
[
"
tt
"
]
=
"
mono
"
,
751
[
"
mm
"
]
=
"
math
"
,
752
[
"
hw
"
]
=
"
handwriting
"
,
753
[
"
cg
"
]
=
"
calligraphy
"
,
754
}
755 756
function
selectfont
.
typeface
(
data
)
757
local
fontclass
=
data
.
metadata
.
typeface
758
local
fontstyle
=
data
.
metadata
.
style
759
local
style
=
m_style
[
fontstyle
]
760
local
size
=
data
.
options
.
designsize
~
=
"
"
and
data
.
options
.
designsize
or
"
default
"
761
local
scale
=
data
.
options
.
rscale
~
=
"
"
and
data
.
options
.
rscale
or
1
762
-- if trace_typescript then
763
-- report_typescript("class: '%s', style: '%s', size: '%s', scale: '%s'",fontclass,fontstyle,size,scale)
764
-- end
765
ctx_definetypeface
(
{
fontclass
}
,
{
fontstyle
}
,
{
style
}
,
{
"
"
}
,
{
"
default
"
}
,
{
designsize
=
size
,
rscale
=
scale
}
)
766
end
767 768
function
selectfont
.
default
(
data
)
769
local
family
=
data
.
metadata
.
family
770
local
fontclass
=
data
.
metadata
.
typeface
771
local
fontstyle
=
data
.
metadata
.
style
772
local
style
=
m_style
[
fontstyle
]
773
report_selectfont
(
"
the requested font '%s' has no files for the 'tf' alternative, Latin Modern is used instead.
"
,
family
)
774
ctx_definetypeface
(
{
fontclass
}
,
{
fontstyle
}
,
{
style
}
,
{
"
modern
"
}
,
{
"
default
"
}
)
775
end
776 777
function
selectfont
.
definefontfamily
(
index
)
778
local
data
=
data
[
index
]
779
local
fontstyle
=
data
.
metadata
.
style
780
local
fontfiles
=
data
.
files
and
data
.
files
[
"
tf
"
]
781
if
fontfiles
then
782
selectfont
.
fallback
(
data
)
783
selectfont
.
typescript
(
data
)
784
if
fontstyle
~
=
"
mm
"
then
785
selectfont
.
bodyfont
(
data
)
786
end
787
selectfont
.
typeface
(
data
)
788
else
789
selectfont
.
default
(
data
)
790
end
791
end
792 793
function
selectfont
.
definefallbackfamily
(
index
)
794
local
data
=
data
[
index
]
795
local
family
=
data
.
metadata
.
family
796
local
fontclass
=
data
.
metadata
.
typeface
797
local
fontstyle
=
data
.
metadata
.
style
798
local
fontfiles
=
data
.
files
799
if
fontfiles
then
800
selectfont
.
registerfallback
(
index
)
801
else
802
report_selectfont
(
"
the requested fallback font '%s' for typeface '%s' style '%s' was ignored because no files where found.
"
,
family
,
fontclass
,
fontstyle
)
803
end
804
end
805 806
function
selectfont
.
definefontfamilypreset
(
name
,
data
)
807
local
p
=
presets
[
name
]
808
local
d
=
settings_to_hash
(
data
)
809
if
not
p
then
810
p
=
d
811
presets
[
name
]
=
p
812
end
813
end
814 815
implement
{
816
name
=
"
registerfontfamily
"
,
817
actions
=
{
selectfont
.
registerfontfamily
,
context
}
,
818
arguments
=
{
819
{
820
{
821
"
metadata
"
,
{
822
{
"
typeface
"
}
,
823
{
"
style
"
}
,
824
{
"
family
"
}
825
}
826
}
,
827
{
828
"
options
"
,
{
829
{
"
designsize
"
}
,
830
{
"
rscale
"
}
,
831
{
"
goodies
"
}
,
832
{
"
preset
"
}
,
833
{
"
extras
"
}
,
834
{
"
features
"
}
,
835
{
"
range
"
}
,
836
{
"
offset
"
}
,
837
{
"
check
"
}
,
838
{
"
force
"
}
839
}
840
}
,
841
{
842
"
userdata
"
843
}
844
}
845
}
846
}
847 848
implement
{
849
name
=
"
registerfontalternative
"
,
850
actions
=
selectfont
.
registerfontalternative
,
851
arguments
=
"
string
"
852
}
853 854
implement
{
855
name
=
"
definefontfamily
"
,
856
actions
=
selectfont
.
definefontfamily
,
857
arguments
=
"
integer
"
858
}
859 860
implement
{
861
name
=
"
definefallbackfamily
"
,
862
actions
=
selectfont
.
definefallbackfamily
,
863
arguments
=
"
integer
"
864
}
865 866
implement
{
867
name
=
"
definefontfamilypreset
"
,
868
actions
=
selectfont
.
definefontfamilypreset
,
869
arguments
=
"
2 strings
"
,
870
}
871