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()