1
1
mirror of https://github.com/rsms/inter.git synced 2024-12-27 01:27:17 +03:00
inter/misc/tools/font_names.py
Rasmus Andersson 0ba7c2b42f New version of fontbuild which addresses several issues
Fixes for things that stopped working when we updated fontmake:
- restore glyph decomposition for VF
- restore glyph overlap removal for VF
- restore version metadata writing for VF

Improvements for VF
- fix "full name" name table entry to say "Inter" instead of "Inter Regular"

New and changed:
- "rename" command for renaming metadata like family and style, optionally
  saving a separate file. Used to produce new "Inter V" family.
- The "build" command no longer performs "style name compactation" for
  Google fonts. Instead, the new "rename" command is used.

Closes #198
Closes #202
2019-10-22 12:31:20 -07:00

149 lines
4.4 KiB
Python

#!/usr/bin/env python
from fontTools.ttLib import TTFont
import os, sys, re
# 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
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 removeWhitespaceFromStyles(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)
rec.string = s
if rid in (SUBFAMILY_NAME,) or rid in vfInstanceSubfamilyNameIds:
rec.string = removeWhitespace(rec.toUnicode())
# 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 loadFont(file):
return TTFont(file, recalcBBoxes=False, recalcTimestamp=False)
def renameFontFamily(infile, outfile, newFamilyName):
font = loadFont(infile)
setFamilyName(font, newFamilyName)
# print('write "%s"' % outfile)
font.save(outfile)
font.close()
def main():
infile = "./build/fonts/var/Inter.var.ttf"
outfile = "./build/tmp/var2.otf"
renameFontFamily(infile, outfile, "Inter V")
print("%s familyName: %r" % (infile, getFamilyName(loadFont(infile)) ))
print("%s familyName: %r" % (outfile, getFamilyName(loadFont(outfile)) ))
if __name__ == "__main__":
sys.exit(main())
# Similar to:
# ttx -i -e -o ./build/tmp/var.ttx ./build/fonts/var/Inter.var.ttf
# ttx -b --no-recalc-timestamp -o ./build/tmp/var.otf ./build/tmp/var.ttx