FontForge Feature Inheritance Across Font Styles
Managing OpenType feature inheritance across multiple font styles in
FontForge requires decoupling your layout logic from individual font
files. Because FontForge stores OpenType Layout (GSUB/GPOS) data per
.sfd (Spline Font Database) file rather than via a global
dynamic project file, maintaining feature consistency across Regular,
Bold, or Italic cuts relies on external feature files
(.fea), lookup exports, and Python automation. This guide
details how to implement a modular feature workflow that prevents
repetitive manual configuration and keeps your font family
synchronized.
The Strategy: Decoupling Logic with Adobe Feature Files
The most robust way to inherit and share OpenType layout features
across multiple styles in FontForge is using external Adobe Feature File
syntax (.fea). By centralizing shared substitutions into
external text files, child styles can inherit parent feature definitions
directly.
1. Structure Modular Feature Files
Instead of writing OpenType code inside FontForge’s internal GUI
editors for every style, create a directory for .fea
files:
common.fea: Stores shared features applicable to the entire family (e.g., standard ligaturesliga, localized formslocl, tabular figurestnum, and discretionary ligaturesdlig).regular.fea: Contains code specific to the Regular weight.bold.fea: Contains code specific to the Bold weight.
Using the include() directive, style-specific files
inherit the parent file:
# In bold.fea
include(common.fea);
# Additional Bold-only substitution rules go here
feature ss01 {
sub a by a.alt;
} ss01;
2. Import Feature Files into FontForge Styles
To apply your modular features to each style file:
- Open your style-specific font file in FontForge (e.g.,
MyFont-Bold.sfd). - Go to File > Merge Feature Info....
- Select your corresponding feature file (e.g.,
bold.fea). - FontForge parses the code and populates the GSUB/GPOS tables,
automatically including everything defined in the parent
common.fea.
Alternative GUI Method: Lookup Export and Import
If you prefer using the native FontForge interface without writing external text files:
- Establish the Master Style: Configure all GSUB substitutions (such as small caps, fractions, and ligatures) in your base style under Element > Font Info > Lookups.
- Export Lookups: Select a lookup in the list and click Save Feature to export it as an external file.
- Inherit into Other Styles:
- Open the target style (e.g., Italic).
- Go to Element > Font Info > Lookups.
- Click Add Lookup, then select Import to load the exported lookup file.
Note: Lookups that rely on specific glyph geometry (like GPOS pair kerning) should generally not be shared wholesale across radically different weights, whereas substitution features (GSUB) inherit seamlessly.
Automating Inheritance Across Styles via Python
When managing larger families, updating features manually across each
.sfd file is prone to human error. FontForge’s built-in
Python scripting environment allows you to apply inherited features
programmatically across the entire family.
Create a script named apply_features.py:
import fontforge
import glob
# Path to the base inherited feature file
common_fea = "features/common.fea"
# Target all SFD files in the directory
font_files = glob.glob("*.sfd")
for file_path in font_files:
font = fontforge.open(file_path)
# Merge the inherited features into the current style
font.mergeFeature(common_fea)
# Save the updated SFD
font.save()
font.close()
print(f"Applied inherited features to {file_path}")Run this script inside FontForge:
fontforge -script apply_features.pyCritical Rules for Smooth Feature Inheritance
- Enforce Strict Glyph Naming: All inherited rules
rely on exact glyph name matching. If
common.feareferencesf_iora.sc, every style in the family must use those exact names, or FontForge will reject the feature compilation. - Separate Substitution from Positioning: Keep GSUB (ligatures, alternates) separate from GPOS (kerning, mark-to-base). Substitution logic is typically 100% reusable across styles, whereas positioning metrics depend on individual glyph shapes and weights.
- Compile at Build Time: Avoid manually saving
complex lookups into
.sfdfiles during early design phases. Instead, keep your.sfdfiles clean and use a Python build script to merge the inherited.feadefinitions whenever you generate final OTF/TTF binaries.