diff options
Diffstat (limited to 'src/silfont/scripts/psfsetglyphorder.py')
-rw-r--r-- | src/silfont/scripts/psfsetglyphorder.py | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/src/silfont/scripts/psfsetglyphorder.py b/src/silfont/scripts/psfsetglyphorder.py new file mode 100644 index 0000000..f05889c --- /dev/null +++ b/src/silfont/scripts/psfsetglyphorder.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 +__doc__ = '''Load glyph order data into public.glyphOrder in lib.plist based on based on a text file in one of two formats: + - simple text file with one glyph name per line + - csv file with headers, using headers "glyph_name" and "sort_final" where the latter contains + numeric values used to sort the glyph names by''' +__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'}, {}), + ('--header', {'help': 'Column header(s) for sort order', 'default': 'sort_final'}, {}), + ('--field', {'help': 'Field(s) in lib.plist to update', 'default': 'public.glyphOrder'}, {}), + ('-i', '--input', {'help': 'Input text file, one glyphname per line'}, {'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': '_gorder.log'})] + + +def doit(args): + font = args.ifont + incsv = args.input + logger = args.logger + removemissing = args.removemissing + + fields = args.field.split(",") + fieldcount = len(fields) + headers = args.header.split(",") + if fieldcount != len(headers): logger.log("Must specify same number of values in --field and --header", "S") + gname = args.gname + + # Identify file format from first line then create glyphdata[] with glyph name then one column per header + glyphdata = {} + fl = incsv.firstline + if fl is None: logger.log("Empty input file", "S") + numfields = len(fl) + incsv.numfields = numfields + fieldpos = [] + if numfields > 1: # More than 1 column, so must have headers + if gname in fl: + glyphnpos = fl.index(gname) + else: + logger.log("No" + gname + "field in csv headers", "S") + for header in headers: + if header in fl: + pos = fl.index(header) + fieldpos.append(pos) + else: + logger.log('No "' + header + '" heading in csv headers"', "S") + next(incsv.reader, None) # Skip first line with headers in + for line in incsv: + glyphn = line[glyphnpos] + if len(glyphn) == 0: + continue # No need to include cases where name is blank + glyphdata[glyphn]=[] + for pos in fieldpos: glyphdata[glyphn].append(float(line[pos])) + elif numfields == 1: # Simple text file. Create glyphdata in same format as for csv files + for i, line in enumerate(incsv): glyphdata[line[0]]=(i,) + else: + logger.log("Invalid csv file", "S") + + # Now process the data + if "lib" not in font.__dict__: font.addfile("lib") + glyphlist = list(font.deflayer.keys()) + + for i in range(0,fieldcount): + array = ET.Element("array") + for glyphn, vals in sorted(glyphdata.items(), key=lambda item: item[1][i]): + if glyphn in glyphlist: + sub = ET.SubElement(array, "string") + sub.text = glyphn + else: + font.logger.log("No glyph in font for " + glyphn, "I") + if not removemissing: + sub = ET.SubElement(array, "string") + sub.text = glyphn + font.lib.setelem(fields[i-1],array) + + for glyphn in sorted(glyphlist): # Remaining glyphs were not in the input file + if glyphn not in glyphdata: font.logger.log("No entry in input file for font glyph " + glyphn, "I") + + return font + + +def cmd(): execute("UFO", doit, argspec) +if __name__ == "__main__": cmd() |