diff options
author | Rasmus <rasmus@notion.se> | 2022-05-26 21:20:06 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-26 21:20:06 +0300 |
commit | 07960766590650e516a75ce6ceba91b68a5fa551 (patch) | |
tree | f0c82cd40cb68950bf8229d14cbc850fec41e5ba /misc/tools/rename.py | |
parent | 633839ad550073f9d12e6cea7964a30523974b68 (diff) | |
download | inter-07960766590650e516a75ce6ceba91b68a5fa551.tar.xz |
UPM 2048 and opsz axis (#462)
- UPM is adjusted to 2048
- Additional opsz VF axis (multi master) added which will eventually replace the separate Display family
- New tooling that uses fontmake instead of Inter's own fontbuild toolchain. (The old toolchain is still supported, i.e. `make -f Makefile_v1.make ...`)
Diffstat (limited to 'misc/tools/rename.py')
-rw-r--r-- | misc/tools/rename.py | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/misc/tools/rename.py b/misc/tools/rename.py new file mode 100644 index 000000000..6793e391c --- /dev/null +++ b/misc/tools/rename.py @@ -0,0 +1,171 @@ +import sys, os, os.path, argparse, re +from fontTools.ttLib import TTFont + +# Adoptation of fonttools/blob/master/Snippets/rename-fonts.py + +WINDOWS_ENGLISH_IDS = 3, 1, 0x409 +MAC_ROMAN_IDS = 1, 0, 0 + +LEGACY_FAMILY = 1 +TRUETYPE_UNIQUE_ID = 3 +FULL_NAME = 4 +POSTSCRIPT_NAME = 6 +PREFERRED_FAMILY = 16 +SUBFAMILY_NAME = 17 +WWS_FAMILY = 21 + + +FAMILY_RELATED_IDS = set([ + LEGACY_FAMILY, + TRUETYPE_UNIQUE_ID, + FULL_NAME, + POSTSCRIPT_NAME, + PREFERRED_FAMILY, + WWS_FAMILY, +]) + +whitespace_re = re.compile(r'\s+') + + +def removeWhitespace(s): + return whitespace_re.sub("", s) + + +def setFullName(font, fullName): + nameTable = font["name"] + nameTable.setName(fullName, FULL_NAME, 1, 0, 0) # mac + nameTable.setName(fullName, FULL_NAME, 3, 1, 0x409) # windows + nameTable.setName(fullName, POSTSCRIPT_NAME, 1, 0, 0) # mac + nameTable.setName(fullName, POSTSCRIPT_NAME, 3, 1, 0x409) # windows + + +def getFamilyName(font): + nameTable = font["name"] + r = None + for plat_id, enc_id, lang_id in (WINDOWS_ENGLISH_IDS, MAC_ROMAN_IDS): + for name_id in (PREFERRED_FAMILY, LEGACY_FAMILY): + r = nameTable.getName(nameID=name_id, platformID=plat_id, platEncID=enc_id, langID=lang_id) + if r is not None: + break + if r is not None: + break + if not r: + raise ValueError("family name not found") + return r.toUnicode() + + +def renameStylesGoogleFonts(font): + familyName = getFamilyName(font) + + # collect subfamily (style) name IDs for variable font's named instances + vfInstanceSubfamilyNameIds = set() + if "fvar" in font: + for namedInstance in font["fvar"].instances: + vfInstanceSubfamilyNameIds.add(namedInstance.subfamilyNameID) + + nameTable = font["name"] + for rec in nameTable.names: + rid = rec.nameID + if rid in (FULL_NAME, LEGACY_FAMILY): + # style part of family name + s = rec.toUnicode() + start = s.find(familyName) + if start != -1: + s = familyName + " " + removeWhitespace(s[start + len(familyName):]) + else: + s = removeWhitespace(s) + if s != "Italic" and s.endswith("Italic"): + # fixup e.g. "ExtraBoldItalic" -> "ExtraBold Italic" + s = s[:len(s) - len("Italic")] + " Italic" + rec.string = s.strip() + if rid in (SUBFAMILY_NAME,) or rid in vfInstanceSubfamilyNameIds: + s = removeWhitespace(rec.toUnicode()) + if s != "Italic" and s.endswith("Italic"): + # fixup e.g. "ExtraBoldItalic" -> "ExtraBold Italic" + s = s[:len(s) - len("Italic")] + " Italic" + rec.string = s.strip() + # else: ignore standard names unrelated to style + + +def setFamilyName(font, nextFamilyName): + prevFamilyName = getFamilyName(font) + if prevFamilyName == nextFamilyName: + return + # raise Exception("identical family name") + + def renameRecord(nameRecord, prevFamilyName, nextFamilyName): + # replaces prevFamilyName with nextFamilyName in nameRecord + s = nameRecord.toUnicode() + start = s.find(prevFamilyName) + if start != -1: + end = start + len(prevFamilyName) + nextFamilyName = s[:start] + nextFamilyName + s[end:] + nameRecord.string = nextFamilyName + return s, nextFamilyName + + # postcript name can't contain spaces + psPrevFamilyName = prevFamilyName.replace(" ", "") + psNextFamilyName = nextFamilyName.replace(" ", "") + for rec in font["name"].names: + name_id = rec.nameID + if name_id not in FAMILY_RELATED_IDS: + # leave uninteresting records unmodified + continue + if name_id == POSTSCRIPT_NAME: + old, new = renameRecord(rec, psPrevFamilyName, psNextFamilyName) + elif name_id == TRUETYPE_UNIQUE_ID: + # The Truetype Unique ID rec may contain either the PostScript Name or the Full Name + if psPrevFamilyName in rec.toUnicode(): + # Note: This is flawed -- a font called "Foo" renamed to "Bar Lol"; + # if this record is not a PS record, it will incorrectly be rename "BarLol". + # However, in practice this is not abig deal since it's just an ID. + old, new = renameRecord(rec, psPrevFamilyName, psNextFamilyName) + else: + old, new = renameRecord(rec, prevFamilyName, nextFamilyName) + else: + old, new = renameRecord(rec, prevFamilyName, nextFamilyName) + # print(" %r: '%s' -> '%s'" % (rec, old, new)) + + +def main(): + argparser = argparse.ArgumentParser( + description='Rename family and/or styles of font' + ) + a = lambda *args, **kwargs: argparser.add_argument(*args, **kwargs) + a('-o', '--output', metavar='<file>', + help='Output font file. Defaults to input file (overwrite)') + a('--family', metavar='<name>', + help='Rename family to <name>') + a('--google-style', action='store_true', + help='Rename style names to Google Fonts standards') + a('input', metavar='<file>', + help='Input font file') + args = argparser.parse_args() + + infile = args.input + outfile = args.output or infile + + font = TTFont(infile, recalcBBoxes=False, recalcTimestamp=False) + editCount = 0 + try: + if args.family: + editCount += 1 + setFamilyName(font, args.family) + + if args.google_style: + editCount += 1 + renameStylesGoogleFonts(font) + + if editCount == 0: + print("no rename options provided", file=sys.stderr) + argparser.print_help(sys.stderr) + sys.exit(1) + return + + font.save(outfile) + finally: + font.close() + + +if __name__ == '__main__': + main() |