Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

imagine.strokefont

import imagine.strokefont

imagine lifts part of this module out to its own top level; each name below is shown with the path that reaches it. Anything still spelled imagine.strokefont.* needs import imagine.strokefont.

StrokeFont: the font built into the module, defined as stroke geometry rather than glyph outlines.

It exists so that text can be drawn with no font file present at all. Because a glyph is a path rather than a filled shape, it scales to any size and takes a weight without needing a separate face per weight.

Constants

EM

imagine.strokefont.EM: number = 20

The em square’s height in design units. A font asked for 20 pixels draws its em at 20 pixels, so scale is simply size / EM.

CAP_HEIGHT

imagine.strokefont.CAP_HEIGHT: number = 14

The height of a capital letter.

X_HEIGHT

imagine.strokefont.X_HEIGHT: number = 10

The height of a lowercase letter with no ascender.

ASCENDER

imagine.strokefont.ASCENDER: number = 15

How far the tallest glyphs rise above the baseline.

DESCENDER

imagine.strokefont.DESCENDER: number

How far descenders fall below the baseline, as a negative number.

WEIGHT

imagine.strokefont.WEIGHT: number

The default stroke width in design units, a little under a tenth of the em, which is the usual weight for a regular sans-serif.

GLYPHS

imagine.strokefont.GLYPHS = {...}

Every glyph, keyed by character.

advance is how far the pen moves after drawing, in design units. strokes is a list of polylines.

NOTDEF

imagine.strokefont.NOTDEF = {...}

What an unmapped character draws: an empty box, the same convention a font uses for a glyph it does not have.

Classes

StrokeFont

class imagine.StrokeFont

The built-in font: a sans-serif drawn from centre-line strokes rather than loaded from a file.

imagine deliberately ships no font file, so [[imagine.Font.system]] and [[imagine.Font.sans]] both depend on what happens to be installed. This one is always there. It is defined as geometry in [[imagine.strokefont]], drawn through the same anti-aliased rasterizer everything else uses, and therefore scales cleanly to any size and takes a weight as a parameter.

import imagine { Image, StrokeFont }

Image(300, 80, 'white')
  .text(16, 22, 'Always available', StrokeFont(28), '#0f172a')
  .save('label.png')

It has the same interface as [[imagine.Font]], so anywhere a font is accepted this can be used instead.

What it is for

Labels, chart axes, watermarks, diagrams, placeholder text, and any output that has to work on a machine with no fonts installed. The look is geometric and single-weight, closer to a technical drawing than to a typeface, because that is what centre-line strokes give you honestly.

It is not a substitute for real typography. For body text, a headline, or anything where the shapes matter, load an actual font with [[imagine.Font.load]].

Coverage

Printable ASCII, from space through ~. Anything else draws the empty box a font uses for a glyph it does not have, so text in another script comes out visibly missing rather than silently blank.

  • printable — has a @to_string(), so echo and print() show something useful

Constructor

imagine.StrokeFont(size: ?number, weight: ?number)

Creates the built-in font at a size.

Parameters

  • size (?number) — The size in pixels - Default: 16.
  • weight (?number) — The stroke width, as a fraction of the size - Default: 0.085, a regular weight. Around 0.13 reads as bold.

StrokeFont.size()

imagine.StrokeFont.size(pixels) -> StrokeFont

Returns the same font at a different size.

Parameters

  • pixels (number)

Returns StrokeFont

StrokeFont.weight()

imagine.StrokeFont.weight(weight) -> StrokeFont

Returns the same font at a different stroke weight.

Parameters

  • weight (number) — A fraction of the size. 0.085 is regular, 0.13 reads as bold, 0.05 as light.

Returns StrokeFont

StrokeFont.pixel_size()

imagine.StrokeFont.pixel_size() -> number

The size in pixels this font draws at.

Returns number

StrokeFont.name()

imagine.StrokeFont.name() -> string

The font’s name.

Returns string

StrokeFont.source()

imagine.StrokeFont.source() -> string

Where this font came from.

Returns string

StrokeFont.has_glyph()

imagine.StrokeFont.has_glyph(character) -> bool

true when this font has a glyph for a character, which for the built-in font means printable ASCII.

Parameters

  • character (string)

Returns bool

StrokeFont.metrics()

imagine.StrokeFont.metrics() -> dict

The font’s vertical metrics at its current size, in pixels.

The dictionary holds name, ascent, descent (negative), line_gap and line_height, the same shape [[imagine.Font]] reports. The em is the size, so single-spaced lines sit exactly size pixels apart.

Returns dict

StrokeFont.wrap()

imagine.StrokeFont.wrap(text, width: number, options) -> string

Breaks a string into lines that fit within a width, returning the text with newlines inserted.

Parameters

  • text (string)
  • width (number) — The maximum line width in pixels.
  • options (?dict) — tracking.

Returns string

StrokeFont.measure()

imagine.StrokeFont.measure(text, options) -> dict

Measures a string without drawing it.

Returns width, height, baseline (the first line’s baseline, measured down from the top of the box) and lines.

Parameters

  • text (string)
  • options (?dict) — tracking, line_height, align.

Returns dict

StrokeFont.render()

imagine.StrokeFont.render(text, options) -> dict

Rasterizes a string into an 8-bit coverage mask.

Returns coverage, width, height and baseline, the same shape [[imagine.Font]] returns, which is what lets both be handed to Image.text() interchangeably.

Parameters

  • text (string)
  • options (?dict) — tracking, line_height, align.

Returns dict

StrokeFont.to_string()

imagine.StrokeFont.to_string()

2026, Richard Ore and Zuri contributors