How to Transform Glyphs Using Matrix in FontForge
This guide explains how to apply mathematical 2D transformation matrices to glyph contours in FontForge. You will learn the mechanics behind FontForge's six-element affine transformation arrays, how to input custom matrix values through the graphical user interface, and how to automate the transformation process using the FontForge Python scripting environment.
Understanding the FontForge Transformation Matrix
FontForge represents 2D affine transformations using a six-element
array: [a, b, c, d, x, y]. This array maps an original
coordinate point \((X, Y)\) to a new
coordinate point \((X', Y')\)
using the following linear equations:
- \(X' = a \cdot X + c \cdot Y + x\)
- \(Y' = b \cdot X + d \cdot Y + y\)
In this structure:
- \(a\): Horizontal scaling factor.
- \(b\): Vertical shear (skew along the Y-axis).
- \(c\): Horizontal shear (skew along the X-axis).
- \(d\): Vertical scaling factor.
- \(x\): Horizontal translation (movement along the X-axis in font units).
- \(y\): Vertical translation (movement along the Y-axis in font units).
Standard Matrix Configurations
- Identity (No Change):
[1, 0, 0, 1, 0, 0] - Translation:
[1, 0, 0, 1, dx, dy] - Scaling:
[sx, 0, 0, sy, 0, 0] - Horizontal Slant (Italicize):
[1, 0, tan(θ), 1, 0, 0]where \(\theta\) is the slant angle. - Rotation:
[cos(θ), sin(θ), -sin(θ), cos(θ), 0, 0]where \(\theta\) is the rotation angle in radians.
Applying Matrices via the Graphical User Interface
- Open your font file in FontForge.
- Select one or more glyphs in the Font View, or double-click a single glyph to open the Glyph View.
- Navigate to the top menu and select Element >
Transformations > Transform... (or
press
Ctrl+Shift+E/Cmd+Shift+E). - In the transformation dialog window, change the first drop-down menu from its default (such as Origin or Move) to Matrix.
- Input your six matrix parameters into the designated fields:
- [ a ] [ c ] [ x ]
- [ b ] [ d ] [ y ]
- Click OK to execute the transformation on the selected contours.
Applying Matrices via Python Scripting
FontForge includes a built-in Python module named psMat
designed for matrix generation, concatenation, and transformation.
Example: Custom Matrix Transformation
To apply a custom matrix directly to a glyph, pass a tuple of six
numerical values to the glyph.transform() method:
import fontforge
# Open the font file
font = fontforge.open("MyFont.sfd")
# Select a target glyph
glyph = font["A"]
# Define a matrix: [a, b, c, d, x, y]
# This example scales X by 1.2, shears X by 0.2, and shifts Y by 50 units
custom_matrix = (1.2, 0.0, 0.2, 1.0, 0.0, 50.0)
# Apply the transformation
glyph.transform(custom_matrix)
# Save changes
font.save()Example: Combining
Transformations with psMat
The psMat module allows you to compose complex matrices
without manual calculation:
import fontforge
import psMat
import math
font = fontforge.open("MyFont.sfd")
glyph = font["B"]
# Generate component matrices
scale = psMat.scale(1.1, 0.9) # Scale X by 110%, Y by 90%
rotate = psMat.rotate(math.radians(15)) # Rotate 15 degrees counter-clockwise
translate = psMat.translate(20, -10) # Move 20 units right, 10 units down
# Multiply matrices together (applied from right to left)
combined_matrix = psMat.compose(scale, rotate)
final_matrix = psMat.compose(combined_matrix, translate)
# Apply to glyph
glyph.transform(final_matrix)
font.save()Post-Transformation Clean-Up
Matrix operations often alter point positioning in ways that disrupt font standards. After applying transformations:
- Round Coordinates to Integers: PostScript and
TrueType outlines typically require whole integer coordinates. Run
Element > Round > To
Int (or
glyph.round()in Python). - Correct Extrema: Rotations and shears move on-curve
extrema. Run Element > Add Extrema
(or
glyph.addExtrema()) to maintain proper curve rendering. - Correct Direction: Reflection matrices (negative
scaling factors) invert path winding order. Run Element
> Correct Direction (or
glyph.correctDirection()) to ensure internal counters render as cutouts rather than solid fills.