File: fontname.py

package info (click to toggle)
python-qtawesome 1.2.2%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 5,892 kB
  • sloc: python: 1,435; makefile: 177; sh: 14
file content (134 lines) | stat: -rwxr-xr-x 4,820 bytes parent folder | download | duplicates (2)
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#!/usr/bin/env python3

# ==========================================================================
# fontname.py
# Copyright 2019 Christopher Simpkins
# MIT License
#
# Dependencies:
#   1) Python 3.6+ interpreter
#   2) fonttools Python library (https://github.com/fonttools/fonttools)
#         - install with `pip3 install fonttools`
#
# Usage:
#   python3 fontname.py [FONT FAMILY NAME] [FONT PATH 1] <FONT PATH ...>
#
# Notes:
#   Use quotes around font family name arguments that include spaces
# ===========================================================================

import os
import sys

from fontTools import ttLib


def main(argv):
    # command argument tests
    print(" ")
    if len(argv) < 2:
        sys.stderr.write(
            f"[fontname.py] ERROR: you did not include enough arguments to the script.{os.linesep}"
        )
        sys.stderr.write(
            f"Usage: python3 fontname.py [FONT FAMILY NAME] [FONT PATH 1] <FONT PATH ...>{os.linesep}"
        )
        sys.exit(1)

    # begin parsing command line arguments
    try:
        font_name = str(argv[0])  # the first argument is the new typeface name
    except Exception as e:
        sys.stderr.write(
            f"[fontname.py] ERROR: Unable to convert argument to string. {e}{os.linesep}"
        )
        sys.exit(1)

    # all remaining arguments on command line are file paths to fonts
    font_path_list = argv[1:]

    # iterate through all paths provided on command line and rename to `font_name` defined by user
    for font_path in font_path_list:
        # test for existence of font file on requested file path
        if not file_exists(font_path):
            sys.stderr.write(
                f"[fontname.py] ERROR: the path '{font_path}' does not appear to be a valid file path.{os.linesep}"
            )
            sys.exit(1)

        tt = ttLib.TTFont(font_path)
        namerecord_list = tt["name"].names

        style = ""

        # determine font style for this file path from name record nameID 2
        for record in namerecord_list:
            if record.nameID == 2:
                style = str(record)
                break

        # test that a style name was found in the OpenType tables of the font
        if len(style) == 0:
            sys.stderr.write(
                f"[fontname.py] Unable to detect the font style from the OpenType name table in '{font_path}'. {os.linesep}"
            )
            sys.stderr.write("Unable to complete execution of the script.")
            sys.exit(1)
        else:
            # used for the Postscript name in the name table (no spaces allowed)
            postscript_font_name = font_name.replace(" ", "")
            # font family name
            nameID1_string = font_name
            nameID16_string = font_name
            # full font name
            nameID4_string = f"{font_name} {style}"
            # Postscript name
            # - no spaces allowed in family name or the PostScript suffix. should be dash delimited
            nameID6_string = f"{postscript_font_name}-{style.replace(' ', '')}"
            # nameID6_string = postscript_font_name + "-" + style.replace(" ", "")

            # modify the opentype table data in memory with updated values
            for record in namerecord_list:
                if record.nameID == 1:
                    record.string = nameID1_string
                elif record.nameID == 4:
                    record.string = nameID4_string
                elif record.nameID == 6:
                    record.string = nameID6_string
                elif record.nameID == 16:
                    record.string = nameID16_string

            # CFF table naming for CFF fonts (only)
            if "CFF " in tt:
                try:
                    cff = tt["CFF "]
                    cff.cff[0].FamilyName = nameID1_string
                    cff.cff[0].FullName = nameID4_string
                    cff.cff.fontNames = [nameID6_string]
                except Exception as e:
                    sys.stderr.write(
                        f"[fontname.py] ERROR: unable to write new names to CFF table: {e}"
                    )

        # write changes to the font file
        try:
            tt.save(font_path)
            print(f"[OK] Updated '{font_path}' with the name '{nameID4_string}'")
        except Exception as e:
            sys.stderr.write(
                f"[fontname.py] ERROR: unable to write new name to OpenType name table for '{font_path}'. {os.linesep}"
            )
            sys.stderr.write(f"{e}{os.linesep}")
            sys.exit(1)


# Utilities


def file_exists(filepath):
    """Tests for existence of a file on the string filepath"""
    return os.path.exists(filepath) and os.path.isfile(filepath)


if __name__ == "__main__":
    main(sys.argv[1:])