API Reference

Read, manipulate and write bitmap fonts in the Bitmap Distribution Format.

To get started, use bdflib.reader.read_bdf() to load a BDF file and create a bdflib.model.Font object, or just create one yourself from scratch.

Modify the font by tinkering with it directly, or by using the helpers in bdflib.effects and bdflib.glyph_combining. If you’re making a font intended for use with the X11 windowing system, check out the helpers in bdflib.xlfd.

When you’re done, you can use bdflib.writer.write_bdf() to write your font back out to a BDF file.

bdflib.model

Classes that represent a bitmap font, with its glyphs and metadata.

class bdflib.model.Font(name: bytes, ptSize: int, xdpi: int, ydpi: int)[source]

Bases: object

Represents the entire font and font-global properties.

Parameters:
  • name (bytes) – The human-readable name of this font, ASCII encoded.
  • ptSize (int) – The nominal size of this font in PostScript points (1/72 of an inch).
  • xdpi (int) – The horizontal resolution of this font in dots-per-inch.
  • ydpi (int) – The vertical resolution of this font in dots-per-inch.

Instances of this class can be used like dict instances. bytes keys refer to the font’s properties and are associated with bytes instances, while int keys refer to the code-points the font supports, and are associated with Glyph instances.

>>> myfont = Font(
...     b"My Font",
...     ptSize=12,
...     xdpi=96,
...     ydpi=96,
... )
>>> myfont.ptSize
12
>>> a_glyph = myfont.new_glyph_from_data(
...     "capital A",
...     codepoint=65,
... )
>>> a_glyph == myfont[65]
True

Note

Some properties (the name, point-size and resolutions) are required, and although they can be examined via the dict interface, they cannot be removed with the del statement.

add_comment(comment)[source]

Add one or more lines of text to the font’s comment field.

Parameters:comment (bytes) – Human-readable text to add to the comment, ASCII encoded. It may include newline characters.

The added text will begin on a new line.

codepoints()[source]

Returns the codepoints that this font has glyphs for.

These codepoints can be used with the regular dict syntax to retrieve the associated glyphs

Returns:Supported codepoints
Return type:iterable of Glyph
copy()[source]

Returns a deep copy of this font.

The new font, along with all of its properties and glyphs, may be modified without affecting this font.

Returns:A new, independent copy of this Font
Return type:Font
get_comments()[source]

Retrieve the lines of the font’s comment field.

Returns:The comment text, ASCII encoded.
Return type:list of bytes
glyphs = None

All the glyphs in this font, even the ones with no associated codepoint.

name = b''

The value of the FONT field in the BDF file

new_glyph_from_data(name, data=None, bbX=0, bbY=0, bbW=0, bbH=0, advance=0, codepoint=None)[source]

Add a new Glyph to this font.

This method’s arguments are passed to the Glyph constructor.

If you include the codepoint parameter, the codepoint will be included in the result of codepoints() and you will be able to look up the glyph by codepoint later. Otherwise, it will only be available via the glyphs property.

Returns:the newly-created Glyph
Return type:Glyph
Raises:GlyphExists – if an existing glyph is already associated with the requested codepoint.
property_names()[source]

Returns the names of this font’s properties.

These names can be used with the regular dict syntax to retrieve the associated value.

Returns:Property names
Return type:iterable of bytes
ptSize = None

The font’s nominal size in PostScript points (1/72 of an inch), the first value in the SIZE field in the BDF file

xdpi = None

The font’s horizontal resolution in dots-per-inch, the second value in the SIZE field in the BDF file

ydpi = None

The font’s vertical resolution in dots-per-inch, the third value in the SIZE field in the BDF file

class bdflib.model.Glyph(name, data=None, bbX=0, bbY=0, bbW=0, bbH=0, advance=0, codepoint=None)[source]

Bases: object

Represents a font glyph and associated properties.

Parameters:
  • name (bytes) – The name of this glyph, ASCII encoded.
  • data (None or iterable of int) – If provided, gives the initial bitmap for the glyph, see the data attribute below.
  • bbX (int) – The left-most edge of the glyph’s bounding box, in pixels.
  • bbY (int) – The bottom-most edge of the glyph’s bounding box, in pixels.
  • bbW (int) – The glyph’s bounding-box extends this many pixels right of bbX (must be >= 0). If data is provided, each integer should be at most this many bits wide.
  • bbH (int) – The glyph’s bounding-box extends this many pixels upward from bbY (must be >= 0). If data is provided, it should yield this many rows.
  • advance (int) – After drawing this glyph, the next glyph will be drawn this many pixels to the right.
  • codepoint (int) – The Unicode codepoint that this glyph represents.
advance

(int) How far to the right the next glyph should be drawn, in pixels.

data

(list of int) Glyph bitmap data.

Each item of the .data property is a int bbW bits wide, representing the pixels of a single row. the first item in .data is the lowest row in the glyph, so that list indices increase in the same direction as pixel coordinates.

>>> my_glyph = Glyph(
...     name=b"capital A",
...     data=[
...         0b10001,
...         0b11111,
...         0b10001,
...         0b01110,
...     ],
...     bbW=5,
...     bbH=4,
... )
>>> for row in reversed(my_glyph.data):
...     print("{:05b}".format(row))
01110
10001
11111
10001

If you want to get the actual coordinates of the glyph’s drawn pixels, look at the iter_pixels() method.

get_ascent()[source]

Returns the distance from the Y axis to the highest point of the glyph.

This is zero if no part of the glyph is above the Y axis.

Returns:The ascent of this glyph.
Return type:int
get_bounding_box()[source]

Returns the position and dimensions of the glyph’s bounding box.

Returns:The left, bottom, width and height of the bounding box, as passed to the constructor.
Return type:tuple of int, int, int, int
get_descent()[source]

Returns the distance from the Y axis to the lowest point of the glyph.

This is zero if no part of the glyph is below the Y axis.

Returns:The descent of this glyph.
Return type:int
iter_pixels()[source]

Yields the state of pixels within the bounding box.

This method returns an iterable of bbH rows, from the top of the glyph (large X values) to the bottom (small X values). Each row is an iterable of bbW booleans, from left to right. Each boolean is True if that pixel should be drawn, and otherwise False.

Alternatively, you can obtain the glyph data in BDF format with get_data(), or access the raw bitmap via the data property.

Returns:the state of each pixel
Return type:iterable of iterable of bool
merge_glyph(other, atX, atY)[source]

Draw another glyph onto this one at the given coordinates.

Parameters:
  • other (Glyph) – The other glyph to draw onto this one.
  • atX (int) – The other glyph’s origin will be placed at this X offset in this glyph.
  • atY (int) – The other glyph’s origin will be placed at this Y offset in this glyph.

This glyph’s bounding box will be stretch to include the area of the added glyph, but the advance will not be modified.

exception bdflib.model.GlyphExists[source]

Bases: Exception

Raised when creating a new glyph for a codepoint that already has one.

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

bdflib.reader

bdflib.reader.read_bdf(raw_iterable)[source]

Read a BDF-format font from the given source.

Parameters:raw_iterable (iterable of bytes) – Each item should be a single line of the BDF file, ASCII encoded.
Returns:the resulting font object
Return type:Font

If you want to read an actual file, make sure you use the ‘b’ flag so you get bytes instead of text:

font = bdflib.reader.read_bdf(open(path, 'rb'))

bdflib.writer

bdflib.writer.write_bdf(font, stream)[source]

Write a BDF-format font to the given stream.

Parameters:
  • font (Font) – The font to write to the given stream.
  • stream – The stream that will receive the font.

stream must be an object with at .write() method that takes a bytes. If you want to write to an actual file, make sure you use the ‘b’ flag:

bdflib.writer.write_bdf(font, open(path, 'wb'))

bdflib.effects

Automatically generate visual variants of a font.

bdflib.effects.embolden(font, maintain_spacing=True)[source]

Create a bold version of a font by widening each glyph.

Parameters:
  • font (Font) – The font to embolden.
  • maintain_spacing (bool) – If true, each glyph’s advance width will be incremented, because a wider glyph needs more room.
Returns:

A copy of font, with each glyph emboldened.

Return type:

Font

To embolden a glyph, it is drawn over itself one pixel to the right, making each vertical stroke one pixel wider.

bdflib.effects.merge(base, custom)[source]

Create a new font by choosing glyphs from two other fonts.

Parameters:
  • base (Font) – The lower-priority font.
  • custom (Font) – The higher-priority font.
Returns:

A font where each glyph comes from base or custom.

For any given codepoint, the resulting font will use the corresponding glyph from custom if there is one, falling back to the glyph from base. The new font’s properties and other metadata are all copied from custom.

bdflib.glyph_combining

Tools for building glyphs by combining other glyphs.

Unicode has a lot of “pre-combined” code-points that are the combination of a normal code-point and a combining code-point, like how U+014D LATIN SMALL LETTER O WITH MACRON is the combination of U+006F LATIN SMALL LETTER O with U+0304 COMBINING MACRON. Given glyphs for their individual components, glyphs for pre-combined code-points can be automatically generated.

An example of using this module to generate pre-combined glyphs:

decompositions = build_unicode_decompositions()
filler = FontFiller(myfont, decompositions)
filler.add_decomposable_glyphs_to_font()
class bdflib.glyph_combining.FontFiller(font, decompositions)[source]

Bases: object

Build pre-combined glyphs from available component glyphs.

Parameters:
  • font (Font) – Any pre-combined glyphs will be added to this font.
  • decompositions – A dict mapping pre-combined characters to their components, as returned by build_unicode_decompositions().

Call add_decomposable_glyphs_to_font() on an instance of this class to add as many pre-combined glyphs as possible.

missing_chars

(collections.Counter) After calling add_decomposable_glyphs_to_font(), this attribute will record characters that could be used in combining sequences, but were missing from the input font. Adding the character with the highest count to the font will give you the biggest increase in Unicode coverage.

unknown_classes

(collections.Counter) After caling add_decomposable_glyphs_to_font(), this attribute will record Unicode combining classes included in the decompositions paramater that bdflib does not yet support. If bdflib were extended to support these Unicode combining classes, we might be able to use them to create new glyphs.

add_decomposable_glyphs_to_font()[source]

Adds all the glyphs that can be built to the given font.

This calls add_glyph_to_font() for each key in the decompositions passed to the class constructor.

add_glyph_to_font(char)[source]

Add the glyph representing char to the given font, if it can be built.

Parameters:char (unicode) – A single-codepoint Unicode string, whose glyph should be generated (if possible) and added to the font passed to the class constructor.
Returns:True if the font now contains a glyph for that character, False otherwise.

This method may return True if a glyph was generated, or if the font already contained the required glyph.

This method may return False if:

  • the decompositions passed to the class constructor do not include any components for char
  • the font passed to the class constructor is missing glyphs for one or more of char’s components, and they could not be generated
  • one of char’s components uses a combining class this code doesn’t understand
bdflib.glyph_combining.build_unicode_decompositions()[source]

Returns a dictionary mapping unicode characters to their components.

Returns:a mapping from pre-combined characters to their components.
Return type:dict mapping unicode to list of tuple of unicode, int

Each key in the resulting dict is a single-character Unicode string, and each value is a list of single-character Unicode strings and their combining classes, the components of the key. For example, one of the items in the result should be:

u"\N{LATIN SMALL LETTER O WITH MACRON}": [
        (u"o", 0),
        (u"\N{COMBINING MACRON}", 230),
]

(where 0 indicates a regular base character, and 230 means the glyph is drawn above the base glyph. See https://www.unicode.org/reports/tr44/#Canonical_Combining_Class_Values for details.)

This function obtains information about combining characters from Python’s unicodedata standard library module. It also properly handles “soft-dotted” characters “i” and “j” where pre-combined glyphs should be built from the dotless versions of those characters.

bdflib.xlfd

Check fonts against the X Logical Font Descriptor conventions.

Fonts in the BDF format can be used for all kinds of things, but commonly they are used with the traditional X11 font APIs, built around X Logical Font Descriptors, which require certain custom properties be set.

To check a BDF font against the XLFD conventions, use validate(), which returns a (hopefully empty) list of problems, represented as subclasses of ValidationError.

If the font is missing properties that can be automatically calculated, fix() will update the font as required.

For more information about these issues, see the official X Logical Font Description Conventions specification.

Helpful constants

Names for XLFD properties:

bdflib.xlfd.FOUNDRY

The organisation responsible for making the font, a namespace for FAMILY_NAME

bdflib.xlfd.FAMILY_NAME

The human-readable name of the font, like “Times New” or “Helvetica”

bdflib.xlfd.WEIGHT_NAME

The human-readable name of the font’s weight, like “Bold” or “Thin”

bdflib.xlfd.SLANT

A code describing the slant style of the font, one of the values in SLANT_VALUES

bdflib.xlfd.SETWIDTH_NAME

The human-reaadable name of the font’s width, like “Expanded” or “Ultracondensed”

bdflib.xlfd.ADD_STYLE_NAME

A human-readable name that further distinguishes this font from other similar fonts; an “additional style” if you will, like “Sans Serif” or “Outline”

bdflib.xlfd.PIXEL_SIZE

The vertical space required for a line of type, in pixels, usually (but not always) the sum of FONT_ASCENT and FONT_DESCENT

bdflib.xlfd.POINT_SIZE

The vertical space required for a line of type, in deci-points

bdflib.xlfd.RESOLUTION_X

The horizontal output resolution this font is intended for, in dots-per-inch

bdflib.xlfd.RESOLUTION_Y

The horizontal output resolution this font is intended for, in dots-per-inch

bdflib.xlfd.SPACING

A code describing the spacing of this font, one of the values in SPACING_VALUES below

bdflib.xlfd.AVERAGE_WIDTH

The average width of all the characters in this font, in deci-pixels.

bdflib.xlfd.CHARSET_REGISTRY

The organisation responsible for defining the character set encoding used by this font, a namespace for CHARSET_ENCODING

bdflib.xlfd.CHARSET_ENCODING

The identifier for the character set encoding used by this font

bdflib.xlfd.FONT_ASCENT

The maxium height above the baseline that any glyph in this font touches, in pixels

bdflib.xlfd.FONT_DESCENT

The maxium depth below the baseline that any glyph in this font touches, in pixels

bdflib.xlfd.DEFAULT_CHAR

If the software using this font wants to draw a glyph that the font does not contain, the glyph with this encoding will be drawn instead

Values for the SLANT property:

bdflib.xlfd.SLANT_ROMAN

This font is drawn with upright strokes

bdflib.xlfd.SLANT_ITALIC

This font is drawn leaning forward, often with curves or flourishes

bdflib.xlfd.SLANT_OBLIQUE

This font is the Roman variant, tilted forward

bdflib.xlfd.SLANT_REVERSE_ITALIC

This font is drawn leaning backward, often with curves or flourishes

bdflib.xlfd.SLANT_REVERSE_OBLIQUE

This font is the Roman variant, tilted backward

bdflib.xlfd.SLANT_OTHER

This font has a tilt that’s not any of the above

bdflib.xlfd.SLANT_VALUES

The set of valid SLANT values:

Values for the SPACING property:

bdflib.xlfd.SPACING_PROPORTIONAL

Each glyph in this font takes space proportional to its natural width, so a character like “i” is narrow while “m” is wide

bdflib.xlfd.SPACING_MONOSPACED

Each glyph in this font takes exactly the same space, regardless of its natural width

bdflib.xlfd.SPACING_CHARCELL

Like SPACING_MONOSPACED, but in addition, no part of any glyph sticks out of the space allocated to it

bdflib.xlfd.SPACING_VALUES

The set of valid SPACING values:

Classes and functions

exception bdflib.xlfd.Contradiction(name: bytes, prop_value: Union[bytes, int], xlfd_value: Union[bytes, int])[source]

Bases: bdflib.xlfd.ValidationError

A value in the XLFD name contradicts a BDF property value

name = None

The property name with conflicting values

prop_value = None

The value associated with the BDF property

xlfd_value = None

The value stored in the XLFD name

exception bdflib.xlfd.ExpectedBytestring(name: bytes, value: int)[source]

Bases: bdflib.xlfd.ValidationError

The value of a property should be a bytestring

name = None

The name of the property whose value should be a bytestring

value = None

The value that is not a bytestring

exception bdflib.xlfd.ExpectedEnumeratedValue(name: bytes, value: Union[bytes, int], expected: Set[bytes])[source]

Bases: bdflib.xlfd.ValidationError

The value of a property should be one of a fixed set of values

expected = None

The set of possible values

name = None

The name of the property with an invalid value

value = None

The value that is not in the expected set

exception bdflib.xlfd.ExpectedInteger(name: bytes, value: bytes)[source]

Bases: bdflib.xlfd.ValidationError

The value of a property should be an integer

name = None

The name of the property whose value should be an integer

value = None

The value that is not an integer

exception bdflib.xlfd.MissingProperty[source]

Bases: bdflib.xlfd.ValidationError

The font is missing a property required by the XLFD conventions

exception bdflib.xlfd.NotAnXlfd[source]

Bases: bdflib.xlfd.ValidationError

The font’s name is not a valid XLFD string

exception bdflib.xlfd.ValidationError[source]

Bases: ValueError

Superclass of all problems detected by validate()

bdflib.xlfd.fix(font: bdflib.model.Font) → None[source]

Add missing XLFD properties to a font, with default or calculated values

Any properties already present will be preserved, even if their values seem to be incorrect.

bdflib.xlfd.validate(font: bdflib.model.Font) → List[bdflib.xlfd.ValidationError][source]

Validate a font against the XLFD conventions

This function checks for missing, required properties, properties with the wrong type, the syntax of the font’s XLFD name and conflicts between the XLFD name and its properties.

All problems detected (not just the first) are returned in a list.