Skip to content
GissioPublic

About

Converts .bdf pixel fonts into .ufo sources, enabling the creation of both static and variable vector fonts.

Topics

Resources

Stars

5 stars

Watchers

1 watching

Forks

Repository files navigation

Project logo

bdf2ufo

bdf2ufo is a tool for converting .bdf bitmap fonts into .ufo sources, enabling the creation of both static and variable vector fonts.

It bridges the gap between classic pixel-based design and modern font production workflows—making it easy to bring legacy bitmap fonts into contemporary type systems.

Features

Variable Font Axes

bdf2ufo provides built-in support for six expressive axes tailored to pixel typography:

  • Weight (wght)
  • Width (wdth)
  • Italic (ital)
  • Roundness (ROND)
  • Bleed (BLED)
  • Jitter (JITT)

These axes allow you to simulate the rendering quirks of historical display technologies such as LCD screens, CRT monitors, and dot matrix printers, while remaining fully compatible with modern OpenType variable font workflows.

The ital axis slants the glyphs by the angle set with the italic_angle build configuration option (12 degrees by default).

The pixel element size follows the design coordinate of the wght axis: an element fills its pixel at 400, half of it at 200 and 1.75 times it at 700. The axis_maps build configuration option maps user coordinates to design coordinates on any axis, for example to make Bold (700) lighter and move the heaviest weight to Black (900). On an axis that is not variable, the map gives the design coordinate of its default value: a static font can report weight 400 or 700 while its elements keep the size of design weight 320. All other axis values in the build configuration are user coordinates.

Smart Glyph Construction

  • Element Glyph System

    Reuses a base “element” glyph to construct characters efficiently, reducing file size and complexity.

  • Automatic Composition

    Builds precomposed characters (e.g. é) from their base and mark glyphs using Unicode decomposition data, and keeps the drawn glyph whenever its bitmap differs.

  • Anchor Generation

    Automatically adds:

    • base-to-mark anchors
    • mark-to-mark anchors
  • Hinting-Safe Components

    Flattens nested components and disables TrueType grid rounding of component offsets, so fonts rendered with hinting (e.g. on Windows) don't show empty pixel rows or columns.

  • Named Glyphs

    Keeps unencoded glyphs (ENCODING -1 in the .bdf file) under their BDF glyph name, without a Unicode value.

  • Small Caps

    Generates the smcp and c2sc OpenType features for Latin and Cyrillic from the glyphs present in the font. See Small caps.

Small caps

bdf2ufo writes smcp (lowercase to small caps) and c2sc (capitals to small caps) automatically for each script whose alphabet is complete. There is no option to set: a script only gets substitutions when every letter of its basic alphabet (a–z for Latin, а–я without й for Cyrillic) has a small cap, so a font with only a few small capitals, such as IPA ɪ and ʀ, gets no half-working feature.

The small cap of a lowercase letter is, in order of preference:

  1. A named glyph with the letter's glyph name and a .sc suffix, such as x.sc or uni0431.sc. Glyph names are AGL names (a, eacute, oslash) or uniXXXX. A named glyph always wins, so it can replace any of the following.
  2. An existing glyph:
    • the lowercase letter itself, if it is drawn as a small cap: most Cyrillic letters (в г д …), Latin letters such as ø ŋ ə, and the Unicode small capitals (ʀ ɪ). See SMALL_CAPS_LOWERCASE in data.py;
    • the Unicode small capital of the letter, found by name: LATIN SMALL LETTER A takes LATIN LETTER SMALL CAPITAL A (U+1D00 ᴀ), LATIN SMALL LIGATURE OE takes U+0276 ɶ;
    • the small cap of an alias, for letters without a small capital of their own, such as dotless ı (i) or kra ĸ (k). See SMALL_CAPS_ALIASES in data.py.
  3. The accented letter itself, when its base letter is its own small cap (Cyrillic й on и).
  4. A built glyph for any other accented letter, named after it with a .sc suffix (such as aacute.sc). Its accents are taken from its capital, but never placed like the capital places them:
    • If the capital is composed (for instance Ǻ from A, ring and acute), the small cap is composed from the same marks. Each mark attaches with its mark anchor to the anchor of the small cap, or of the previous mark of the same anchor, like on a lowercase letter. Where the capital draws its marks is not used.
    • If the capital is drawn, its accent pixels are copied and moved onto the small cap of the base letter by the difference of their base anchors, so an accent drawn differently from the combining mark (such as the apostrophe of Ľ) stays that way.
    • If the font has no such capital, the marks of the canonical decomposition are attached with their mark anchors.

A letter that is its own small cap is substituted by a .sc copy of itself, so that smcp and c2sc change the glyph, as Shaperglot expects.

A Cyrillic font thus only needs .sc glyphs for а б е р у ф to get Cyrillic small caps. Small caps are never taken from another script, so Latin small caps are not reused for Cyrillic letters.

Lowercase letters need an uppercase form to get a small cap, so IPA letters such as ɹ or ʎ keep their shape. Greek is not supported yet.

The substitutions of each script are written as separate lookups: Latin applies to the DFLT and latn scripts, Cyrillic to cyrl. A glyph that the ccmp feature substitutes for a letter of another script (i for the Cyrillic і) thus takes the small cap of the script of the text.

Anchors for accented small caps

bdf2ufo assumes no anchors for small caps: a small cap only has the anchors that custom_anchors gives it, keyed by character or by glyph name. A letter that is its own small cap, such as ø, keeps its own anchors, and so does its .sc copy. Accented small caps are placed on these anchors, so a small cap needs the anchors that its accents attach to:

custom_anchors:
  "ᴀ": # Small capital a
    "top": [2, 5]
    "bottom": [2, -1]
    "ogonek": [3, 0]
  "x.sc": # Small capital x
    "top": [2, 5]
    "bottom": [2, -1]

The same anchors also position combining marks typed after a small cap.

bdf2ufo warns about every small cap that lacks an anchor that its capital has, naming the missing anchors:

uni025B.sc has no 'bottom', 'ogonek', 'top' anchor, which uni0190 has

An accented small cap whose base small cap lacks the anchor of one of its accents is not built, and bdf2ufo warns about it:

uni1E13.sc could be built with a 'bottom' anchor on uni1D05

Run bdf2ufo with -v to see in the build log what else is missing, for instance:

Small caps (cyrl) left out, 6 of 31 letters have no small cap: а б е р у ф
U+0431 has no small cap, uni0431.sc could be added
uni0451.sc could be built with a small cap of uni0415

Axes overview

Tag Name Small Large
wght Weight drawing drawing
wdth Width drawing drawing
ital Italic drawing drawing
ROND Roundness drawing drawing
BLED Bleed drawing drawing
JITT Jitter drawing drawing

Getting Started

1. Convert your source font (if needed)

If your font is in .ttf or .otf, convert it to .bdf using otf2bdf:

2. Set up your environment

Make sure you have:

  • Python
  • pip

Install dependencies:

pip install -r requirements.txt

3. Prepare your project

  • Create an empty directory for your .ufo masters
  • Review the example config: sources/PressStart2P/PressStart2P-build-config.yaml

4. Run bdf2ufo

View CLI usage:

python -m scripts.bdf2ufo.cli

bdf2ufo only prints warnings and errors. Add -v (--verbose) to log the progress of the conversion, including which small caps could be added.

5. Build your fonts

Create a config.yaml in your masters directory:

sources:
  - [font-name].designspace
autohintTTF: false
flattenComponents: false

Both options matter for pixel fonts:

  • autohintTTF: false keeps ttfautohint away from the static fonts. gftools then adds a gasp table and a prep program with dropout control instead, and the outlines stay on the pixel grid.
  • flattenComponents: false keeps the components of static fonts as bdf2ufo wrote them. If gftools builder flattens them, they lose the setting that turns off grid rounding, and hinted rendering shows empty pixel rows and columns.

See sources/config.yaml for an example.

Then compile using:

gftools builder [masters-path]/config.yaml

Fonts using bdf2ufo

Additional Resources

About

Converts .bdf pixel fonts into .ufo sources, enabling the creation of both static and variable vector fonts.

Topics

Resources

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages