Another script to batch process fonts with TTFAutohint
Ramiro Espinoza
Posts: 839
Hi there,
I've been writing some simple scripts to learn a bit more about Python. Yesterday I wrote this one to batch process font families with TTFAutohint in the Mac. It is useful for me and maybe for someone else.
I've been writing some simple scripts to learn a bit more about Python. Yesterday I wrote this one to batch process font families with TTFAutohint in the Mac. It is useful for me and maybe for someone else.
#(re-type.com) Generate and execute the code to batch process a bunch of fonts with TTFAutohint #IMPORTANT: You must name your fonts this way: fontname-weight.ttf import os font_name = raw_input("Write the font name: ") font_family = [] number_of_weights = int(raw_input("Write the number of weights: ")) while True: weight = raw_input ("Enter the name of your font weights one by one: ") font_family.append(weight) if len(font_family) == number_of_weights: break input_directory = raw_input("Write the directory where your input fonts are located: ") for n in font_family: run_ttfautohint = "ttfautohint -v -f latn -n -w gGD "+input_directory+font_name+"-"+n+".ttf"+" "+input_directory+font_name+"-"+n+"-HINTED"+".ttf" os.system(run_ttfautohint)
Tagged:
1
Comments
-
FYI — for that first loop, you could simply structure it like this instead:
while len(font_family) < number_of_weights: weight = raw_input("Enter the name of your font weights one by one: ") font_family.append(weight)
More “pythonic” than using a conditional and break statement within the loop.1 -
Thanks for the tip, Ken.0
-
Tutorial for non Python-savy people: You can use this script in the following way:
1. Copy-paste the code in a text editor.
2. Save the file with a .py suffix.
3. Open Terminal
4. Type "python" and DO NOT press "Enter".
5. Drop the .py file on the Terminal window and press "Enter".
6. Follow the instructions of the program. The new hinted files should show up in the same directory with the word "HINTED" added to their names.
TIP: You can easily get the exact directory where your input files are located by dropping one of the files in a new Terminal window.
TIP2: It is very easy to find the TTFAutohint parameters in the code (just in case: line 17). You can modify them to fit your needs.1 -
Hi Ramiro,
Instead of letting the user input every filename one by one, you could also use the os module in Python to get access to the filesystem. Here is an example of a function that will collect all files with a ‘.ttf’ extension in a pre-defined directory .import os
# small function to collect all files with (a) particular extension(s) in a directory
def getFiles(root, ext):
files = []
allfiles = os.listdir(root)
for myfile in allfiles:
if os.path.splitext(myfile)[1] in ext:
files.append(os.path.join(root, myfile))
return files
root = '/Users/paulus/Desktop/generated/truetype' # ! define your own directory here
if not os.path.exists(root):
print 'Not a valid directory'
else:
ext = ['.ttf']
filenames = getFiles(root, ext)
print filenames
print 'done'2 -
Two other ways without requiring the script to ask the user to input file names and paths, or requiring the path to be hard-coded into the script:
- Have the user cd to the directory containing the TTFs before running and rewrite the script to assume that the TTFs are in the current working directory.
- Or, rewrite it so that it assumes the TTFs are in the same folder as the Python script. That way, there's nothing to input and no need to modify in the script. Just copy or move the script to the folder containing the TTFs and run it.0 -
Alternatively, you could also run the script from a RoboFab environment (i.e. FontLab, RoboFont) and make use of its built-in dialogs:
from robofab.interface.all.dialogs import GetFolder
root = GetFolder('Please select a folder')
print root2 -
Wait, wait! Now I need another month to learn these modules and methods1
-
I am trying to emulate the ttfautohinting batch from FontLab or Glyphs, and almost everything is working except for the bash command. Here is what I have done from all your comments:
# Runing from FontLab or Glyphs
import os
import subprocess
from robofab.interface.all.dialogs import GetFolder
# small function to collect all files with (a) particular extension(s) in a directory
def getFiles(root, ext):
files = []
allfiles = os.listdir(root)
for myfile in allfiles:
if os.path.splitext(myfile)[1] in ext:
files.append(os.path.join(myfile))
return files
setting = "-c -i -W"
root = GetFolder('Please select a folder') # ! define your own directory here
ext = ['.ttf']
filenames = getFiles(root, ext)
newRoot = root+"/hinted/"
if not os.path.exists(newRoot):
os.makedirs(newRoot)
for font in filenames:
run_ttfautohint = " ttfautohint "+setting+" "+root+"/"+font+" "+newRoot+font
#print run_ttfautohint # control point
bashCommand = subprocess.Popen(run_ttfautohint)
bashCommand.wait()
if not os.path.exists(newRoot+font):
print "not hinted", font
else:
print "hinted", font, "@", newRoot
print 'Finished'0 -
Why do this on a Mac?-1
-
I thought that when TTFAutohint is running in Windows or Mac OS environments, it makes the same work. But outside of the choice of the operating system; Isn't the goal of this discussion to create a batch process through a python script that use Robofab environment in order to run TTFAutohint? I think that if this script is possible, such script could be used as a part of other scripts for generating and processing fonts. Sorry, I am a kind of naif in this topics, so I apologize.0
-
Dave: ‘Why do this on a Mac?’
IMHO shell scripts are a very convenient alternative, irrespective the platform. Because reproducibility is a key factor for font production –especially with tools like ttfautohint that are constantly updated– it must be easy to repeat the process. If WOFF, EOT, SVG, and SVGZ have to be generated, subsequently shell scripts can be applied too, of course.
---------------------------------------------------
#!/bin/bash
TTFA -f -i -v /Volumes/FontProduction/TrueType/Web/West/Argo/Base/A057012T.ttf /Volumes/FontProduction/Web/West/TTFA_output/Argo/West/A057012T.ttf
TTFA -f -i -v /Volumes/FontProduction/TrueType/Web/West/Argo/Base/A057013T.ttf /Volumes/FontProduction/Web/West/TTFA_output/Argo/West/A057013T.ttf
et cetera
---------------------------------------------------
For this a fixed directory system makes sense. Because we use an eight-character file-naming system throughout the production (like URW[++] did already in the 1970s) the scripts are easy to duplicate and rename for the different typefaces. At the ATypI 2008 conference in St. Petersburg I gave a brief talk about this and the slides can be found here as PDF. The file-naming part starts at page 65.
1 -
I can’t comment on why the bash command is not working, but I suggest to do all the operations on file paths via the os.path module. This will make your code easier to recycle, and less Mac-centric.
For instance:newRoot = root+"/hinted/"
Would be better written as:newRoot = os.path.join(root, 'hinted')
1 -
I'd also like to pitch in for using the
format
function and/or%
operator for strings, which would allow thettfautohint
command to be rewritten in a more readable way:"ttfautohint {0} {1} {2}".format(setting, os.path.join(root, font), os.path.join(newRoot, font)
Or perhaps more maintainably:ttfcmd = "ttfautohint {0} {1} {2}" setting = "-c -i -W" inputPath = os.path.join(root, font) outputPath = os.path.join(newRoot, font) run_ttfautohint = ttfcmd.format(setting, inputPath, outputPath)
1 -
And lastly, a python feature that I've only recently fully understood (and might be interesting to someone else here): list comprehensions.
getFiles
can be rewritten simply:def getFiles(root, ext): return [f for f in os.listdir(root) if os.path.splitext(f)[1] in ext]
I've found that this makes my Python a lot more succinct, maintainable, and easy to understand (after I got the syntax). Here's a brief overview for those so inclined: http://carlgroner.me/Python/2011/11/09/An-Introduction-to-List-Comprehensions-in-Python.html0 -
It makes the same result, yes; but you can't see it without Windows. The drag and drop workflow Ramiro explained is much more convenient with the GUI that ttfautohint provides..?0
-
Thanks for the advices. I implemented some of them in a very simplistic way (the only one I can afford for the moment
import os # small function to collect all files with (a) particular extension(s) in a directory def getFiles(root, ext): files = [] allfiles = os.listdir(root) for myfile in allfiles: if os.path.splitext(myfile)[1] in ext: files.append(os.path.join(root, myfile)) return files root = '/Users/ramiro/Desktop/test-TTF' # ! define your own directory here settings = "-v -f latn -n -w gGD " # ! define your settings for TTFAutohint new_root = "mkdir " + root +"/Hinted-Fonts" os.system(new_root) if not os.path.exists(root): print 'Not a valid directory' else: ext = ['.ttf'] filenames = getFiles(root, ext) for n in filenames: run_ttfautohint = "ttfautohint "+ settings + n +" "+ n +"-HINTED" move_files = "mv " + root + "/*-HINTED" +" "+ new_root+"/" os.system(run_ttfautohint),os.system(move_files)
0
Categories
- All Categories
- 43 Introductions
- 3.7K Typeface Design
- 798 Font Technology
- 1K Technique and Theory
- 617 Type Business
- 444 Type Design Critiques
- 541 Type Design Software
- 30 Punchcutting
- 136 Lettering and Calligraphy
- 83 Technique and Theory
- 53 Lettering Critiques
- 483 Typography
- 301 History of Typography
- 114 Education
- 68 Resources
- 498 Announcements
- 79 Events
- 105 Job Postings
- 148 Type Releases
- 165 Miscellaneous News
- 269 About TypeDrawers
- 53 TypeDrawers Announcements
- 116 Suggestions and Bug Reports