font-otd.lua /size: 11 Kb    last modification: 2020-07-01 14:35
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
font-otd
'
]
=
{
2
version
=
1
.
001
,
3
comment
=
"
companion to font-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
local
type
=
type
10
local
match
=
string
.
match
11
local
sequenced
=
table
.
sequenced
12 13
local
trace_dynamics
=
false
trackers
.
register
(
"
otf.dynamics
"
,
function
(
v
)
trace_dynamics
=
v
end
)
14
local
trace_applied
=
false
trackers
.
register
(
"
otf.applied
"
,
function
(
v
)
trace_applied
=
v
end
)
15 16
local
report_otf
=
logs
.
reporter
(
"
fonts
"
,
"
otf loading
"
)
17
local
report_process
=
logs
.
reporter
(
"
fonts
"
,
"
otf process
"
)
18 19
local
allocate
=
utilities
.
storage
.
allocate
20 21
local
fonts
=
fonts
22
local
otf
=
fonts
.
handlers
.
otf
23
local
hashes
=
fonts
.
hashes
24
local
definers
=
fonts
.
definers
25
local
constructors
=
fonts
.
constructors
26
local
specifiers
=
fonts
.
specifiers
27 28
local
fontidentifiers
=
hashes
.
identifiers
29
local
fontresources
=
hashes
.
resources
30
local
fontproperties
=
hashes
.
properties
31
local
fontdynamics
=
hashes
.
dynamics
32 33
local
contextsetups
=
specifiers
.
contextsetups
34
local
contextnumbers
=
specifiers
.
contextnumbers
35
local
contextmerged
=
specifiers
.
contextmerged
36 37
local
setmetatableindex
=
table
.
setmetatableindex
38 39
local
a_to_script
=
{
}
40
local
a_to_language
=
{
}
41 42
-- we can have a scripts hash in fonts.hashes
43 44
function
otf
.
setdynamics
(
font
,
attribute
)
45
-- local features = contextsetups[contextnumbers[attribute]] -- can be moved to caller
46
local
features
=
contextsetups
[
attribute
]
47
if
features
then
48
local
dynamics
=
fontdynamics
[
font
]
49
dynamic
=
contextmerged
[
attribute
]
or
0
50
local
script
,
language
51
if
dynamic
=
=
2
then
-- merge
52
language
=
features
.
language
or
fontproperties
[
font
]
.
language
or
"
dflt
"
53
script
=
features
.
script
or
fontproperties
[
font
]
.
script
or
"
dflt
"
54
else
-- if dynamic == 1 then -- replace
55
language
=
features
.
language
or
"
dflt
"
56
script
=
features
.
script
or
"
dflt
"
57
end
58
if
script
=
=
"
auto
"
then
59
-- checkedscript and resources are defined later so we cannot shortcut them -- todo: make installer
60
script
=
definers
.
checkedscript
(
fontidentifiers
[
font
]
,
fontresources
[
font
]
,
features
)
61
end
62
local
ds
=
dynamics
[
script
]
-- can be metatable magic (less testing)
63
-- or dynamics.dflt
64
if
not
ds
then
65
ds
=
{
}
66
dynamics
[
script
]
=
ds
67
end
68
local
dsl
=
ds
[
language
]
69
-- or ds.dflt
70
if
not
dsl
then
71
dsl
=
{
}
72
ds
[
language
]
=
dsl
73
end
74
local
dsla
=
dsl
[
attribute
]
75
if
not
dsla
then
76
local
tfmdata
=
fontidentifiers
[
font
]
77
a_to_script
[
attribute
]
=
script
78
a_to_language
[
attribute
]
=
language
79
-- we need to save some values .. quite messy
80
local
properties
=
tfmdata
.
properties
81
local
shared
=
tfmdata
.
shared
82
local
s_script
=
properties
.
script
83
local
s_language
=
properties
.
language
84
local
s_mode
=
properties
.
mode
85
local
s_features
=
shared
.
features
86
properties
.
mode
=
"
node
"
87
properties
.
language
=
language
88
properties
.
script
=
script
89
properties
.
dynamics
=
true
-- handy for tracing
90
shared
.
features
=
{
}
91
-- end of save
92
local
set
=
constructors
.
checkedfeatures
(
"
otf
"
,
features
)
93
set
.
mode
=
"
node
"
-- really needed
94
dsla
=
otf
.
setfeatures
(
tfmdata
,
set
)
95
if
trace_dynamics
then
96
report_otf
(
"
setting dynamics %s: attribute %a, script %a, language %a, set %a
"
,
contextnumbers
[
attribute
]
,
attribute
,
script
,
language
,
set
)
97
end
98
-- we need to restore some values
99
properties
.
script
=
s_script
100
properties
.
language
=
s_language
101
properties
.
mode
=
s_mode
102
shared
.
features
=
s_features
103
-- end of restore
104
dynamics
[
script
]
[
language
]
[
attribute
]
=
dsla
-- cache
105
elseif
trace_dynamics
then
106
-- report_otf("using dynamics %s: attribute %a, script %a, language %a",contextnumbers[attribute],attribute,script,language)
107
end
108
return
dsla
109
end
110
end
111 112
function
otf
.
scriptandlanguage
(
tfmdata
,
attr
)
113
local
properties
=
tfmdata
.
properties
114
if
attr
and
attr
>
0
then
115
return
a_to_script
[
attr
]
or
properties
.
script
or
"
dflt
"
,
a_to_language
[
attr
]
or
properties
.
language
or
"
dflt
"
116
else
117
return
properties
.
script
or
"
dflt
"
,
properties
.
language
or
"
dflt
"
118
end
119
end
120 121
-- we reimplement the dataset resolver
122 123
local
autofeatures
=
fonts
.
analyzers
.
features
124
local
featuretypes
=
otf
.
tables
.
featuretypes
125
local
defaultscript
=
otf
.
features
.
checkeddefaultscript
126
local
defaultlanguage
=
otf
.
features
.
checkeddefaultlanguage
127 128
local
resolved
=
{
}
-- we only resolve a font,script,language,attribute pair once
129
local
wildcard
=
"
*
"
130 131
-- what about analyze in local and not in font
132 133
-- needs checking: some added features can pass twice
134 135
local
P
,
C
,
Cc
,
lpegmatch
=
lpeg
.
P
,
lpeg
.
C
,
lpeg
.
Cc
,
lpeg
.
match
136 137
local
pattern
=
P
(
"
always
"
)
*
(
P
(
-1
)
*
Cc
(
true
)
+
P
(
"
:
"
)
*
C
(
(
1
-
P
(
-1
)
)
^
1
)
)
138 139
local
function
initialize
(
sequence
,
script
,
language
,
s_enabled
,
a_enabled
,
font
,
attr
,
dynamic
,
ra
,
autoscript
,
autolanguage
)
140
local
features
=
sequence
.
features
141
if
features
then
142
local
order
=
sequence
.
order
143
if
order
then
144
local
featuretype
=
featuretypes
[
sequence
.
type
or
"
unknown
"
]
145
local
lookupdone
=
false
146
for
i
=
1
,
#
order
do
--
147
local
kind
=
order
[
i
]
--
148
local
e_e
149
local
a_e
=
a_enabled
and
a_enabled
[
kind
]
-- the value (location)
150
if
a_e
~
=
nil
then
151
e_e
=
a_e
152
else
153
e_e
=
s_enabled
and
s_enabled
[
kind
]
-- the value (font)
154
end
155
if
e_e
then
156
local
usedattribute
,
usedscript
,
usedlanguage
,
usedlookup
157
local
valid
=
type
(
e_e
)
=
=
"
string
"
and
lpegmatch
(
pattern
,
e_e
)
158
if
valid
then
159
-- we have hit always
160
usedattribute
=
autofeatures
[
kind
]
or
false
161
usedlanguage
=
"
*
"
162
usedscript
=
"
*
"
163
usedlookup
=
{
valid
,
usedattribute
,
sequence
,
kind
}
164
else
165
-- we already checked for e_e
166
local
scripts
=
features
[
kind
]
--
167
local
languages
=
scripts
[
script
]
or
scripts
[
wildcard
]
168
if
not
languages
and
autoscript
then
169
langages
=
defaultscript
(
featuretype
,
autoscript
,
scripts
)
170
end
171
if
languages
then
172
-- we need detailed control over default because we want to trace
173
-- only first attribute match check, so we assume simple fina's
174
-- local valid = false
175
if
languages
[
language
]
then
176
valid
=
e_e
177
elseif
languages
[
wildcard
]
then
178
valid
=
e_e
179
elseif
autolanguage
and
defaultlanguage
(
featuretype
,
autolanguage
,
languages
)
then
180
valid
=
e_e
181
end
182
end
183
if
valid
then
184
usedattribute
=
autofeatures
[
kind
]
or
false
185
usedlanguage
=
script
186
usedscript
=
language
187
usedlookup
=
{
valid
,
usedattribute
,
sequence
,
kind
}
188
end
189
end
190
if
not
usedlookup
then
191
-- go on
192
elseif
lookupdone
then
193
if
trace_applied
then
194
report_process
(
195
"
font %s, dynamic %a (%a), feature %a, script %a, language %a, lookup %a, value %a, nofsteps %a, lookup already set by %a
"
,
196
font
,
attr
or
0
,
dynamic
,
kind
,
usedscript
,
usedlanguage
,
sequence
.
name
,
valid
,
sequence
.
nofsteps
,
ra
[
#
ra
]
[
4
]
)
197
end
198
else
199
ra
[
#
ra
+
1
]
=
usedlookup
200
if
trace_applied
then
201
report_process
(
202
"
font %s, dynamic %a (%a), feature %a, script %a, language %a, lookup %a, value %a, nofsteps %a
"
,
203
font
,
attr
or
0
,
dynamic
,
kind
,
usedscript
,
usedlanguage
,
sequence
.
name
,
valid
,
sequence
.
nofsteps
)
204
else
205
return
-- no need to look further
206
end
207
lookupdone
=
true
208
end
209
end
210
end
211
end
212
end
213
end
214 215
-- there is some fuzzy language/script state stuff in properties (temporary)
216 217
function
otf
.
dataset
(
tfmdata
,
font
,
attr
)
-- attr only when explicit (as in special parbuilder)
218 219
local
script
,
language
,
s_enabled
,
a_enabled
,
dynamic
220 221
if
attr
and
attr
~
=
0
then
222
dynamic
=
contextmerged
[
attr
]
or
0
223
-- local features = contextsetups[contextnumbers[attr]] -- could be a direct list
224
local
features
=
contextsetups
[
attr
]
225
a_enabled
=
features
-- location based
226
if
dynamic
=
=
1
then
-- or dynamic == -1 then
227
-- replace
228
language
=
features
.
language
or
"
dflt
"
229
script
=
features
.
script
or
"
dflt
"
230
elseif
dynamic
=
=
2
then
-- or dynamic == -2 then
231
-- merge
232
local
properties
=
tfmdata
.
properties
233
s_enabled
=
tfmdata
.
shared
.
features
-- font based
234
language
=
features
.
language
or
properties
.
language
or
"
dflt
"
235
script
=
features
.
script
or
properties
.
script
or
"
dflt
"
236
else
237
-- error
238
local
properties
=
tfmdata
.
properties
239
language
=
properties
.
language
or
"
dflt
"
240
script
=
properties
.
script
or
"
dflt
"
241
end
242
else
243
local
properties
=
tfmdata
.
properties
244
language
=
properties
.
language
or
"
dflt
"
245
script
=
properties
.
script
or
"
dflt
"
246
s_enabled
=
tfmdata
.
shared
.
features
-- can be made local to the resolver
247
dynamic
=
0
248
end
249 250
local
res
=
resolved
[
font
]
251
if
not
res
then
252
res
=
{
}
253
resolved
[
font
]
=
res
254
end
255
local
rs
=
res
[
script
]
256
if
not
rs
then
257
rs
=
{
}
258
res
[
script
]
=
rs
259
end
260
local
rl
=
rs
[
language
]
261
if
not
rl
then
262
rl
=
{
}
263
rs
[
language
]
=
rl
264
end
265
local
ra
=
rl
[
attr
]
266
if
ra
=
=
nil
then
-- attr can be false
267
ra
=
{
268
-- indexed but we can also add specific data by key in:
269
}
270
rl
[
attr
]
=
ra
271
local
sequences
=
tfmdata
.
shared
.
reorderedsequences
or
tfmdata
.
resources
.
sequences
272
if
sequences
then
273
local
autoscript
=
(
s_enabled
and
s_enabled
.
autoscript
)
or
(
a_enabled
and
a_enabled
.
autoscript
)
274
local
autolanguage
=
(
s_enabled
and
s_enabled
.
autolanguage
)
or
(
a_enabled
and
a_enabled
.
autolanguage
)
275
for
s
=
1
,
#
sequences
do
276
-- just return nil or ra step
277
initialize
(
sequences
[
s
]
,
script
,
language
,
s_enabled
,
a_enabled
,
font
,
attr
,
dynamic
,
ra
,
autoscript
,
autolanguage
)
278
end
279
end
280
end
281
return
ra
282 283
end
284