OTFeatureFreezer GUI app and pyftfeatfreeze commandline tool in Python to permanently "apply" OpenType features to fonts, by remapping their Unicode assignments
View the Project on GitHub twardoch/fonttools-opentype-feature-freezer
OpenType Feature Freezer is a powerful tool designed to make sophisticated typographic features, like small caps or old-style numerals, accessible by default in your fonts. This means you can use these features even in applications with limited or no OpenType support.
Many professional fonts come with “OpenType features” – special typographic effects such as true small capitals, alternative character shapes, ligatures, or figures (numbers) that align differently with text. Normally, you need specific software that allows you to turn these features on.
OpenType Feature Freezer modifies a font file so that selected OpenType features are “frozen” into it. The characters that were previously only accessible via these features become the default characters in the modified font.
For example, if you freeze the “small caps” (smcp
) feature, typing lowercase letters will directly produce small capitals.
This tool is for anyone who wants to use advanced typographic features in applications that don’t provide easy access to OpenType controls. This includes:
OpenType Feature Freezer is available in two forms:
OTFeatureFreezer.app
icon to your /Applications
folder.OTFeatureFreezer.app
icon in /Applications
, choose “Open” from the menu, and then click “Open” in the dialog box.setup_featfreeze.exe
to install the application.This requires Python 3.6 or newer. If you don’t have Python, get it from python.org or your system’s package manager.
Recommended Method (using pipx): Pipx installs Python command-line tools in isolated environments, which is clean and convenient.
pipx install opentype-feature-freezer
To upgrade later:
pipx upgrade opentype-feature-freezer
Alternative Method (using pip):
It’s generally recommended to run pip
via python3 -m pip
to ensure you’re using pip
associated with the correct Python installation, especially if you have multiple Python versions.
It’s best to do this inside a Python virtual environment:
python3 -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
python3 -m pip install --upgrade opentype-feature-freezer
If the above fails, or for a user-specific installation (avoids needing admin rights):
python3 -m pip install --user --upgrade opentype-feature-freezer
Development Version (from GitHub - for testing latest changes):
python3 -m pip install --upgrade git+https://github.com/twardoch/fonttools-opentype-feature-freezer
The GUI provides an easy-to-use interface for all the freezing and renaming options:
.otf
or .ttf
font file.[input_filename].featfreeze.otf
by default).smcp,c2sc,onum
). These are the features you want to “freeze.”cyrl
, latn
) to apply features only for that script. If blank, features are applied across all relevant scripts.SRB
for Serbian) to apply features for that specific language system.search1/replace1,search2/replace2
.The GUI includes a “Help” menu with links to “About” information and the project’s online documentation.
The basic command structure is:
pyftfeatfreeze [OPTIONS] INPATH [OUTPATH]
INPATH
: Path to the input .otf
or .ttf
font file.OUTPATH
: Optional path for the output font file. If omitted, it defaults to INPATH.featfreeze.otf
.Common CLI Options:
-f TAGS, --features TAGS
: Comma-separated OpenType feature tags (e.g., 'smcp,c2sc'
).-s SCRIPT, --script SCRIPT
: OpenType script tag (e.g., cyrl
). If omitted, processing applies to all relevant scripts.-l LANG, --lang LANG
: OpenType language tag (e.g., SRB
).-S, --suffix
: Add a suffix to font family name (derived from feature tags).-U SUFFIX, --usesuffix SUFFIX
: Use a custom suffix (e.g., SC
) when -S
is active.-R 'S/R,...', --replacenames 'S/R,...'
: Search and replace strings in font names (e.g., 'MyFont/MyFontNew,Regular/Reg'
).-z, --zapnames
: Zap glyph names from TTF fonts.-i, --info
: Update font version string.-r, --report
: Report font’s features, scripts, languages instead of processing.-n, --names
: Output names of remapped glyphs.-v, --verbose
: Print detailed processing information.-V, --version
: Show program version.-h, --help
: Show help message with all options.CLI Examples:
pyftfeatfreeze -f 'c2sc,smcp,onum' -S -U "SC OS" -R 'OpenSans/OpenSansSO' OpenSans-Regular.ttf OpenSansSO-Regular.ttf
locl
for Cyrillic script, Bulgarian language), add “BG” suffix:
pyftfeatfreeze -f 'locl' -s 'cyrl' -l 'BGR ' -S -U BG MyFont.otf MyFontBG.otf
Note: To remap features for multiple script/language combinations, run the tool multiple times, using the output of one run as the input for the next. Apply renaming options (-S
, -U
, -R
) typically on the final run.
pyftfeatfreeze -R 'Lato/Otal,Regular/Rg' Lato-Regular.ttf Otal-Rg.ttf
The core logic resides in the RemapByOTL
class within src/opentype_feature_freezer/__init__.py
. The process flow is as follows:
fontTools.ttLib.TTFont
.--features
), script tag (--script
), and language tag (--lang
).LangSysRecord
, the DefaultLangSys
for that script is used.a.alt1
from [a.alt1, a.alt2]
).cmap
Remapping:
cmap
table) is modified. Existing Unicode codepoints that pointed to original glyphs are updated to point to the new glyphs resulting from the applied substitutions. This is what makes the features “default.”--suffix
, --usesuffix
, or --replacenames
, the tool modifies various name records in the name
table (e.g., Family Name (ID 1), Full Name (ID 4), PostScript Name (ID 6), Version String (ID 5), Unique ID (ID 3), WWS Family/Subfamily (ID 16, 17))..otf
), it also updates FamilyName
, FullName
, and the main font name in the CFF
table..ttf
), the --zapnames
option sets the post
table format to 3.0. This removes glyph names from the font, which can sometimes reduce file size but makes debugging harder.fontTools.ttLib.TTFont.save()
.Key Modules:
src/opentype_feature_freezer/__init__.py
: Contains the RemapByOTL
class with the primary font processing logic.src/opentype_feature_freezer/cli.py
: Implements the pyftfeatfreeze
command-line interface using Python’s argparse
module. It parses arguments and passes them to RemapByOTL
.app/OTFeatureFreezer.py
: Uses ezgooey
to wrap the argparse
definitions from cli.py
, creating the OTFeatureFreezer
GUI application for macOS and Windows.Limitations:
cmap
Dependency: The tool works by remapping existing cmap
entries. If a glyph involved in a substitution (either the original or the replacement) does not have a Unicode value assigned in any cmap
table, that specific remapping might not have a visible effect through standard character input. A warning is issued in such cases.typing
module usage.logging
module is used for outputting informational messages, warnings, and errors. Verbosity is controlled by the -v
flag.pyproject.toml
.mypy.ini
.tests/
directory.pyproject.toml
apart from MyPy, contributions should generally follow PEP 8 guidelines and maintain consistency with the existing codebase.Contributions are welcome! Whether it’s reporting a bug, suggesting an improvement, or submitting code changes.
Reporting Issues:
Development Setup:
git clone https://github.com/twardoch/fonttools-opentype-feature-freezer.git
cd fonttools-opentype-feature-freezer
pytest
and mypy
, in a virtual environment using Poetry:
poetry install
poetry shell
Building:
poetry build
The distributable files will be in the dist/
directory.
app/
subdirectory.cd app
./macdeploy all
Running Tests:
poetry install
).pytest
from the project root directory:
pytest
Or, if your environment is not yet active:
poetry run pytest
This tool is licensed “as is” under the Apache License, Version 2.0. By using the tool, you accept all conditions of the license, including Disclaimer of Warranty and Limitation of Liability.
Important: When modifying fonts, please ensure you comply with the font’s End User License Agreement (EULA). If the font is licensed under the SIL Open Font License (OFL) and uses Reserved Font Name(s), you must use the -R
(rename) option to change the font’s name if you plan to distribute the modified version.
-s
(script) option: if not provided, remapping attempts to apply to all relevant scripts.-S
(suffix) option: if not provided, no suffix is added. Introduced GUI apps.For older history, this tool was previously part of the fonttools-utils
repository.
AUTHORS
and CONTRIBUTORS
files, and GitHub commit history).fontTools
library.