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
|
#!/usr/bin/env python3
__doc__ = '''Add public.postscriptNames to lib.plist based on a csv file in one of two formats:
- simple glyphname, postscriptname with no headers
- with headers, where the headers for glyph name and postscript name "glyph_name" and "ps_name"'''
__url__ = 'https://github.com/silnrsi/pysilfont'
__copyright__ = 'Copyright (c) 2015 SIL International (https://www.sil.org)'
__license__ = 'Released under the MIT License (https://opensource.org/licenses/MIT)'
__author__ = 'David Raymond'
from silfont.core import execute
from xml.etree import ElementTree as ET
argspec = [
('ifont', {'help': 'Input font file'}, {'type': 'infont'}),
('ofont', {'help': 'Output font file', 'nargs': '?'}, {'type': 'outfont'}),
('--gname', {'help': 'Column header for glyph name', 'default': 'glyph_name'}, {}),
('-i', '--input', {'help': 'Input csv file'}, {'type': 'incsv', 'def': 'glyph_data.csv'}),
('-x', '--removemissing', {'help': 'Remove from list if glyph not in font', 'action': 'store_true', 'default': False}, {}),
('-l', '--log', {'help': 'Log file'}, {'type': 'outfile', 'def': 'setpsnames.log'})]
def doit(args):
font = args.ifont
logger = args.logger
incsv = args.input
gname = args.gname
removemissing = args.removemissing
glyphlist = list(font.deflayer.keys()) # List to check every glyph has a psname supplied
# Identify file format from first line
fl = incsv.firstline
if fl is None: logger.log("Empty input file", "S")
numfields = len(fl)
incsv.numfields = numfields
if numfields == 2:
glyphnpos = 0
psnamepos = 1 # Default for plain csv
elif numfields > 2: # More than 2 columns, so must have standard headers
if gname in fl:
glyphnpos = fl.index(gname)
else:
logger.log("No " + gname + " field in csv headers", "S")
if "ps_name" in fl:
psnamepos = fl.index("ps_name")
else:
logger.log("No ps_name field in csv headers", "S")
next(incsv.reader, None) # Skip first line with headers in
else:
logger.log("Invalid csv file", "S")
# Now process the data
dict = ET.Element("dict")
for line in incsv:
glyphn = line[glyphnpos]
psname = line[psnamepos]
if len(psname) == 0 or glyphn == psname:
continue # No need to include cases where production name is blank or same as working name
# Check if in font
infont = False
if glyphn in glyphlist:
glyphlist.remove(glyphn)
infont = True
else:
if not removemissing: logger.log("No glyph in font for " + glyphn + " on line " + str(incsv.line_num), "I")
if not removemissing or infont:
# Add to dict
sub = ET.SubElement(dict, "key")
sub.text = glyphn
sub = ET.SubElement(dict, "string")
sub.text = psname
# Add to lib.plist
if len(dict) > 0:
if "lib" not in font.__dict__: font.addfile("lib")
font.lib.setelem("public.postscriptNames", dict)
else:
if "lib" in font.__dict__ and "public.postscriptNames" in font.lib:
font.lib.remove("public.postscriptNames")
for glyphn in sorted(glyphlist): logger.log("No PS name in input file for font glyph " + glyphn, "I")
return font
def cmd(): execute("UFO", doit, argspec)
if __name__ == "__main__": cmd()
|