lib/fontcustom/scripts/generate.py in fontcustom-1.2.0 vs lib/fontcustom/scripts/generate.py in fontcustom-1.3.0.beta
- old
+ new
@@ -1,138 +1,127 @@
import fontforge
import os
-import md5
import subprocess
import tempfile
import json
+#
+# Manifest / Options
+# Older Pythons don't have argparse, so we use optparse instead
+#
+
try:
- import argparse
- parser = argparse.ArgumentParser(description='Convert a directory of svg and eps files into a unified font file.')
- parser.add_argument('dir', metavar='directory', type=unicode, nargs=2, help='directory of vector files')
- parser.add_argument('--name', metavar='fontname', type=unicode, nargs='?', help='reference name of the font (no spaces)')
- parser.add_argument('--autowidth', '-a', action='store_true', help='automatically size generated glyphs to their vector width')
- parser.add_argument('--nohash', '-n', action='store_true', help='disable hash fingerprinting of font files')
- parser.add_argument('--debug', '-d', action='store_true', help='display debug messages')
- args = parser.parse_args()
- indir = args.dir[0]
- outdir = args.dir[1]
+ import argparse
+ parser = argparse.ArgumentParser()
+ parser.add_argument('manifest', help='Path to .fontcustom-manifest.json')
+ args = parser.parse_args()
except ImportError:
- # Older Pythons don't have argparse, so we use optparse instead
- import optparse
- parser = optparse.OptionParser(description='Convert a directory of svg and eps files into a unified font file.')
- parser.add_option('--name', metavar='fontname', type='string', nargs='?', help='reference name of the font (no spaces)')
- parser.add_option('--autowidth', '-a', action='store_true', help='automatically size generated glyphs to their vector width')
- parser.add_option('--nohash', '-n', action='store_true', help='disable hash fingerprinting of font files')
- parser.add_argument('--debug', '-d', action='store_true', help='display debug messages')
- (args, posargs) = parser.parse_args()
- indir = posargs[0]
- outdir = posargs[1]
+ import optparse
+ parser = optparse.OptionParser()
+ parser.add_option('manifest', help='Path to .fontcustom-manifest.json')
+ (nothing, args) = parser.parse_args()
-f = fontforge.font()
-f.encoding = 'UnicodeFull'
-f.design_size = 16
-f.em = 512
-f.ascent = 448
-f.descent = 64
+manifestfile = open(args.manifest, 'r+')
+manifest = json.load(manifestfile)
+options = manifest['options']
-m = md5.new()
-cp = 0xf100
-files = []
+#
+# Font
+#
+font = fontforge.font()
+font.encoding = 'UnicodeFull'
+font.design_size = 16
+font.em = 512
+font.ascent = 448
+font.descent = 64
+font.fontname = options['font_name']
+font.familyname = options['font_name']
+font.fullname = options['font_name']
+if options['autowidth']:
+ font.autoWidth(0, 0, 512)
+
+# NOTE not referenced anywhere, safe to remove?
KERNING = 15
-for dirname, dirnames, filenames in os.walk(indir):
- for filename in filenames:
- name, ext = os.path.splitext(filename)
- filePath = os.path.join(dirname, filename)
- size = os.path.getsize(filePath)
+#
+# Glyphs
+#
- if ext in ['.svg', '.eps']:
- if ext in ['.svg']:
- # hack removal of <switch> </switch> tags
- svgfile = open(filePath, 'r+')
- tmpsvgfile = tempfile.NamedTemporaryFile(suffix=ext, delete=False)
- svgtext = svgfile.read()
- svgfile.seek(0)
+def removeSwitchFromSvg( file ):
+ svgfile = open(file, 'r+')
+ tmpsvgfile = tempfile.NamedTemporaryFile(suffix=".svg", delete=False)
+ svgtext = svgfile.read()
+ svgfile.seek(0)
+ svgtext = svgtext.replace('<switch>', '')
+ svgtext = svgtext.replace('</switch>', '')
+ tmpsvgfile.file.write(svgtext)
+ svgfile.close()
+ tmpsvgfile.file.close()
- # replace the <switch> </switch> tags with 'nothing'
- svgtext = svgtext.replace('<switch>', '')
- svgtext = svgtext.replace('</switch>', '')
+ return tmpsvgfile.name
- tmpsvgfile.file.write(svgtext)
+def createGlyph( name, source, code ):
+ frag, ext = os.path.splitext(source)
- svgfile.close()
- tmpsvgfile.file.close()
+ if ext == '.svg':
+ temp = removeSwitchFromSvg(source)
+ glyph = font.createChar(code)
+ glyph.importOutlines(temp)
+ os.unlink(temp)
- filePath = tmpsvgfile.name
- # end hack
+ if options['autowidth']:
+ glyph.left_side_bearing = glyph.right_side_bearing = 0
+ glyph.round()
+ else:
+ glyph.width = 512
- m.update(filename + str(size) + ';')
- glyph = f.createChar(cp)
- glyph.importOutlines(filePath)
+for glyph, data in manifest['glyphs'].iteritems():
+ name = createGlyph(glyph, data['source'], data['codepoint'])
- # if we created a temporary file, let's clean it up
- if tmpsvgfile:
- os.unlink(tmpsvgfile.name)
+#
+# Generate Files
+#
- # glyph.left_side_bearing = KERNING
- # glyph.right_side_bearing = KERNING
+try:
+ fontfile = options['output']['fonts'] + '/' + options['font_name']
+ if not options['no_hash']:
+ fontfile += '_' + manifest['checksum']['current'][:32]
- # possible optimization?
- # glyph.simplify()
- # glyph.round()
+ # Generate TTF and SVG
+ font.generate(fontfile + '.ttf')
+ font.generate(fontfile + '.svg')
+ manifest['fonts'].append(fontfile + '.ttf')
+ manifest['fonts'].append(fontfile + '.svg')
- # set glyph size explicitly or automatically depending on autowidth
- if args.autowidth:
- glyph.left_side_bearing = glyph.right_side_bearing = 0
- glyph.round()
- else:
- # force a manual size when autowidth is disabled
- glyph.width = 512
+ # Hint the TTF file
+ subprocess.call('ttfautohint -s -f -n ' + fontfile + '.ttf ' + fontfile + '-hinted.ttf > /dev/null 2>&1 && mv ' + fontfile + '-hinted.ttf ' + fontfile + '.ttf', shell=True)
- files.append(name)
- cp += 1
+ # Fix SVG header for webkit
+ # from: https://github.com/fontello/font-builder/blob/master/bin/fontconvert.py
+ svgfile = open(fontfile + '.svg', 'r+')
+ svgtext = svgfile.read()
+ svgfile.seek(0)
+ svgfile.write(svgtext.replace('''<svg>''', '''<svg xmlns="http://www.w3.org/2000/svg">'''))
+ svgfile.close()
- # resize glyphs if autowidth is enabled
- if args.autowidth:
- f.autoWidth(0, 0, 512)
+ # Convert WOFF
+ scriptPath = os.path.dirname(os.path.realpath(__file__))
+ try:
+ subprocess.Popen([scriptPath + '/sfnt2woff', fontfile + '.ttf'], stdout=subprocess.PIPE)
+ except OSError:
+ # If the local version of sfnt2woff fails (i.e., on Linux), try to use the
+ # global version. This allows us to avoid forcing OS X users to compile
+ # sfnt2woff from source, simplifying install.
+ subprocess.call(['sfnt2woff', fontfile + '.ttf'])
+ manifest['fonts'].append(fontfile + '.woff')
-if args.nohash:
- fontfile = outdir + '/' + args.name
-else:
- hashStr = m.hexdigest()
- fontfile = outdir + '/' + args.name + '_' + hashStr
+ # Convert EOT for IE7
+ subprocess.call('python ' + scriptPath + '/eotlitetool.py ' + fontfile + '.ttf -o ' + fontfile + '.eot', shell=True)
+ subprocess.call('mv ' + fontfile + '.eotlite ' + fontfile + '.eot', shell=True)
+ manifest['fonts'].append(fontfile + '.eot')
-f.fontname = args.name
-f.familyname = args.name
-f.fullname = args.name
-f.generate(fontfile + '.ttf')
-f.generate(fontfile + '.svg')
-
-# Fix SVG header for webkit
-# from: https://github.com/fontello/font-builder/blob/master/bin/fontconvert.py
-svgfile = open(fontfile + '.svg', 'r+')
-svgtext = svgfile.read()
-svgfile.seek(0)
-svgfile.write(svgtext.replace('''<svg>''', '''<svg xmlns="http://www.w3.org/2000/svg">'''))
-svgfile.close()
-
-scriptPath = os.path.dirname(os.path.realpath(__file__))
-try:
- subprocess.Popen([scriptPath + '/sfnt2woff', fontfile + '.ttf'], stdout=subprocess.PIPE)
-except OSError:
- # If the local version of sfnt2woff fails (i.e., on Linux), try to use the
- # global version. This allows us to avoid forcing OS X users to compile
- # sfnt2woff from source, simplifying install.
- subprocess.call(['sfnt2woff', fontfile + '.ttf'])
-
-# eotlitetool.py script to generate IE7-compatible .eot fonts
-subprocess.call('python ' + scriptPath + '/eotlitetool.py ' + fontfile + '.ttf -o ' + fontfile + '.eot', shell=True)
-subprocess.call('mv ' + fontfile + '.eotlite ' + fontfile + '.eot', shell=True)
-
-# Hint the TTF file
-subprocess.call('ttfautohint -s -f -n ' + fontfile + '.ttf ' + fontfile + '-hinted.ttf > /dev/null 2>&1 && mv ' + fontfile + '-hinted.ttf ' + fontfile + '.ttf', shell=True)
-
-# Describe output in JSON
-outname = os.path.basename(fontfile)
-print json.dumps({'fonts': [outname + '.ttf', outname + '.woff', outname + '.eot', outname + '.svg'], 'glyphs': files})
+finally:
+ manifestfile.seek(0)
+ manifestfile.write(json.dumps(manifest, indent=2, sort_keys=True))
+ manifestfile.truncate()
+ manifestfile.close()