font-tfm.lua /size: 23 Kb    last modification: 2021-10-28 13:50
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
font-tfm
'
]
=
{
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
if
not
context
then
return
end
-- use luatex-fonts-tfm.lua instead
10 11
local
next
,
type
=
next
,
type
12
local
match
,
format
=
string
.
match
,
string
.
format
13
local
concat
,
sortedhash
=
table
.
concat
,
table
.
sortedhash
14
local
idiv
=
number
.
idiv
15 16
local
trace_defining
=
false
trackers
.
register
(
"
fonts.defining
"
,
function
(
v
)
trace_defining
=
v
end
)
17
local
trace_features
=
false
trackers
.
register
(
"
tfm.features
"
,
function
(
v
)
trace_features
=
v
end
)
18 19
local
report_defining
=
logs
.
reporter
(
"
fonts
"
,
"
defining
"
)
20
local
report_tfm
=
logs
.
reporter
(
"
fonts
"
,
"
tfm loading
"
)
21 22
local
findbinfile
=
resolvers
.
findbinfile
23
local
setmetatableindex
=
table
.
setmetatableindex
24 25
local
fonts
=
fonts
26
local
handlers
=
fonts
.
handlers
27
local
helpers
=
fonts
.
helpers
28
local
readers
=
fonts
.
readers
29
local
constructors
=
fonts
.
constructors
30
local
encodings
=
fonts
.
encodings
31 32
local
tfm
=
constructors
.
handlers
.
tfm
33
tfm
.
version
=
1
.
000
34
tfm
.
maxnestingdepth
=
5
35
tfm
.
maxnestingsize
=
65536
*
1024
36 37
local
otf
=
fonts
.
handlers
.
otf
38
local
otfenhancers
=
otf
.
enhancers
39 40
local
tfmfeatures
=
constructors
.
features
.
tfm
41
local
registertfmfeature
=
tfmfeatures
.
register
42 43
local
tfmenhancers
=
constructors
.
enhancers
.
tfm
44
local
registertfmenhancer
=
tfmenhancers
.
register
45 46
local
charcommand
=
helpers
.
commands
.
char
47 48
constructors
.
resolvevirtualtoo
=
false
-- wil be set in font-ctx.lua
49 50
fonts
.
formats
.
tfm
=
"
type1
"
-- we need to have at least a value here
51
fonts
.
formats
.
ofm
=
"
type1
"
-- we need to have at least a value here
52 53
--[[ldx-- 54<p>The next function encapsulates the standard <l n='tfm'/> loader as 55supplied by <l n='luatex'/>.</p> 56--ldx]]
--
57 58
-- this might change: not scaling and then apply features and do scaling in the
59
-- usual way with dummy descriptions but on the other hand .. we no longer use
60
-- tfm so why bother
61 62
-- ofm directive blocks local path search unless set; btw, in context we
63
-- don't support ofm files anyway as this format is obsolete
64 65
-- we need to deal with nested virtual fonts, but because we load in the
66
-- frontend we also need to make sure we don't nest too deep (esp when sizes
67
-- get large)
68
--
69
-- (VTITLE Example of a recursion)
70
-- (MAPFONT D 0 (FONTNAME recurse)(FONTAT D 2))
71
-- (CHARACTER C A (CHARWD D 1)(CHARHT D 1)(MAP (SETRULE D 1 D 1)))
72
-- (CHARACTER C B (CHARWD D 2)(CHARHT D 2)(MAP (SETCHAR C A)))
73
-- (CHARACTER C C (CHARWD D 4)(CHARHT D 4)(MAP (SETCHAR C B)))
74
--
75
-- we added the same checks as below to the luatex engine
76 77
function
tfm
.
setfeatures
(
tfmdata
,
features
)
78
local
okay
=
constructors
.
initializefeatures
(
"
tfm
"
,
tfmdata
,
features
,
trace_features
,
report_tfm
)
79
if
okay
then
80
return
constructors
.
collectprocessors
(
"
tfm
"
,
tfmdata
,
features
,
trace_features
,
report_tfm
)
81
else
82
return
{
}
-- will become false
83
end
84
end
85 86
local
depth
=
{
}
-- table.setmetatableindex("number")
87 88
-- Normally we just load the tfm data and go on. However there was some demand for
89
-- loading good old tfm /pfb files where afm files were lacking and even enc files
90
-- of dubious quality so we now support loading such (often messy) setups too.
91
--
92
-- Because such fonts also use (ugly) tweaks achieve some purpose (like swapping
93
-- accents) we need to delay the unicoding actions till after the features have been
94
-- applied.
95
--
96
-- It must be noted that in ConTeXt we don't expect this to be used at all. Here is
97
-- example:
98
--
99
-- tfm metrics + pfb vector for index + pfb file for shapes
100
--
101
-- \font\foo=file:csr10.tfm:reencode=auto;mode=node;liga=yes;kern=yes
102
--
103
-- tfm metrics + pfb vector for index + enc file for tfm mapping + pfb file for shapes
104
--
105
-- \font\foo=file:csr10.tfm:reencode=csr.enc;mode=node;liga=yes;kern=yes
106
--
107
-- tfm metrics + enc file for mapping to tfm + bitmaps shapes
108
--
109
-- \font\foo=file:csr10.tfm:reencode=csr.enc;bitmap=yes;mode=node;liga=yes;kern=yes
110
--
111
-- One can add features:
112
--
113
-- fonts.handlers.otf.addfeature {
114
-- name = "czechdqcheat",
115
-- type = "substitution",
116
-- data = {
117
-- quotedblright = "csquotedblright",
118
-- },
119
-- }
120
--
121
-- So "czechdqcheat=yes" is then a valid feature. And yes, it's a cheat.
122 123
local
loadtfmvf
=
tfm
.
readers
.
loadtfmvf
124 125
local
function
read_from_tfm
(
specification
)
126
local
filename
=
specification
.
filename
127
local
size
=
specification
.
size
128
depth
[
filename
]
=
(
depth
[
filename
]
or
0
)
+
1
129
if
trace_defining
then
130
report_defining
(
"
loading tfm file %a at size %s
"
,
filename
,
size
)
131
end
132
local
tfmdata
=
loadtfmvf
(
filename
,
size
)
133
if
tfmdata
then
134 135
local
features
=
specification
.
features
and
specification
.
features
.
normal
or
{
}
136
local
features
=
constructors
.
checkedfeatures
(
"
tfm
"
,
features
)
137
specification
.
features
.
normal
=
features
138 139
-- If reencode returns a new table, we assume that we're doing something
140
-- special. An 'auto' reencode picks up its vector from the pfb file.
141 142
local
getmapentry
=
fonts
.
mappings
.
getentry
143 144
if
getmapentry
and
not
features
.
reencode
then
145
-- This can happen multiple times but not that often so we don't
146
-- optimize this.
147
local
encoding
,
pfbfile
,
encfile
=
getmapentry
(
filename
)
148
if
encoding
and
pfbfile
then
149
features
.
reencode
=
encfile
150
features
.
pfbfile
=
pfbfile
151
end
152
end
153
local
newtfmdata
=
(
depth
[
filename
]
=
=
1
)
and
tfm
.
reencode
(
tfmdata
,
specification
)
154
if
newtfmdata
then
155
tfmdata
=
newtfmdata
156
end
157 158
local
resources
=
tfmdata
.
resources
or
{
}
159
local
properties
=
tfmdata
.
properties
or
{
}
160
local
parameters
=
tfmdata
.
parameters
or
{
}
161
local
shared
=
tfmdata
.
shared
or
{
}
162
--
163
shared
.
features
=
features
164
shared
.
resources
=
resources
165
--
166
properties
.
id
=
specification
.
id
167
properties
.
name
=
tfmdata
.
name
-- todo: fallback
168
properties
.
fontname
=
tfmdata
.
fontname
-- todo: fallback
169
properties
.
psname
=
tfmdata
.
psname
-- todo: fallback
170
properties
.
fullname
=
tfmdata
.
fullname
-- todo: fallback
171
properties
.
filename
=
specification
.
filename
-- todo: fallback
172
properties
.
format
=
tfmdata
.
format
or
fonts
.
formats
.
tfm
-- better than nothing
173
properties
.
usedbitmap
=
tfmdata
.
usedbitmap
174
--
175
if
getmapentry
and
newtfmdata
then
176
properties
.
filename
=
features
.
pfbfile
177
end
178
--
179
tfmdata
.
properties
=
properties
180
tfmdata
.
resources
=
resources
181
tfmdata
.
parameters
=
parameters
182
tfmdata
.
shared
=
shared
183
--
184
shared
.
rawdata
=
{
resources
=
resources
}
185
shared
.
features
=
features
186
--
187
-- The next branch is only entered when we have a proper encoded file i.e.
188
-- unicodes and such. It really nakes no sense to do feature juggling when
189
-- we have no names and unicodes.
190
--
191
if
newtfmdata
then
192
--
193
-- Some opentype processing assumes these to be present:
194
--
195
if
not
resources
.
marks
then
196
resources
.
marks
=
{
}
197
end
198
if
not
resources
.
sequences
then
199
resources
.
sequences
=
{
}
200
end
201
if
not
resources
.
features
then
202
resources
.
features
=
{
203
gsub
=
{
}
,
204
gpos
=
{
}
,
205
}
206
end
207
if
not
tfmdata
.
changed
then
208
tfmdata
.
changed
=
{
}
209
end
210
if
not
tfmdata
.
descriptions
then
211
tfmdata
.
descriptions
=
tfmdata
.
characters
212
end
213
--
214
-- It might be handy to have this:
215
--
216
otf
.
readers
.
addunicodetable
(
tfmdata
)
217
--
218
-- We make a pseudo opentype font, e.g. kerns and ligatures etc:
219
--
220
tfmenhancers
.
apply
(
tfmdata
,
filename
)
221
--
222
-- Now user stuff can kick in.
223
--
224
constructors
.
applymanipulators
(
"
tfm
"
,
tfmdata
,
features
,
trace_features
,
report_tfm
)
225
--
226
-- As that can also mess with names and such, we are now ready for finalizing
227
-- the unicode information. This is a different order that for instance type one
228
-- (afm) files. First we try to deduce unicodes from already present information.
229
--
230
otf
.
readers
.
unifymissing
(
tfmdata
)
231
--
232
-- Next we fill in the gaps, based on names from teh agl. Probably not much will
233
-- happen here.
234
--
235
fonts
.
mappings
.
addtounicode
(
tfmdata
,
filename
)
236
--
237
-- The tounicode data is passed to the backend that constructs the vectors for us.
238
--
239
if
not
CONTEXTLMTXMODE
or
CONTEXTLMTXMODE
=
=
0
then
240
tfmdata
.
tounicode
=
1
241
end
242
local
tounicode
=
fonts
.
mappings
.
tounicode
243
for
unicode
,
v
in
next
,
tfmdata
.
characters
do
244
local
u
=
v
.
unicode
245
if
u
then
246
v
.
tounicode
=
tounicode
(
u
)
247
end
248
end
249
--
250
-- However, when we use a bitmap font those vectors can't be constructed because
251
-- that information is not carried with those fonts (there is no name info, nor
252
-- proper index info, nor unicodes at that end). So, we provide it ourselves.
253
--
254
if
tfmdata
.
usedbitmap
then
255
tfm
.
addtounicode
(
tfmdata
)
256
end
257
end
258
--
259
shared
.
processes
=
next
(
features
)
and
tfm
.
setfeatures
(
tfmdata
,
features
)
or
nil
260
--
261
if
size
<
0
then
262
size
=
idiv
(
65536
*
-
size
,
100
)
263
end
264 265
parameters
.
factor
=
1
-- already scaled
266
parameters
.
units
=
1000
-- just in case
267
parameters
.
size
=
size
268
parameters
.
slant
=
parameters
.
slant
or
parameters
[
1
]
or
0
269
parameters
.
space
=
parameters
.
space
or
parameters
[
2
]
or
0
270
parameters
.
space_stretch
=
parameters
.
space_stretch
or
parameters
[
3
]
or
0
271
parameters
.
space_shrink
=
parameters
.
space_shrink
or
parameters
[
4
]
or
0
272
parameters
.
x_height
=
parameters
.
x_height
or
parameters
[
5
]
or
0
273
parameters
.
quad
=
parameters
.
quad
or
parameters
[
6
]
or
0
274
parameters
.
extra_space
=
parameters
.
extra_space
or
parameters
[
7
]
or
0
275
--
276
constructors
.
enhanceparameters
(
parameters
)
-- official copies for us
277
--
278
properties
.
private
=
properties
.
private
or
tfmdata
.
private
or
privateoffset
279
--
280
if
newtfmdata
then
281
--
282
-- We do nothing as we assume flat tfm files. It would become real messy
283
-- otherwise and I don't have something for testing on my system anyway.
284
--
285
else
286
-- already loaded
287
local
fonts
=
tfmdata
.
fonts
288
if
fonts
then
289
for
i
=
1
,
#
fonts
do
290
local
font
=
fonts
[
i
]
291
local
id
=
font
.
id
292
if
not
id
then
293
local
name
=
font
.
name
294
local
size
=
font
.
size
295
if
name
and
size
then
296
local
data
,
id
=
constructors
.
readanddefine
(
name
,
size
)
297
if
id
then
298
font
.
id
=
id
299
font
.
name
=
nil
300
font
.
size
=
nil
301
end
302
end
303
end
304
end
305
end
306
end
307
--
308
properties
.
haskerns
=
true
309
properties
.
hasligatures
=
true
310
properties
.
hasitalics
=
true
311
resources
.
unicodes
=
{
}
312
resources
.
lookuptags
=
{
}
313
--
314
depth
[
filename
]
=
depth
[
filename
]
-
1
315
--
316
return
tfmdata
317
else
318
depth
[
filename
]
=
depth
[
filename
]
-
1
319
end
320
end
321 322
local
function
check_tfm
(
specification
,
fullname
)
-- we could split up like afm/otf
323
local
foundname
=
findbinfile
(
fullname
,
'
tfm
'
)
or
"
"
324
if
foundname
=
=
"
"
then
325
foundname
=
findbinfile
(
fullname
,
'
ofm
'
)
or
"
"
-- not needed in context
326
end
327
if
foundname
=
=
"
"
then
328
foundname
=
fonts
.
names
.
getfilename
(
fullname
,
"
tfm
"
)
or
"
"
329
end
330
if
foundname
~
=
"
"
then
331
specification
.
filename
=
foundname
332
specification
.
format
=
"
ofm
"
333
return
read_from_tfm
(
specification
)
334
elseif
trace_defining
then
335
report_defining
(
"
loading tfm with name %a fails
"
,
specification
.
name
)
336
end
337
end
338 339
readers
.
check_tfm
=
check_tfm
340 341
function
readers
.
tfm
(
specification
)
342
local
fullname
=
specification
.
filename
or
"
"
343
if
fullname
=
=
"
"
then
344
local
forced
=
specification
.
forced
or
"
"
345
if
forced
~
=
"
"
then
346
fullname
=
specification
.
name
.
.
"
.
"
.
.
forced
347
else
348
fullname
=
specification
.
name
349
end
350
end
351
return
check_tfm
(
specification
,
fullname
)
352
end
353 354
readers
.
ofm
=
readers
.
tfm
355 356
-- The reencoding acts upon the 'reencode' feature which can have values 'auto' or
357
-- an enc file. You can also specify a 'pfbfile' feature (but it defaults to the
358
-- tfm filename) and a 'bitmap' feature. When no enc file is givven (auto) we will
359
-- get the vectors from the pfb file.
360 361
do
362 363
local
outfiles
=
{
}
364 365
local
tfmcache
=
table
.
setmetatableindex
(
function
(
t
,
tfmdata
)
366
local
id
=
font
.
define
(
tfmdata
)
367
t
[
tfmdata
]
=
id
368
return
id
369
end
)
370 371
local
encdone
=
table
.
setmetatableindex
(
"
table
"
)
372 373
function
tfm
.
reencode
(
tfmdata
,
specification
)
374 375
local
features
=
specification
.
features
376 377
if
not
features
then
378
return
379
end
380 381
local
features
=
features
.
normal
382 383
if
not
features
then
384
return
385
end
386 387
local
tfmfile
=
file
.
basename
(
tfmdata
.
name
)
388
local
encfile
=
features
.
reencode
-- or features.enc
389
local
pfbfile
=
features
.
pfbfile
-- or features.pfb
390
local
bitmap
=
features
.
bitmap
-- or features.pk
391 392
if
not
encfile
then
393
return
394
end
395 396
local
pfbfile
=
pfbfile
or
outfiles
[
tfmfile
]
397 398
if
pfbfile
=
=
nil
then
399
if
bitmap
then
400
pfbfile
=
false
401
elseif
type
(
pfbfile
)
~
=
"
string
"
then
402
pfbfile
=
tfmfile
403
end
404
if
type
(
pfbfile
)
=
=
"
string
"
then
405
pfbfile
=
file
.
addsuffix
(
pfbfile
,
"
pfb
"
)
406
-- pdf.mapline(tfmfile .. "<" .. pfbfile)
407
report_tfm
(
"
using type1 shapes from %a for %a
"
,
pfbfile
,
tfmfile
)
408
else
409
report_tfm
(
"
using bitmap shapes for %a
"
,
tfmfile
)
410
pfbfile
=
false
-- use bitmap
411
end
412
outfiles
[
tfmfile
]
=
pfbfile
413
end
414 415
local
encoding
=
false
416
local
vector
=
false
417
if
type
(
pfbfile
)
=
=
"
string
"
then
418
local
pfb
=
constructors
.
handlers
.
pfb
419
if
pfb
and
pfb
.
loadvector
then
420
local
v
,
e
=
pfb
.
loadvector
(
pfbfile
)
421
if
v
then
422
vector
=
v
423
end
424
if
e
then
425
encoding
=
e
426
end
427
end
428
end
429
if
type
(
encfile
)
=
=
"
string
"
and
encfile
~
=
"
auto
"
then
430
encoding
=
fonts
.
encodings
.
load
(
file
.
addsuffix
(
encfile
,
"
enc
"
)
)
431
if
encoding
then
432
encoding
=
encoding
.
vector
433
end
434
end
435
if
not
encoding
then
436
report_tfm
(
"
bad encoding for %a, quitting
"
,
tfmfile
)
437
return
438
end
439 440
local
unicoding
=
fonts
.
encodings
.
agl
and
fonts
.
encodings
.
agl
.
unicodes
441
local
virtualid
=
tfmcache
[
tfmdata
]
442
local
tfmdata
=
table
.
copy
(
tfmdata
)
-- good enough for small fonts
443
local
characters
=
{
}
444
local
originals
=
tfmdata
.
characters
445
local
indices
=
{
}
446
local
parentfont
=
{
"
font
"
,
1
}
-- can be zero (self referencing)
447
local
private
=
tfmdata
.
privateoffset
or
constructors
.
privateoffset
448
local
reported
=
encdone
[
tfmfile
]
[
encfile
]
-- bah, encdone for tfm or pfb ?
449
-- create characters table
450 451
-- vector : pfbindex -> name
452
-- encoding : tfmindex -> name
453 454
-- we store the order also because some tex encodings (see math-vfu) needs
455
-- that for remapping with non standard glyphs names cq. lack of unicode
456
-- slot information
457 458
for
k
,
v
in
next
,
originals
do
459
v
.
order
=
k
460
end
461 462
local
backmap
=
vector
and
table
.
swapped
(
vector
)
463
local
done
=
{
}
-- prevent duplicate
464
for
tfmindex
,
name
in
sortedhash
(
encoding
)
do
-- predictable order
465
local
original
=
originals
[
tfmindex
]
466
if
original
then
467
local
unicode
=
unicoding
[
name
]
468
if
unicode
then
469
original
.
unicode
=
unicode
470
else
471
unicode
=
private
472
private
=
private
+
1
473
if
trace_defining
and
not
reported
then
474
report_tfm
(
"
glyph %a in font %a with encoding %a gets unicode %U
"
,
name
,
tfmfile
,
encfile
,
unicode
)
475
end
476
end
477
characters
[
unicode
]
=
original
478
indices
[
tfmindex
]
=
unicode
479
original
.
name
=
name
-- so one can lookup weird names
480
if
backmap
then
481
original
.
index
=
backmap
[
name
]
-- the pfb index
482
else
-- probably bitmap
483
original
.
commands
=
{
parentfont
,
charcommand
[
tfmindex
]
}
-- or "slot"
484
original
.
oindex
=
tfmindex
485
end
486
done
[
name
]
=
true
487
elseif
not
done
[
name
]
then
488
report_tfm
(
"
bad index %a in font %a with name %a
"
,
tfmindex
,
tfmfile
,
name
)
489
end
490
end
491 492
encdone
[
tfmfile
]
[
encfile
]
=
true
493 494
-- redo kerns and ligatures
495 496
for
k
,
v
in
next
,
characters
do
497
local
kerns
=
v
.
kerns
498
if
kerns
then
499
local
t
=
{
}
500
for
k
,
v
in
next
,
kerns
do
501
local
i
=
indices
[
k
]
502
if
i
then
503
t
[
i
]
=
v
504
end
505
end
506
v
.
kerns
=
next
(
t
)
and
t
or
nil
507
end
508
local
ligatures
=
v
.
ligatures
509
if
ligatures
then
510
local
t
=
{
}
511
for
k
,
v
in
next
,
ligatures
do
512
local
i
=
indices
[
k
]
513
if
i
then
514
t
[
i
]
=
v
515
v
.
char
=
indices
[
v
.
char
]
516
end
517
end
518
v
.
ligatures
=
next
(
t
)
and
t
or
nil
519
end
520
end
521 522
-- wrap up
523 524
tfmdata
.
fonts
=
{
{
id
=
virtualid
}
}
525
tfmdata
.
characters
=
characters
526
tfmdata
.
fullname
=
tfmdata
.
fullname
or
tfmdata
.
name
527
tfmdata
.
psname
=
file
.
nameonly
(
pfbfile
or
tfmdata
.
name
)
528
tfmdata
.
filename
=
pfbfile
529
-- tfmdata.format = bitmap and "type3" or "type1"
530
tfmdata
.
format
=
"
type1
"
531
if
not
CONTEXTLMTXMODE
or
CONTEXTLMTXMODE
=
=
0
then
532
tfmdata
.
encodingbytes
=
2
533
tfmdata
.
tounicode
=
1
534
tfmdata
.
embedding
=
"
subset
"
535
end
536
tfmdata
.
usedbitmap
=
bitmap
and
virtualid
537
tfmdata
.
private
=
private
538 539
return
tfmdata
540
end
541 542
end
543 544
-- Now we implement the regular features handlers. We need to convert the
545
-- tfm specific structures to opentype structures. In basemode they are
546
-- converted back so that is a bit of a waste but it's fast enough.
547 548
do
549 550
local
everywhere
=
{
[
"
*
"
]
=
{
[
"
*
"
]
=
true
}
}
-- or: { ["*"] = { "*" } }
551
local
noflags
=
{
false
,
false
,
false
,
false
}
552 553
local
function
enhance_normalize_features
(
data
)
554
local
ligatures
=
setmetatableindex
(
"
table
"
)
555
local
kerns
=
setmetatableindex
(
"
table
"
)
556
local
characters
=
data
.
characters
557
for
u
,
c
in
next
,
characters
do
558
local
l
=
c
.
ligatures
559
local
k
=
c
.
kerns
560
if
l
then
561
ligatures
[
u
]
=
l
562
for
u
,
v
in
next
,
l
do
563
l
[
u
]
=
{
ligature
=
v
.
char
}
564
end
565
c
.
ligatures
=
nil
566
end
567
if
k
then
568
kerns
[
u
]
=
k
569
for
u
,
v
in
next
,
k
do
570
k
[
u
]
=
v
-- { v, 0 }
571
end
572
c
.
kerns
=
nil
573
end
574
end
575 576
for
u
,
l
in
next
,
ligatures
do
577
for
k
,
v
in
next
,
l
do
578
local
vl
=
v
.
ligature
579
local
dl
=
ligatures
[
vl
]
580
if
dl
then
581
for
kk
,
vv
in
next
,
dl
do
582
v
[
kk
]
=
vv
-- table.copy(vv)
583
end
584
end
585
end
586
end
587 588
local
features
=
{
589
gpos
=
{
}
,
590
gsub
=
{
}
,
591
}
592
local
sequences
=
{
593
-- only filled ones
594
}
595
if
next
(
ligatures
)
then
596
features
.
gsub
.
liga
=
everywhere
597
data
.
properties
.
hasligatures
=
true
598
sequences
[
#
sequences
+
1
]
=
{
599
features
=
{
600
liga
=
everywhere
,
601
}
,
602
flags
=
noflags
,
603
name
=
"
s_s_0
"
,
604
nofsteps
=
1
,
605
order
=
{
"
liga
"
}
,
606
type
=
"
gsub_ligature
"
,
607
steps
=
{
608
{
609
coverage
=
ligatures
,
610
}
,
611
}
,
612
}
613
end
614
if
next
(
kerns
)
then
615
features
.
gpos
.
kern
=
everywhere
616
data
.
properties
.
haskerns
=
true
617
sequences
[
#
sequences
+
1
]
=
{
618
features
=
{
619
kern
=
everywhere
,
620
}
,
621
flags
=
noflags
,
622
name
=
"
p_s_0
"
,
623
nofsteps
=
1
,
624
order
=
{
"
kern
"
}
,
625
type
=
"
gpos_pair
"
,
626
steps
=
{
627
{
628
format
=
"
kern
"
,
629
coverage
=
kerns
,
630
}
,
631
}
,
632
}
633
end
634
data
.
resources
.
features
=
features
635
data
.
resources
.
sequences
=
sequences
636
data
.
shared
.
resources
=
data
.
shared
.
resources
or
resources
637
end
638 639
registertfmenhancer
(
"
normalize features
"
,
enhance_normalize_features
)
640
registertfmenhancer
(
"
check extra features
"
,
otfenhancers
.
enhance
)
641 642
end
643 644
-- As with type one (afm) loading, we just use the opentype ones:
645 646
registertfmfeature
{
647
name
=
"
mode
"
,
648
description
=
"
mode
"
,
649
initializers
=
{
650
base
=
otf
.
modeinitializer
,
651
node
=
otf
.
modeinitializer
,
652
}
653
}
654 655
registertfmfeature
{
656
name
=
"
features
"
,
657
description
=
"
features
"
,
658
default
=
true
,
659
initializers
=
{
660
base
=
otf
.
basemodeinitializer
,
661
node
=
otf
.
nodemodeinitializer
,
662
}
,
663
processors
=
{
664
node
=
otf
.
featuresprocessor
,
665
}
666
}
667