wolfhece.opengl.glyph_atlas

SDF glyph atlas for GPU text rendering.

Renders TrueType glyphs at high resolution via PIL, computes a Signed Distance Field (SDF), and packs them into a single-channel OpenGL texture atlas. The SDF allows resolution-independent rendering with clean glow/outline effects at any zoom level.

Usage:

atlas = GlyphAtlas.get("arial.ttf")   # cached singleton per font
atlas.bind(0)                          # bind to texture unit 0
m = atlas.get_metrics('A')             # query glyph layout info

Author: HECE - University of Liege, Pierre Archambeau Date: 2026

Copyright (c) 2026 University of Liege. All rights reserved.

Module Contents

wolfhece.opengl.glyph_atlas._HAS_PIL = True[source]
wolfhece.opengl.glyph_atlas._HAS_SCIPY = True[source]
wolfhece.opengl.glyph_atlas._DEFAULT_CHARSET: list[str][source]
class wolfhece.opengl.glyph_atlas.GlyphMetrics[source]

Layout metrics for a single glyph in the SDF atlas.

All spatial values are normalised so that 1.0 equals one em (i.e. the RENDER_SIZE used during atlas construction).

char[source]

The character.

uv_x[source]

Left U coordinate in the atlas (0..1).

uv_y[source]

Top V coordinate in the atlas (0..1).

uv_w[source]

U extent of the cell.

uv_h[source]

V extent of the cell.

offset_x[source]

X offset from cursor to quad left edge (normalised).

offset_y[source]

Y offset from baseline to quad top in font coords (negative = above baseline).

quad_w[source]

Total quad width including SDF padding (normalised).

quad_h[source]

Total quad height including SDF padding (normalised).

advance[source]

Horizontal advance to the next character (normalised).

char: str = ''[source]
uv_x: float = 0.0[source]
uv_y: float = 0.0[source]
uv_w: float = 0.0[source]
uv_h: float = 0.0[source]
offset_x: float = 0.0[source]
offset_y: float = 0.0[source]
quad_w: float = 0.0[source]
quad_h: float = 0.0[source]
advance: float = 0.0[source]
class wolfhece.opengl.glyph_atlas.GlyphAtlas(font_name: str = 'arial.ttf', charset: list[str] | None = None)[source]

SDF glyph atlas backed by a single-channel OpenGL texture.

Build once per font; the atlas is cached and reused for all rendering. The SDF encoding (0.5 = edge, >0.5 = inside, <0.5 = outside) makes it trivial to render glow, outlines, and anti-aliased text at any scale from a single texture.

Parameters:
  • font_name – TrueType font file name (resolved via wolfhece.textpillow.load_font()).

  • charset – List of characters to include. Defaults to ASCII printable + common accented latin characters.

RENDER_SIZE: int = 64[source]
SDF_SPREAD: float = 8.0[source]
PAD: int = 12[source]
ATLAS_MAX_WIDTH: int = 1024[source]
_cache: dict[str, GlyphAtlas][source]
font_name = 'arial.ttf'[source]
_charset[source]
_metrics: dict[str, GlyphMetrics][source]
_texture_id: int | None = None[source]
_atlas_width: int = 0[source]
_atlas_height: int = 0[source]
_atlas_data: numpy.ndarray | None = None[source]
_line_height: float = 1.0[source]
_ascender: float = 0.8[source]
_descender: float = 0.2[source]
classmethod get(font_name: str = 'arial.ttf') GlyphAtlas[source]

Return a cached atlas for font_name, creating it if needed.

classmethod clear_cache()[source]

Destroy all cached atlases and free GPU textures.

_build()[source]

Render all glyphs, compute SDF, shelf-pack into atlas.

static _compute_sdf(bitmap: numpy.ndarray, spread: float) numpy.ndarray[source]

Compute SDF from a greyscale bitmap.

Returns array in [0, 1]: 0.5 = edge, >0.5 = inside, <0.5 = outside. Falls back to a simple ramp when scipy is not installed.

upload()[source]

Upload atlas data as a single-channel GL_R8 OpenGL texture.

bind(unit: int = 0)[source]

Bind atlas texture to the given texture unit.

destroy()[source]

Free GPU texture memory.

get_metrics(char: str) GlyphMetrics | None[source]

Return metrics for char, or None if absent from the atlas.

property metrics: dict[str, GlyphMetrics][source]

Full metrics dictionary (read-only view).

property line_height: float[source]

Line height relative to one em.

property ascender: float[source]

Ascender relative to one em.

property descender: float[source]

Descender relative to one em.

property texture_id: int | None[source]
property atlas_size: tuple[int, int][source]

(width, height) of the atlas texture in pixels.

property atlas_data: numpy.ndarray | None[source]

Raw SDF atlas as a float32 array (for testing).