summaryrefslogtreecommitdiffstats
path: root/lib/silfont/scripts/psfsetpsnames.py
blob: 55528c7bd3ac2f429f4ffcc77c40456c97609e74 (plain)
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 python
__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__ = 'http://github.com/silnrsi/pysilfont'
__copyright__ = 'Copyright (c) 2015 SIL International (http://www.sil.org)'
__license__ = 'Released under the MIT License (http://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()