Snippets: add rename-fonts.py to append a suffix to all family names
This commit is contained in:
parent
01173c4599
commit
80bfc3ccd5
170
Snippets/rename-fonts.py
Executable file
170
Snippets/rename-fonts.py
Executable file
@ -0,0 +1,170 @@
|
||||
#!/usr/bin/env python
|
||||
"""Script to add a suffix to all family names in the input font's `name` table,
|
||||
and to optionally rename the output files with the given suffix.
|
||||
|
||||
The current family name substring is searched in the nameIDs 1, 3, 4, 6, 16,
|
||||
and 21, and if found the suffix is inserted after it; or else the suffix is
|
||||
appended at the end.
|
||||
"""
|
||||
from __future__ import print_function, absolute_import, unicode_literals
|
||||
import os
|
||||
import argparse
|
||||
import logging
|
||||
from fontTools.ttLib import TTFont
|
||||
from fontTools.misc.cliTools import makeOutputFileName
|
||||
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
WINDOWS_ENGLISH_IDS = 3, 1, 0x409
|
||||
MAC_ROMAN_IDS = 1, 0, 0
|
||||
|
||||
FAMILY_RELATED_IDS = dict(
|
||||
LEGACY_FAMILY=1,
|
||||
TRUETYPE_UNIQUE_ID=3,
|
||||
FULL_NAME=4,
|
||||
POSTSCRIPT_NAME=6,
|
||||
PREFERRED_FAMILY=16,
|
||||
WWS_FAMILY=21,
|
||||
)
|
||||
|
||||
|
||||
def get_current_family_name(table):
|
||||
family_name_rec = None
|
||||
for plat_id, enc_id, lang_id in (WINDOWS_ENGLISH_IDS, MAC_ROMAN_IDS):
|
||||
for name_id in (
|
||||
FAMILY_RELATED_IDS["PREFERRED_FAMILY"],
|
||||
FAMILY_RELATED_IDS["LEGACY_FAMILY"],
|
||||
):
|
||||
family_name_rec = table.getName(
|
||||
nameID=name_id,
|
||||
platformID=plat_id,
|
||||
platEncID=enc_id,
|
||||
langID=lang_id,
|
||||
)
|
||||
if family_name_rec is not None:
|
||||
break
|
||||
if family_name_rec is not None:
|
||||
break
|
||||
if not family_name_rec:
|
||||
raise ValueError("family name not found; can't add suffix")
|
||||
return family_name_rec.toUnicode()
|
||||
|
||||
|
||||
def insert_suffix(string, family_name, suffix):
|
||||
# check whether family_name is a substring
|
||||
start = string.find(family_name)
|
||||
if start != -1:
|
||||
# insert suffix after the family_name substring
|
||||
end = start + len(family_name)
|
||||
new_string = string[:end] + suffix + string[end:]
|
||||
else:
|
||||
# it's not, we just append the suffix at the end
|
||||
new_string = string + suffix
|
||||
return new_string
|
||||
|
||||
|
||||
def rename_record(name_record, family_name, suffix):
|
||||
string = name_record.toUnicode()
|
||||
new_string = insert_suffix(string, family_name, suffix)
|
||||
name_record.string = new_string
|
||||
return string, new_string
|
||||
|
||||
|
||||
def rename_file(filename, family_name, suffix):
|
||||
filename, ext = os.path.splitext(filename)
|
||||
ps_name = family_name.replace(" ", "")
|
||||
if ps_name in filename:
|
||||
ps_suffix = suffix.replace(" ", "")
|
||||
return insert_suffix(filename, ps_name, ps_suffix) + ext
|
||||
else:
|
||||
return insert_suffix(filename, family_name, suffix) + ext
|
||||
|
||||
|
||||
def add_family_suffix(font, suffix):
|
||||
table = font["name"]
|
||||
|
||||
family_name = get_current_family_name(table)
|
||||
logger.info(" Current family name: '%s'", family_name)
|
||||
|
||||
# postcript name can't contain spaces
|
||||
ps_family_name = family_name.replace(" ", "")
|
||||
ps_suffix = suffix.replace(" ", "")
|
||||
for rec in table.names:
|
||||
name_id = rec.nameID
|
||||
if name_id not in FAMILY_RELATED_IDS.values():
|
||||
continue
|
||||
if name_id == FAMILY_RELATED_IDS["POSTSCRIPT_NAME"]:
|
||||
old, new = rename_record(rec, ps_family_name, ps_suffix)
|
||||
elif name_id == FAMILY_RELATED_IDS["TRUETYPE_UNIQUE_ID"]:
|
||||
# The Truetype Unique ID rec may contain either the PostScript
|
||||
# Name or the Full Name string, so we try both
|
||||
if ps_family_name in rec.toUnicode():
|
||||
old, new = rename_record(rec, ps_family_name, ps_suffix)
|
||||
else:
|
||||
old, new = rename_record(rec, family_name, suffix)
|
||||
else:
|
||||
old, new = rename_record(rec, family_name, suffix)
|
||||
logger.info(" %r: '%s' -> '%s'", rec, old, new)
|
||||
|
||||
return family_name
|
||||
|
||||
|
||||
def main(args=None):
|
||||
parser = argparse.ArgumentParser(
|
||||
description=__doc__,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
)
|
||||
parser.add_argument("-s", "--suffix", required=True)
|
||||
parser.add_argument("input_fonts", metavar="FONTFILE", nargs="+")
|
||||
output_group = parser.add_mutually_exclusive_group()
|
||||
output_group.add_argument("-i", "--inplace", action="store_true")
|
||||
output_group.add_argument("-d", "--output-dir")
|
||||
output_group.add_argument("-o", "--output-file")
|
||||
parser.add_argument("-R", "--rename-files", action="store_true")
|
||||
parser.add_argument("-v", "--verbose", action="count", default=0)
|
||||
options = parser.parse_args(args)
|
||||
|
||||
if not options.verbose:
|
||||
level = "WARNING"
|
||||
elif options.verbose == 1:
|
||||
level = "INFO"
|
||||
else:
|
||||
level = "DEBUG"
|
||||
logging.basicConfig(level=level, format="%(message)s")
|
||||
|
||||
if options.output_file and len(options.input_fonts) > 1:
|
||||
parser.error(
|
||||
"argument -o/--output-file can't be used with multiple inputs"
|
||||
)
|
||||
if options.rename_files and (options.inplace or options.output_file):
|
||||
parser.error("argument -R not allowed with arguments -i or -o")
|
||||
|
||||
for input_name in options.input_fonts:
|
||||
logger.info("Renaming font: '%s'", input_name)
|
||||
|
||||
font = TTFont(input_name)
|
||||
family_name = add_family_suffix(font, options.suffix)
|
||||
|
||||
if options.inplace:
|
||||
output_name = input_name
|
||||
elif options.output_file:
|
||||
output_name = options.output_file
|
||||
else:
|
||||
if options.rename_files:
|
||||
input_name = rename_file(
|
||||
input_name, family_name, options.suffix
|
||||
)
|
||||
output_name = makeOutputFileName(input_name, options.output_dir)
|
||||
|
||||
font.save(output_name)
|
||||
logger.info("Saved font: '%s'", output_name)
|
||||
|
||||
font.close()
|
||||
del font
|
||||
|
||||
logger.info("Done!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
x
Reference in New Issue
Block a user