Custom Validation Checks with FontForge Python
FontForge provides a robust Python scripting interface that allows
type designers and font developers to automate testing and build custom
validation checks. By querying glyph geometry, font metrics, metadata,
and OpenType tables directly through the fontforge Python
module, you can programmatically detect design flaws, enforce style
standards, and catch technical errors across entire font families before
production.
Built-In Validation via Python
FontForge includes a native validation suite that can be executed
directly from Python. The glyph.validate() method runs
standard technical checks on individual glyphs, assessing outline
validity, path direction, self-intersections, and point placement.
import fontforge
font = fontforge.open("MyFont.sfd")
for glyph in font.glyphs():
state = glyph.validate()
if state != 0:
print(f"Validation warning on {glyph.glyphname}: code {state}")The returned integer is a bitmask representing specific errors, such as missing extrema, open contours, or self-intersecting paths.
Writing Custom Geometric Checks
You are not limited to built-in rules; you can inspect the raw coordinates of contours and points to enforce proprietary geometric constraints.
1. Detecting Extrema Violations
Glyph curves generally require on-curve control points at their horizontal and vertical extrema for proper rasterization and hinting. You can iterate through a glyph's layers and contours to inspect control points:
def check_extrema(glyph):
layer = glyph.layers[glyph.active_layer]
for contour in layer:
for point in contour:
# Analyze on-curve and off-curve coordinates
if point.on_curve:
# Custom logic for bounding limits
pass2. Checking Minimum Distance Between Points
Coincident or nearly overlapping points can cause rendering artifacts. You can compute the Euclidean distance between sequential points along a contour to ensure they meet a minimum threshold:
import math
def check_minimum_distance(glyph, min_dist=1.0):
layer = glyph.layers[glyph.active_layer]
for contour in layer:
for i in range(len(contour)):
p1 = contour[i]
p2 = contour[(i + 1) % len(contour)]
dist = math.hypot(p2.x - p1.x, p2.y - p1.y)
if dist < min_dist:
print(f"{glyph.glyphname}: Points too close ({dist:.2f} units)")Validating Metrics and Spacing
Custom scripts can evaluate spacing rules across the font to ensure uniform appearance:
- Bounding Box Checks: Verify that glyph paths do not
exceed the font's
ascentordescentlimits unexpectedly. - Sidebearing Consistency: Check that left sidebearings (LSB) and right sidebearings (RSB) meet minimum margins or adhere to spacing tables.
- Monospace Uniformity: If building a monospaced
font, assert that
glyph.widthis identical for every character.
def validate_monospace(font, expected_width=600):
for glyph in font.glyphs():
if glyph.width != expected_width:
print(f"Width error: {glyph.glyphname} has width {glyph.width}")Verifying Metadata and Encodings
FontForge Python scripts can inspect font-level properties, OpenType features, and Unicode mappings to ensure delivery compliance:
- Required Glyphs: Verify the existence of essential
glyphs such as
.notdef,space, and standard punctuation. - Unicode Coverage: Ensure specific blocks (such as Basic Latin or accented sets) contain no unmapped gaps.
- Naming Consistency: Check that the PostScript name,
family name, and weight strings in
font.sfnt_namesfollow the required naming conventions and do not contain illegal characters.
Automating Validation in Build Pipelines
Because FontForge can be run headless from the command line using
fontforge -script validator.py, you can integrate custom
validation scripts directly into continuous integration (CI) workflows.
By configuring your script to exit with a non-zero status code
(sys.exit(1)) when a test fails, you prevent faulty font
binaries from being generated and released.