Skip to main content

Fontforge Utility Plugin on References and Selections

This plugin helps finding:

  • Glyphs with nested references and flatten such references
  • Glyphs with distorted references and unlink references
  • Unused glyphs and remove them

Required Python version is:

  • 3.9 to 3.11 for limited features
    • "Select unused glyphs" menu will be disabled in this case due to possible crash
  • 3.12 or later for full features

Details

Glyphs with nested references

Nested references are known to cause problems in certain environments. More information can be found at fontbakery issue 2961 and arrowtype issue 412.

Glyphs with distorted references

While each references can have affine transformation, ttfautohint tool cannot deal with distorted references well. Unlinking such references will be needed if you plan to use ttfautohint.

Unused glyphs (Python ≥ 3.12 only)

When a glyph is expressed as unused or unreachable, such glyphs neither has Unicode encodings nor is referenced from another glyph or a GSUB table. They can be dropped to reduce the file size.

Install

pip3 install fontforge-ref-sel-util

Make sure Fontforge Python module is usable

In interactive mode of Python, run:

import fontforge

If it raises ModuleNotFoundError exception, install Fontforge first. If installed, make sure the build option set that the Python module gets also installed. If already so, Python interpreter does not recognize the module path where the required module.

export PYTHONPATH=/path/to/fontforge/python/module:$PYTHONPATH

Usage

In Fontforge GUI

This plugin adds following items into "Tools" menu:

  • Select
    • Glyphs with nested references
    • Glyphs with distorted references
    • Glyphs referring currently selected glyphs
      • Direct refs only
      • Including indirect refs
    • Unused glyphs
  • Decompose nested references

In Python script

import fontforge
import fontforge_refsel

font = fontforge.open('path/to/font.sfd')

# Select glyphs with nested references
fontforge_refsel.selectGlyphsWithNestedRefs(font)      # set selection
fontforge_refsel.selectGlyphsWithNestedRefs(font, 0)   # set selection
fontforge_refsel.selectGlyphsWithNestedRefs(font, 1)   # append selection
fontforge_refsel.selectGlyphsWithNestedRefs(font, -1)  # deselect

# Select glyphs with distorted references
# (i.e. non-identity linearly transformed references)
fontforge_refsel.selectGlyphsWithDistortedRefs(font)      # set selection
fontforge_refsel.selectGlyphsWithDistortedRefs(font, 0)   # set selection
fontforge_refsel.selectGlyphsWithDistortedRefs(font, 1)   # append selection
fontforge_refsel.selectGlyphsWithDistortedRefs(font, -1)  # deselect

# Select unreachable glyphs
fontforge_refsel.selectUnusedGlyphs(font)      # set selection
fontforge_refsel.selectUnusedGlyphs(font, 0)   # set selection
fontforge_refsel.selectUnusedGlyphs(font, 1)   # append selection
fontforge_refsel.selectUnusedGlyphs(font, -1)  # deselect

# Check a glyph
glyph = font['foo']
result = fontforge_refsel.glyphHasNestedRefs(glyph)
result = fontforge_refsel.glyphHasDistortedRefs(glyph)
result = glyph.glyphname in fontforge_refsel.unusedGlyphs(font)

# List of glyphs with...
result = [glyph.glyphname for glyph in filter(fontforge_refsel.glyphHasNestedRefs, font.glyphs())]
result = [glyph.glyphname for glyph in filter(fontforge_refsel.glyphHasDistortedRefs, font.glyphs())]
result = list(fontforge_refsel.unusedGlyphs(font))  # unusedGlyphs() returns a frozenset object

# Decompose nested references
fontforge_refsel.decomposeNestedRefs(font)         # selected glyphs
fontforge_refsel.decomposeNestedRefs(font, False)  # selected glyphs
fontforge_refsel.decomposeNestedRefs(font, True)   # all glyphs
# if no glyphs are selected, processes all glyphs

# Unlink distorted references (Python < 3.12 may crash)
fontforge_refsel.selectGlyphsWithDistortedRefs(font)
font.unlinkReferences()
font.removeOverlap()  # may or may not needed

# Drop unused glyphs (Python < 3.12 may crash)
for glyph in fontforge_refsel.unusedGlyphs(font):
    font.removeGlyph(glyph)

# Check what glyph refers certain glyph
glyph = font['foo']
result = fontforge_refsel.whatRefers(glyph)         # direct references only
result = fontforge_refsel.whatRefers(glyph, False)  # direct references only
result = fontforge_refsel.whatRefers(glyph, True)   # also indirect references

Metadata

Release files for fontforge-ref-sel-util 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fontforge-ref-sel-util 0.2.0
File Size Uploaded
fontforge_ref_sel_util-0.2.0.tar.gz 8.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fontforge-ref-sel-util 0.2.0
File Interpreter ABI Platform
fontforge_ref_sel_util-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 18.5 kB

Release files / fontforge_ref_sel_util-0.2.0.tar.gz

Download URL fontforge_ref_sel_util-0.2.0.tar.gz
Size 8.9 kB
Tags Source
SHA-256 checksum
How to use checksums
949fe768e5962c1b308be9e74f16de8395751cc5557b3dcc4829be56456560f8
BLAKE2b-256 checksum
How to use checksums
5ae8a9310187b2df9972d3c66605cc4274f84ee31486f074e5751912f43d7d47
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.

Transparency log

Release files / fontforge_ref_sel_util-0.2.0-py3-none-any.whl

Download URL fontforge_ref_sel_util-0.2.0-py3-none-any.whl
Size 9.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6ce5ddc9126d8ac1e46ec5c74b8013319be2c5eede4ab6fd460f141870d1e037
BLAKE2b-256 checksum
How to use checksums
7adbaefca85b6537ade7a707732b3d7c2676479e6bc06a1e5b64b831f978ba4f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page