1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
#!/usr/bin/env python3
__doc__ = 'Build features.fea file into a ttf font'
# TODO: add conditional compilation, compare to fea, compile to ttf
__url__ = 'https://github.com/silnrsi/pysilfont'
__copyright__ = 'Copyright (c) 2017 SIL International (https://www.sil.org)'
__license__ = 'Released under the MIT License (https://opensource.org/licenses/MIT)'
__author__ = 'Martin Hosken'
from fontTools.feaLib.builder import Builder
from fontTools import configLogger
from fontTools.ttLib import TTFont
from fontTools.ttLib.tables.otTables import lookupTypes
from fontTools.feaLib.lookupDebugInfo import LookupDebugInfo
from silfont.core import execute
class MyBuilder(Builder):
def __init__(self, font, featurefile, lateSortLookups=False, fronts=None):
super(MyBuilder, self).__init__(font, featurefile)
self.lateSortLookups = lateSortLookups
self.fronts = fronts if fronts is not None else []
def buildLookups_(self, tag):
assert tag in ('GPOS', 'GSUB'), tag
countFeatureLookups = 0
fronts = set([l for k, l in self.named_lookups_.items() if k in self.fronts])
for bldr in self.lookups_:
bldr.lookup_index = None
if bldr.table == tag and getattr(bldr, '_feature', "") != "":
countFeatureLookups += 1
lookups = []
latelookups = []
for bldr in self.lookups_:
if bldr.table != tag:
continue
if self.lateSortLookups and getattr(bldr, '_feature', "") == "":
if bldr in fronts:
latelookups.insert(0, bldr)
else:
latelookups.append(bldr)
else:
bldr.lookup_index = len(lookups)
lookups.append(bldr)
bldr.map_index = bldr.lookup_index
numl = len(lookups)
for i, l in enumerate(latelookups):
l.lookup_index = numl + i
l.map_index = l.lookup_index
for l in lookups + latelookups:
self.lookup_locations[tag][str(l.lookup_index)] = LookupDebugInfo(
location=str(l.location),
name=self.get_lookup_name_(l),
feature=None)
return [b.build() for b in lookups + latelookups]
def add_lookup_to_feature_(self, lookup, feature_name):
super(MyBuilder, self).add_lookup_to_feature_(lookup, feature_name)
lookup._feature = feature_name
#TODO: provide more argument info
argspec = [
('input_fea', {'help': 'Input fea file'}, {}),
('input_font', {'help': 'Input font file'}, {}),
('-o', '--output', {'help': 'Output font file'}, {}),
('-v', '--verbose', {'help': 'Repeat to increase verbosity', 'action': 'count', 'default': 0}, {}),
('-m', '--lookupmap', {'help': 'File into which place lookup map'}, {}),
('-l','--log',{'help': 'Optional log file'}, {'type': 'outfile', 'def': '_buildfea.log', 'optlog': True}),
('-e','--end',{'help': 'Push lookups not in features to the end', 'action': 'store_true'}, {}),
('-F','--front',{'help': 'Pull named lookups to the front of unnamed list', 'action': 'append'}, {}),
]
def doit(args) :
levels = ["WARNING", "INFO", "DEBUG"]
configLogger(level=levels[min(len(levels) - 1, args.verbose)])
font = TTFont(args.input_font)
builder = MyBuilder(font, args.input_fea, lateSortLookups=args.end, fronts=args.front)
builder.build()
if args.lookupmap:
with open(args.lookupmap, "w") as outf:
for n, l in sorted(builder.named_lookups_.items()):
if l is not None:
outf.write("{},{},{}\n".format(n, l.table, l.map_index))
font.save(args.output)
def cmd(): execute(None, doit, argspec)
if __name__ == '__main__': cmd()
|