Is there a good way to transform every glyph of a font uniformly?

822 views Asked by At

I'm a little stuck on how to apply a transformation to every glyph of a particular font using fonttools. I'm playing with an Open Source font where every character is just a taaaad too high up in its bounding box, so I was hoping to transform it down.

It is a variable font (Source Sans). This is the salient code sample:

from fontTools import ttLib
from fontTools.pens.transformPen import TransformPen
from fontTools.pens.ttGlyphPen import TTGlyphPen

font = ttLib.TTFont(font_path)


for glyphName in font["glyf"].keys():
    print(glyphName)
    glyph = font.getGlyphSet().get(glyphName)
    glyphPen = TTGlyphPen(font.getGlyphSet())
    transformPen = TransformPen(glyphPen, (1.0, 0.0, 0.0, 1.0, 0, -300))
    glyph.draw(transformPen)
    transformedGlyph = glyphPen.glyph()
    font["glyf"][glyphName] = transformedGlyph

However, when I do this, the transformation doesn't quite go as expected... some characters are shifted down a lot, and other are shifted down only a little. i, 3, 4, 5, and 6 are some noteworthy examples, whereas other letters and numbers are unaffected.

Is there an easier way to do this in general, and if not, why are some letters getting transformed differently than others?

1

There are 1 answers

0
Steven Petryk On BEST ANSWER

I found out what was happening.

Some glyphs are made up of other, nested glyphs. These are called composite glyphs, as opposed to simple glyphs.

Since I was transforming all glyphs, I was transforming all composite glyphs, as well as the simple glyphs that they were composed from. This led to composite glyphs getting the appearance of being transformed twice.

The new code looks like this:

glyphPen = TTGlyphPen(font.getGlyphSet())
transformPen = TransformPen(glyphPen, Transform().translate(0, -25))

for glyphName in font.getGlyphOrder():
    glyph = font['glyf'][glyphName]

    # Avoid double-transforming composite glyphs
    if glyph.isComposite():
        continue

    glyph.draw(transformPen, font['glyf'])
    font['glyf'][glyphName] = glyphPen.glyph()