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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
#!/usr/bin/env python
__doc__ = 'Generate a ttf file without OpenType tables from a UFO'
__url__ = 'http://github.com/silnrsi/pysilfont'
__copyright__ = 'Copyright (c) 2017 SIL International (http://www.sil.org)'
__license__ = 'Released under the MIT License (http://opensource.org/licenses/MIT)'
__author__ = 'Alan Ward'
# Compared to fontmake it does not decompose glyphs or remove overlaps
# and curve conversion seems to happen in a different way.
from silfont.core import execute
import defcon, ufo2ft.outlineCompiler, ufo2ft.preProcessor, ufo2ft.filters
argspec = [
('iufo', {'help': 'Input UFO folder'}, {}),
('ottf', {'help': 'Output ttf file name'}, {}),
('--removeOverlaps', {'help': 'Merge overlapping contours', 'action': 'store_true'}, {}),
('--decomposeComponents', {'help': 'Decompose componenets', 'action': 'store_true'}, {}),
('-l', '--log', {'help': 'Optional log file'}, {'type': 'outfile', 'def': '_ufo2ttf.log', 'optlog': True})]
PUBLIC_PREFIX = 'public.'
def doit(args):
ufo = defcon.Font(args.iufo)
# if style is Regular and there are no openTypeNameRecords defining the full name (ID=4), then
# add one so that "Regular" is omitted from the fullname
if ufo.info.styleName == 'Regular':
if ufo.info.openTypeNameRecords is None:
ufo.info.openTypeNameRecords = []
fullNameRecords = [ nr for nr in ufo.info.openTypeNameRecords if nr['nameID'] == 4]
if not len(fullNameRecords):
ufo.info.openTypeNameRecords.append( { 'nameID': 4, 'platformID': 3, 'encodingID': 1, 'languageID': 1033, 'string': ufo.info.familyName } )
# args.logger.log('Converting UFO to ttf and compiling fea')
# font = ufo2ft.compileTTF(ufo,
# glyphOrder = ufo.lib.get(PUBLIC_PREFIX + 'glyphOrder'),
# useProductionNames = False)
args.logger.log('Converting UFO to ttf without OT', 'P')
# default arg value for TTFPreProcessor class: removeOverlaps = False, convertCubics = True
preProcessor = ufo2ft.preProcessor.TTFPreProcessor(ufo, removeOverlaps = args.removeOverlaps, convertCubics=True,
flattenComponents = True,
skipExportGlyphs = ufo.lib.get("public.skipExportGlyphs", []))
# Need to handle cases if filters that are used are set in com.github.googlei18n.ufo2ft.filters with lib.plist
dc = dtc = ftpos = None
for (i,filter) in enumerate(preProcessor.preFilters):
if isinstance(filter, ufo2ft.filters.decomposeComponents.DecomposeComponentsFilter):
dc = True
if isinstance(filter, ufo2ft.filters.decomposeTransformedComponents.DecomposeTransformedComponentsFilter):
dtc = True
if isinstance(filter, ufo2ft.filters.flattenComponents.FlattenComponentsFilter):
ftpos = i
# Add decomposeComponents if --decomposeComponents is used
if args.decomposeComponents and not dc: preProcessor.preFilters.append(
ufo2ft.filters.decomposeComponents.DecomposeComponentsFilter())
# Add decomposeTransformedComponents if not already set via lib.plist
if not dtc: preProcessor.preFilters.append(ufo2ft.filters.decomposeTransformedComponents.DecomposeTransformedComponentsFilter())
# Remove flattenComponents if set via lib.plist since we set it via flattenComponents = True when setting up the preprocessor
if ftpos: preProcessor.preFilters.pop(ftpos)
glyphSet = preProcessor.process()
outlineCompiler = ufo2ft.outlineCompiler.OutlineTTFCompiler(ufo,
glyphSet=glyphSet,
glyphOrder=ufo.lib.get(PUBLIC_PREFIX + 'glyphOrder'))
font = outlineCompiler.compile()
# handle uvs glyphs until ufo2ft does it for us.
uvsdict = getuvss(ufo)
if len(uvsdict):
from fontTools.ttLib.tables._c_m_a_p import cmap_format_14
cmap_uvs = cmap_format_14(14)
cmap_uvs.platformID = 0
cmap_uvs.platEncID = 5
cmap_uvs.cmap = {}
cmap_uvs.uvsDict = uvsdict
font['cmap'].tables.append(cmap_uvs)
args.logger.log('Saving ttf file', 'P')
font.save(args.ottf)
args.logger.log('Done', 'P')
def getuvss(ufo):
uvsdict = {}
uvs = ufo.lib.get('org.sil.variationSequences', None)
if uvs is not None:
for usv, dat in uvs.items():
usvc = int(usv, 16)
pairs = []
uvsdict[usvc] = pairs
for k, v in dat.items():
pairs.append((int(k, 16), v))
return uvsdict
for g in ufo:
uvs = getattr(g, 'lib', {}).get("org.sil.uvs", None)
if uvs is None:
continue
codes = [int(x, 16) for x in uvs.split()]
if codes[1] not in uvsdict:
uvsdict[codes[1]] = []
uvsdict[codes[1]].append((codes[0], (g.name if codes[0] not in g.unicodes else None)))
return uvsdict
def cmd(): execute(None, doit, argspec)
if __name__ == '__main__': cmd()
|