Get glyph widths by fontforge script

3.4k views Asked by At

For getting glyph widths, I convert a TTF font to AFM, and then parse the content of AFM file to get the width of each glyph.

Since technically, fontforge is capturing the glyph widths from the binary TTF file, and then create a AFM font file based on the AFM standard template. I wonder if it is possible to directly convert a TTF file to a list of glyph widths by a fontforge command?!?

1

There are 1 answers

0
allcaps On BEST ANSWER

FontForge includes two interpreters so you can write scripts to modify fonts. One of these interpreters is Python (preferred), one is a legacy language. Fontforge embeds Python but it is also possible to build Fontforge as a Python extension.

So what will you use: Python or Legacy language? What interface: Command line or GUI or Python extension?

Command line and Legacy Language

The script can be in a file, or just a string presented as an argument. You may need to specify which interpreter to use with the -lang argument. See Command Line Arguments.

$ fontforge -script scriptfile.pe {arguments}
$ fontforge -c "script-string" {arguments}
$ fontforge -lang={ff|py} -c "script-string"

After scanning the documentation I wrote my scriptfile.pe:

Open($1, 1)
Select($2)
Print( GlyphInfo('Width') )

Than:

$ fontforge -script scriptfile.pe YourFont.ttf A
... # Some output truncated.
1298

Execute Scripts from GUI

Open a font. Than choose: 'File' > 'Execute script...'. Enter:

Select('A')
Error(ToString(GlyphInfo('Width')))

Click 'OK'.

Fontforge Error Window

Python Extension

First the width of a single glyph (docs):

>>> import fontforge
>>> f = fontforge.open("YourFont.ttf")
>>> f['A'].width
1298

Here the answer to your question. For each glyph the encoding index, name and width:

>>> for i in f.selection.all():
...    try:
...       name, width = f[i].glyphname, f[i].width
...       print i, name, width
...    except:
...       pass
... 
0 uni0009 0
2 uni0002 0
13 nonmarkingreturn 510
# ... Truncated ...
65707 germandbls.smcp 2266
>>>

Note: I used try/except because somehow f.selection.all() does also select non-glyphs. Accessing a glyph that doesn't exist will raise an error.