Last active
April 8, 2017 14:20
-
-
Save m4rc1e/8b9a6e5678c6628eae7e682d4de63220 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Generate variable fonts with fontmake from .glyphs sources. | |
Script traverses a directory tree and will generate var fonts if it | |
encounters a .glyphs file with at least 2 masters and more than 3 | |
instances, if directory matches the repository GF-Checklist spec: | |
https://github.com/googlefonts/gf-docs/blob/master/ProjectChecklist.md | |
""" | |
import glyphsLib | |
import os | |
from os.path import basename | |
import sys | |
import shutil | |
import re | |
SOURCE_FOLDERS = [ | |
'source', | |
'sources', | |
] | |
METADATA_CATEGORIES = { | |
'SERIF': 'Serif', | |
'SANS_SERIF': 'Sans Serif', | |
'DISPLAY': 'Display', | |
'HANDWRITING': 'Handwriting', | |
'MONOSPACE': 'Monospace', | |
} | |
def git_url(copyright): | |
'''Return the url from a string | |
e.g: | |
Copyright the ABC Project Authors (https://www.github.com/mrc/sans) -> | |
https://www.github.com/mrc/sans | |
''' | |
try: | |
return re.search(r'http[a-zA-Z0-9\:\.\/]{1,256}', copyright).group(0) | |
except: | |
all | |
return 'None' | |
def find_mm_compatible_glyphs_files(path): | |
"""Traverse dir tree and generate ttf flavoured variable fonts from | |
MM compatible .glyphs files.""" | |
families = [] | |
for root, dirs, files in os.walk(path, topdown=False): | |
for f in files: | |
if '.glyphs' in f and basename(root) in SOURCE_FOLDERS: | |
glyphs_path = os.path.join(root,f) | |
try: | |
with open(glyphs_path, 'rb') as glyphs_file: | |
glyphs_source = glyphsLib.load(glyphs_file) | |
master_count = len(glyphs_source['fontMaster']) | |
instance_count = len(glyphs_source['instances']) | |
# Get fonts which successfully use MM | |
if master_count >= 2 and instance_count >= 3 and \ | |
master_count != instance_count: | |
print 'Adding: %s' % root | |
families.append((glyphs_path, glyphs_source)) | |
except: # TODO error log and catch these exceptions betters | |
print 'Cannot add %s' % f | |
all | |
return families | |
def rename_fonts(path): | |
for f in os.listdir(path): | |
if f.endswith('.ttf'): | |
new_f = f.replace('VTBeta', 'VFBeta') | |
new_f = new_f.replace('-VF.ttf', '.ttf') | |
old_name = os.path.join(path, f) | |
new_name = os.path.join(path, new_f) | |
os.rename(old_name, new_name) | |
def cleanup_folders(vf_family_dir_name): | |
"""Remove fontmake gen folders and rename variable_ttf folder | |
to familyname""" | |
if not os.path.isdir(vf_family_dir_name): | |
os.rename('variable_ttf', vf_family_dir_name) | |
else: | |
new_files = os.listdir('variable_ttf') | |
for f in new_files: | |
os.rename( | |
os.path.join('variable_ttf', f), | |
os.path.join(vf_family_dir_name, f), | |
) | |
shutil.rmtree('variable_ttf') | |
# Remove temp folders needed to generate variable fonts | |
shutil.rmtree('master_ufo') | |
shutil.rmtree('master_ttf_interpolatable') | |
def create_early_access_file(path): | |
"""Early Access files are used in https://fonts.google.com/earlyaccess | |
to determine faily catagory""" | |
early_acc_filename = 'EARLY_ACCESS.category' | |
early_acc_path = os.path.join(path, early_acc_filename) | |
if not early_acc_filename in os.listdir(path): | |
print 'Writing EARLY_ACCESS.category %s' % early_acc_path | |
with open(early_acc_path, 'w') as acc: | |
acc.write('Sans Serif') | |
def cp_file(src, dest): | |
"""If a file does not exist, copy it""" | |
if not os.path.exists(dest): | |
shutil.copyfile(src, dest) | |
def create_description_file(glyphs_source, path): | |
"""Create basic html doc from glyphs source. | |
May need hand editing if the copyright does not contain a url""" | |
with open('DESCRIPTION.en_us_temp.html', 'r') as tmp_doc: | |
desc_txt = tmp_doc.read() | |
desc_txt = desc_txt.replace( | |
'{{ designer }}', glyphs_source['designer'] | |
) | |
proj_url = git_url(glyphs_source['copyright']) | |
desc_txt = desc_txt.replace('{{ git_url }}', proj_url) | |
desc_file = os.path.join(path, 'DESCRIPTION.en_us.html') | |
with open(desc_file, 'w') as desc_doc: | |
desc_doc.write(desc_txt) | |
def gen_vf_project(glyphs_path, glyphs_source, ofl_path): | |
"""Generate .glyph file into VF font project, based on | |
https://github.com/google/fonts/pull/724""" | |
family_name = glyphs_source['familyName'] | |
vf_family_name = family_name + ' VF Beta' | |
# Generate variable font via cmdline fontmake | |
os.system( | |
"fontmake -g '%s' -o variable --family-name='%s'" | |
% (glyphs_path, vf_family_name) | |
) | |
ofl_family_dir = family_name.lower().replace(' ', '') | |
vf_family_dir = ofl_family_dir + 'vfbeta' | |
rename_fonts('variable_ttf') | |
cleanup_folders(vf_family_dir) | |
create_early_access_file(vf_family_dir) | |
create_description_file(glyphs_source, vf_family_dir) | |
ofl_txt = os.path.join(ofl_path, ofl_family_dir, 'OFL.txt') | |
vf_ofl_txt = os.path.join(vf_family_dir, 'OFL.txt') | |
cp_file(ofl_txt, vf_ofl_txt) | |
def main(path, ofl_path): | |
mm_families = find_mm_compatible_glyphs_files(path) | |
for glyphs_path, glyphs_source in mm_families: | |
gen_vf_project(glyphs_path, glyphs_source, ofl_path) | |
if __name__ == '__main__': | |
if len(sys.argv) != 3: | |
print 'ERROR: include tree path to .glyphs sources and ofl dir' | |
else: | |
main(sys.argv[1], sys.argv[2]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment