Subset a Font from a Text File with FontForge Python

Yes, you can generate a font subset based on a text file using FontForge's Python module. This process works by extracting unique characters from your source text file, opening the target font in FontForge, selecting only the glyphs corresponding to those characters, removing all unused glyphs, and exporting the reduced font file. This is an effective way to drastically reduce font file sizes for web performance or embedded systems.

Prerequisites

To use FontForge with Python, you must run your script through FontForge's embedded Python interpreter. FontForge provides a standalone binary that can execute Python scripts directly using the -script flag:

fontforge -script subset.py

Alternatively, on Linux distributions, you can install the system-level Python bindings (often packaged as python3-fontforge).

The Subsetting Script

Below is a complete Python script that reads unique characters from input.txt, extracts them from SourceFont.ttf, and outputs a subsetted font named SubsetFont.ttf.

import sys
import fontforge

def subset_font(font_path, text_path, output_path):
    # Step 1: Read unique characters from the text file
    with open(text_path, 'r', encoding='utf-8') as f:
        text_content = f.read()
    
    unique_chars = set(text_content)

    # Step 2: Open the target font
    font = fontforge.open(font_path)

    # Step 3: Deselect all glyphs to start with a clean slate
    font.selection.none()

    # Step 4: Select only the glyphs present in the text file
    for char in unique_chars:
        codepoint = ord(char)
        # Verify the glyph exists in the font before selecting
        if codepoint in font:
            font.selection.select(("more",), codepoint)

    # Step 5: Always retain the .notdef glyph (undefined character box)
    if ".notdef" in font:
        font.selection.select(("more",), ".notdef")

    # Step 6: Invert the selection and clear all unused glyphs
    font.selection.invert()
    font.clear()

    # Step 7: Generate the optimized subset font
    font.generate(output_path)
    font.close()

if __name__ == "__main__":
    subset_font("SourceFont.ttf", "input.txt", "SubsetFont.ttf")

How the Script Works

  1. Character Extraction: The script opens the plain text file using UTF-8 encoding and places all characters into a Python set, eliminating duplicates.
  2. Glyph Selection: It converts each character to its Unicode codepoint via ord(char) and verifies if the font contains that encoding. The ("more",) flag appends the character to the active selection without resetting previous selections.
  3. Preserving Critical Glyphs: Retaining standard fallback glyphs like .notdef is critical to prevent font rendering errors when an unmapped character is encountered in runtime environments.
  4. Inversion and Removal: font.selection.invert() flips the selection so that all unused characters are highlighted, and font.clear() wipes them entirely from the font database.
  5. Generation: font.generate() exports the subsetted font into modern formats like TTF, OTF, or WOFF depending on the specified file extension.