Skip to content

Instantly share code, notes, and snippets.

@ryanoasis
Created February 23, 2016 16:23
Show Gist options
  • Save ryanoasis/af51f008838aaa46fb61 to your computer and use it in GitHub Desktop.
Save ryanoasis/af51f008838aaa46fb61 to your computer and use it in GitHub Desktop.
Nerd Fonts: SubFamily font name and name fixes plus additional improvements (WIP)
diff --git a/font-patcher b/font-patcher
index 57bb42b..4c9c6db 100755
--- a/font-patcher
+++ b/font-patcher
@@ -2,20 +2,31 @@
# coding=utf8
# version: 0.6.0
+version = "0.6.0"
+projectName = "Nerd Fonts"
+projectNameAbbreviation = "NF"
+projectNameSingular = projectName[:-1]
+
import sys
-import psMat
+
+try:
+ import psMat
+except ImportError:
+ sys.stderr.write(projectName + ": FontForge module is probably not installed. [See: http://designwithfontforge.com/en-US/Installing_Fontforge.html]\n")
+ sys.exit(1)
+
import re
import os
import argparse
import errno
try:
- #Load the module
- import fontforge
+ #Load the module
+ import fontforge
except ImportError:
- sys.stderr.write("FontForge module could not be loaded. Try installing fontforge python bindings\n")
- sys.exit(1)
+ sys.stderr.write(projectName + ": FontForge module could not be loaded. Try installing fontforge python bindings [e.g. on Linux Debian or Ubuntu: `sudo apt-get install fontforge python-fontforge`]\n")
+ sys.exit(1)
# argparse stuff
@@ -37,7 +48,7 @@ args = parser.parse_args()
#print type(fontforge.version())
#print int(fontforge.version())
-version = "0.6.0"
+
changelog = open("changelog.md", "r")
minimumVersion = 20141231
actualVersion = int(fontforge.version())
@@ -45,16 +56,16 @@ actualVersion = int(fontforge.version())
# versions tested: 20150612, 20150824
if actualVersion < minimumVersion:
- print "You seem to be using an unsupported (old) version of fontforge: " + str(actualVersion)
- print "Please use at least version: " + str(minimumVersion)
+ print projectName + ": You seem to be using an unsupported (old) version of fontforge: " + str(actualVersion)
+ print projectName + ": Please use at least version: " + str(minimumVersion)
sys.exit(1)
-verboseAdditionalFontNameSuffix = " Nerd Font"
+verboseAdditionalFontNameSuffix = " " + projectNameSingular
if args.windows:
# attempt to shorten here on the additional name BEFORE trimming later
- additionalFontNameSuffix = " NF"
+ additionalFontNameSuffix = " " + projectNameAbbreviation
else:
additionalFontNameSuffix = verboseAdditionalFontNameSuffix
@@ -72,8 +83,8 @@ if args.pomicons:
# if all source glyphs included simplify the name
if args.fontawesome and args.octicons and args.pomicons and args.powerlineextra:
- additionalFontNameSuffix = " Nerd Font Complete"
- verboseAdditionalFontNameSuffix = " Nerd Font Complete"
+ additionalFontNameSuffix = " " + projectNameSingular + " Complete"
+ verboseAdditionalFontNameSuffix = " " + projectNameSingular + " Complete"
# add mono signifier to end of name
if args.single:
@@ -83,14 +94,71 @@ if args.single:
sourceFont = fontforge.open(args.font)
-fontname, style = re.match("^([^-]*)(?:(-.*))?$", sourceFont.fontname).groups()
-familyname = sourceFont.familyname
+# '^([^-]*)-*([^-]*)$' was not working with multiple dashes
+
+# basically split the font name around the dash "-" to get the fontname and the style (e.g. Bold)
+# this does not seem very reliable so only use the style here as a fallback if the font does not
+# have an internal style defined (in sfnt_names)
+# using '([^-]*?)' to get the item before the first dash "-"
+# using '([^-]*(?!.*-))' to get the item after the last dash "-"
+fontname, fallbackStyle = re.match("^([^-]*).*?([^-]*(?!.*-))$", sourceFont.fontname).groups()
+# dont trust 'sourceFont.familyname'
+familyname = fontname
# fullname (filename) can always use long/verbose font name, even in windows
fullname = sourceFont.fullname + verboseAdditionalFontNameSuffix
fontname = fontname + additionalFontNameSuffix.replace(" ", "")
+print 'sourceFont.fontname'
+print sourceFont.fontname
+print fontname, fallbackStyle
+print familyname
+print fullname
+print fontname
+print sourceFont.cidsubfontnames
+# print sourceFont.subfamily
+print sourceFont.copyright
+print sourceFont.uniqueid
+print sourceFont.sfnt_names
+print sourceFont.sfnt_names[2][2]
+print sourceFont.sfnt_names[3]
+# okay try to do more reliably, search tuple:
+print 'search tuple'
+
+# let us try to get the 'style' from the font info in sfnt_names and fallback to the
+# parse fontname if it fails:
+try:
+ subFamilyTupleIndex = [x[1] for x in sourceFont.sfnt_names].index("SubFamily")
+ # String ID is at the second index in the Tuple lists
+ sfntNamesStringIDIndex = 2
+ # now we have the correct item:
+ subFamily = sourceFont.sfnt_names[sfntNamesStringIDIndex][subFamilyTupleIndex]
+except IndexError:
+ print "Could not find 'SubFamily' for given font, falling back to parsed fontname"
+ subFamily = fallbackStyle
+
+# some fonts have inaccurate 'SubFamily', if it is Regular let us trust the filename more:
+if subFamily == "Regular":
+ subFamily = fallbackStyle
+
+
+# print 'subfamily'
+# print subFamily
+# print 'search tuple 2'
+# print 'fallback style'
+# print fallbackStyle
+# print [i for i, v in enumerate(sourceFont.sfnt_names) if v[1] == 'Copyright']
+# print 'i v'
+# print i
+# print v
+
+# sys.exit(1)
+# test setting the proper value:
+# sourceFont.appendSFNTName('English (US)', 'SubFamily', subFamily)
+# sourceFont.appendSFNTName('English (US)', 'SubFamily', "Regular")
+
if args.windows:
maxLength = 31
+ familyname += " " + projectNameAbbreviation
fullname += " Windows Compatible"
# now make sure less than 32 characters name length
#if len(fullname) > maxLength:
@@ -99,6 +167,8 @@ if args.windows:
fontname = fontname[:maxLength]
if len(fullname) > maxLength:
familyname = familyname[:maxLength]
+else:
+ familyname += " " + projectNameSingular
# rename font
@@ -120,19 +190,20 @@ make_sure_path_exists(args.outputdir)
# comply with SIL Open Font License (OFL)
reservedFontNameReplacements = { 'source': 'sauce', 'Source': 'Sauce', 'hermit': 'hurmit', 'Hermit': 'Hurmit', 'fira': 'fura', 'Fira': 'Fura', 'hack': 'knack', 'Hack': 'Knack' }
-projectInfo = "Patched with 'Nerd Fonts Patcher' (https://github.com/ryanoasis/nerd-fonts)"
+projectInfo = "Patched with '" + projectName + " Patcher' (https://github.com/ryanoasis/nerd-fonts)"
sourceFont.familyname = replace_all(familyname, reservedFontNameReplacements)
sourceFont.fullname = replace_all(fullname, reservedFontNameReplacements)
sourceFont.fontname = replace_all(fontname, reservedFontNameReplacements)
sourceFont.appendSFNTName('English (US)', 'Preferred Family', sourceFont.familyname)
sourceFont.appendSFNTName('English (US)', 'Compatible Full', sourceFont.fullname)
+sourceFont.appendSFNTName('English (US)', 'SubFamily', subFamily)
sourceFont.comment = projectInfo
sourceFont.fontlog = projectInfo + "\n\n" + changelog.read()
# todo version not being set for all font types (e.g. ttf)
#print "Version was " + sourceFont.version
-sourceFont.version += ";Nerd Fonts " + version
+sourceFont.version += ";" + projectName + " " + version
#print "Version now is " + sourceFont.version
# glyph font
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment