Rotate All Glyphs by Angle in FontForge Python

This guide explains how to batch-rotate all glyph outlines by a specific angle using the FontForge Python module. By leveraging FontForge's scripting interface alongside the psMat transformation module, you can programmatically apply affine transformation matrices across every glyph in a font file and export the modified font.

The FontForge Python Script

To rotate glyphs, FontForge provides the transform() method on glyph objects, which accepts a 2D transformation matrix. The psMat module provides the rotate() function to generate this matrix using radians.

Below is the complete script to open a font, rotate every glyph outline by a designated angle, and save the result:

import fontforge
import psMat
import math

def rotate_font_glyphs(input_font_path, output_font_path, angle_degrees):
    # Open the font file
    font = fontforge.open(input_font_path)
    
    # Convert angle to radians
    angle_radians = math.radians(angle_degrees)
    
    # Create the rotation matrix
    rotation_matrix = psMat.rotate(angle_radians)
    
    # Iterate through all glyphs in the font
    for glyph in font.glyphs():
        # Apply the rotation transformation to the glyph outline
        glyph.transform(rotation_matrix)
    
    # Generate the updated font file
    font.generate(output_font_path)
    font.close()

# Example usage: Rotate all glyphs 45 degrees counterclockwise
rotate_font_glyphs("input.ttf", "output_rotated.ttf", 45)

How It Works

  1. fontforge.open(input_font_path): Loads the source font into memory. FontForge supports formats including TTF, OTF, and SFD.
  2. psMat.rotate(angle_radians): Constructs a \(2 \times 3\) affine transformation matrix representing rotation. FontForge expects the angle in radians, so math.radians() is used to convert standard degree values.
  3. font.glyphs(): Returns a generator covering every glyph defined within the font.
  4. glyph.transform(matrix): Multiplies all coordinate points and control handles of the glyph's paths by the transformation matrix.
  5. font.generate(output_font_path): Compiles and writes the modified outlines into a new font file.

Rotating Around the Glyph Center

By default, psMat.rotate() rotates outlines around the font origin point (0, 0). To rotate each glyph around its individual visual center instead of the font origin, compose a transformation that shifts the glyph center to (0,0), rotates, and shifts it back:

def rotate_glyphs_around_center(glyph, angle_radians):
    # Get bounding box: (xmin, ymin, xmax, ymax)
    bbox = glyph.boundingBox()
    
    # Calculate visual center
    cx = (bbox[0] + bbox[2]) / 2.0
    cy = (bbox[1] + bbox[3]) / 2.0
    
    # Compose: translate to origin -> rotate -> translate back
    transform = psMat.compose(
        psMat.translate(-cx, -cy),
        psMat.rotate(angle_radians),
        psMat.translate(cx, cy)
    )
    
    glyph.transform(transform)

Replace glyph.transform(rotation_matrix) in the main loop with rotate_glyphs_around_center(glyph, angle_radians) if you require in-place rotation for each character.