Skip to content

The Bitmap Font (BMF) Format

The BMF font format is based on a group of glyphs drawn inside text files (much like ASCII art), and a set of JSON configuration files to set their parameters.

The Bitmap Font Builder tool can be used to convert BMF fonts into outline formats (such as OpenType).

This format was devised by Lasse Fister as part of the original Bitmap Font Builder package. This page is an attempt to document the format based on the builder's source code.

Font components

A font's directory structure is made out of three main parts:

  • the glyphs directory (glyphs/ by default)
  • font specification files, one per desired weight, in JSON format (FontName-Regular.json by default)
  • other option files inside the options/ directory

The BMF format is rather flexible in what it allows, so in this page we also indicate some sensible defaults. There are two good examples for understanding how a font is structured:

  • the font-skeleton repository, with a minimal set of options
  • the graphicoreBMFB font included in the Bitmap Font Builder, which uses advanced features such as kerning and ligatures.

Glyphs

Glyphs are in a folder called glyphs. Inside the folder, glyphs are stored in simple text files. For example, the capital A from the Graphicore font looks like this:

...........
........###
.......###.
......####.
.....##.##.
....##..##.
.. #######.
..##....##.
.##.....###
##.........
...........
...........

The options/glyphs.json file contains the list of characters and their respective files.

Options

The font's metadata, options and generation parameters are all stored in options files, which are specified according to the JSON format.

The recommended structure for options files would be:

  • a specifications file (Fontname-Regular.json), for font metadata and base features
  • an options file (options/options.json)
  • a list of characters and corresponding glyphs (options/glyphs.json)
  • a list of kerning pairs (options/kerning.json, optional)
  • a list of ligatures (options/ligatures.json, optional)

Multiple options files and inheritance

While all of the font's options could fit into one single option file, this would be somewhat clunky beyond the most basic uses, so BMF supports multiple option files, with an inheritance system that allows us to specify more than one file.

Options can inherit from one another, and the last defined JSON file takes priority. They must specify their ancestors in their root object like this:

{
    "inherit": ["glyphs.json", "kerning.json", "ligatures.json"]
}

This will load ligatures.json first and all its ancestors, then kerning.json and all its ancestors, and finally the glyphs.

If an option is already set, it will not be overwritten by the ancestors. Options are only set in the root element and in its direct children if these are dicts, there is no deeper copying.

Side bearing values

A glyph contains no side bearing values. That information is stored inside the features.distances table that you can find in options.

Available options and defaults

This is a work in progress effort to document all available fields and values, but not yet complete. In the meantime, the graphicoreBitmapFont included in the Bitmap Font Builder is a great example of how to use BMF options. The defaults dict in ./graphicoreBMFB/__init__.py has some comments and the default values.

Option sets:

  • font
    • fileName: "unnamed",
    • featureFile: A .fea file to be merged directly. Default: false
    • glyphFolder: Name of the folder where glyph files are contained. Default: "glyphs",
    • lineCount: Height of all glyphs. Glyphs with a different number of lines will be cropped or padded as needed. Default: 12
    • descent: Count of lines below the baseline. Default: 2
    • upos: Underline position from the baseline. Default: 3
    • uwidth: Underline height. Default: 1
    • filled: Character to use for filled pixels inside glyph files. Default: "#"
    • empty: Character to use for empty pixels inside glyph files. Default: "."
    • classRightIndicator: Default: u"@_1R",
    • classLeftIndicator: Default: u"@_2L"
  • metadata
  • generator
  • glyphs
  • features

TODO: incorporate below code into the list

{
    "metadata": {
        # postscript names, as used in fontforge
        "fontname": "unnamed-medium",
        "weight": "Medium",
        "fullname": "unnamed medium",
        "familyname": "unnamed",
        "copyright": "Copyright (c), put your notice here.",
        "version": "0",
        "more": {
            "English": {
                "Manufacturer": "unnamed",
                "Designer": "unnamed",
                "Designer URL": "http://unnamed",
                "Vendor URL": "http://unnamed",
                "License": "no text",
                "License URL": "http://unnamed",
                "Trademark": "",
                "Descriptor": "Built with graphicore Boolean Matrix Font Building and fontforge. http://graphicore.de",
            }
        }
    },
    "generator": {
        "unit": 125,                # one raster unit in em
        "offset": 5,                # the x and y offset of the final pixel shape
        "width": 115,               # the width (diameter) of the final pixel shape
        "em": 1000,                 # the fonts em height usually 1000 for postscript font and for truetyoe a power of 2, such as 2048
        "emDescent": 200,           # if set here the descent is not beeing calculated, thus givin some control over it
        "contextualShape": False,   # magical thing
        # a value biger than 0 will turn on contextualShapes for outside
        # corners. i.e. corners where otherwise nothing would have been drawn
        # the combination: offset > 0 and width < unit and itself
        # outsideCornerRadius = 0.5 fontforge has problems removing the
        # overlaps in some chars making outsideCornerRadius (width/2) -1 is the
        # best solution I know so far
        "outsideCornerRadius": 0,
        "insideCornerRadius": 0,

        "generatedFeatureFile": False,    # a .fea file that will be generated (and then merged)
        "generatedClassesFile": "classes.json",
        "generatedKerningFile": "kerning.json",
        "fileFormats": ['otf', 'sfd'],
        "ffGenerateFlags": ["opentype", "old-kern", "dummy-dsig"],
        "removeOverlap": True,
        "autoHint": True,   # an either good idea, but slow
        "invertOutside": False
    },

    "glyphs": {},    # dict of glyphsNames: glyphFiles.txt
    "features": {
        "kerningClasses": {},    # dict of "kerningclassname": ["list of space separated glyphnames a b c comma"]
        "distances": {},         # dict of "keringclassname": int(always ad on this side) #this is not the dist table
                                 # distances stores the left and right sidebearing of the characters in the kerning class
        "kern": [],              # list of ["rightEdgeKerningClass", "leftEdgeKerningKlass", int(distance)[, bool enum]]
        "liga": [],              # list of ligatures ["replace space separated like f f i", "by_a_single_glyph_like_f_f_i"]
        "dlig": [],
        # all features here are made for all the following languagesystems: pairs of cryptic 4 letter words ["script", "language"]
        # for real good international magic some work would be required
        "languagesystems": [["DFLT", "dflt"], ["latn", "dflt"]]
    }
}

List of default character mappings

TODO: Convert to Markdown table

A : aCap.txt
B : bCap.txt
C : cCap.txt
D : dCap.txt
E : eCap.txt
F : fCap.txt
G : gCap.txt
H : hCap.txt
I : iCap.txt
J : jCap.txt
K : kCap.txt
L : lCap.txt
M : mCap.txt
N : nCap.txt
O : oCap.txt
P : pCap.txt
Q : qCap.txt
R : rCap.txt
S : sCap.txt
T : tCap:.txt
U : uCap.txt
V : vCap.txt
W : wCap.txt
X : xCap.txt
Y : yCap.txt
Z : zCap.txt
-----
1.txt
2.txt
3.txt
4.txt
5.txt
6.txt
7.txt
8.txt
9.txt
0.txt
-----
interrogación        - ? : _questionmark.txt
exclamación          - ! : _exclamationmark.txt
paréntesis izquierdo - ( : _leftparenthesis.txt
paréntesis derecho   - ) : _rightparenthesis.txt
llave izquierda      - { : _leftcurlybracket.txt
llave derecha        - } : _rightcurlybracket.txt
corchete izquierdo   - [ : _leftsquarebracket.txt
corchete derecho     - ] : _rightsquarebracket.txt 
arroba               - @ : _commercialat.txt
dólar                - $ : _dollarsign.txt
euro                 - € : _euro.txt
almohadilla          - # : _numbersign.txt
et                   - & : _ampersand.txt
comillas             - " : _quotationmark.txt
asterisco            - * : _asterisk.txt
guion/menos          - - : _hyphenminus.txt
más                  - + : _plussign.txt
barra                - / : _solidus.txt
punto                - . : _fullstop.txt
coma                 - , : _comma.txt
dos puntos           - : : _colon.txt
punto y coma         - ; : _semicolon.txt
porcentaje           - % : _percentsign.txt