summaryrefslogtreecommitdiff
path: root/misc/tools/font_names.py
diff options
context:
space:
mode:
authorRasmus Andersson <rasmus@notion.se>2019-10-22 22:27:06 +0300
committerRasmus Andersson <rasmus@notion.se>2019-10-22 22:31:20 +0300
commit0ba7c2b42f06dd2ded8cdeca8563dadf089f1d14 (patch)
treec06f63ab2eb51eef6da90fc86d84d6129cfe4bea /misc/tools/font_names.py
parentbc8b267b01d4652334e6f4a5452e77fbf79b329d (diff)
downloadinter-0ba7c2b42f06dd2ded8cdeca8563dadf089f1d14.tar.xz
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
Diffstat (limited to 'misc/tools/font_names.py')
-rw-r--r--misc/tools/font_names.py148
1 files changed, 148 insertions, 0 deletions
diff --git a/misc/tools/font_names.py b/misc/tools/font_names.py
new file mode 100644
index 000000000..c321ca673
--- /dev/null
+++ b/misc/tools/font_names.py
@@ -0,0 +1,148 @@
+#!/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