wolfhece.opengl.glyph_atlas =========================== .. py:module:: wolfhece.opengl.glyph_atlas .. autoapi-nested-parse:: 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 --------------- .. py:data:: _HAS_PIL :value: True .. py:data:: _HAS_SCIPY :value: True .. py:data:: _DEFAULT_CHARSET :type: list[str] .. py:class:: GlyphMetrics 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). .. attribute:: char The character. .. attribute:: uv_x Left U coordinate in the atlas (0..1). .. attribute:: uv_y Top V coordinate in the atlas (0..1). .. attribute:: uv_w U extent of the cell. .. attribute:: uv_h V extent of the cell. .. attribute:: offset_x X offset from cursor to quad left edge (normalised). .. attribute:: offset_y Y offset from baseline to quad top in font coords (negative = above baseline). .. attribute:: quad_w Total quad width including SDF padding (normalised). .. attribute:: quad_h Total quad height including SDF padding (normalised). .. attribute:: advance Horizontal advance to the next character (normalised). .. py:attribute:: char :type: str :value: '' .. py:attribute:: uv_x :type: float :value: 0.0 .. py:attribute:: uv_y :type: float :value: 0.0 .. py:attribute:: uv_w :type: float :value: 0.0 .. py:attribute:: uv_h :type: float :value: 0.0 .. py:attribute:: offset_x :type: float :value: 0.0 .. py:attribute:: offset_y :type: float :value: 0.0 .. py:attribute:: quad_w :type: float :value: 0.0 .. py:attribute:: quad_h :type: float :value: 0.0 .. py:attribute:: advance :type: float :value: 0.0 .. py:class:: GlyphAtlas(font_name: str = 'arial.ttf', charset: list[str] | None = None) 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. :param font_name: TrueType font file name (resolved via :func:`wolfhece.textpillow.load_font`). :param charset: List of characters to include. Defaults to ASCII printable + common accented latin characters. .. py:attribute:: RENDER_SIZE :type: int :value: 64 .. py:attribute:: SDF_SPREAD :type: float :value: 8.0 .. py:attribute:: PAD :type: int :value: 12 .. py:attribute:: ATLAS_MAX_WIDTH :type: int :value: 1024 .. py:attribute:: _cache :type: dict[str, GlyphAtlas] .. py:attribute:: font_name :value: 'arial.ttf' .. py:attribute:: _charset .. py:attribute:: _metrics :type: dict[str, GlyphMetrics] .. py:attribute:: _texture_id :type: int | None :value: None .. py:attribute:: _atlas_width :type: int :value: 0 .. py:attribute:: _atlas_height :type: int :value: 0 .. py:attribute:: _atlas_data :type: numpy.ndarray | None :value: None .. py:attribute:: _line_height :type: float :value: 1.0 .. py:attribute:: _ascender :type: float :value: 0.8 .. py:attribute:: _descender :type: float :value: 0.2 .. py:method:: get(font_name: str = 'arial.ttf') -> GlyphAtlas :classmethod: Return a cached atlas for *font_name*, creating it if needed. .. py:method:: clear_cache() :classmethod: Destroy all cached atlases and free GPU textures. .. py:method:: _build() Render all glyphs, compute SDF, shelf-pack into atlas. .. py:method:: _compute_sdf(bitmap: numpy.ndarray, spread: float) -> numpy.ndarray :staticmethod: 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. .. py:method:: upload() Upload atlas data as a single-channel ``GL_R8`` OpenGL texture. .. py:method:: bind(unit: int = 0) Bind atlas texture to the given texture unit. .. py:method:: destroy() Free GPU texture memory. .. py:method:: get_metrics(char: str) -> GlyphMetrics | None Return metrics for *char*, or ``None`` if absent from the atlas. .. py:property:: metrics :type: dict[str, GlyphMetrics] Full metrics dictionary (read-only view). .. py:property:: line_height :type: float Line height relative to one em. .. py:property:: ascender :type: float Ascender relative to one em. .. py:property:: descender :type: float Descender relative to one em. .. py:property:: texture_id :type: int | None .. py:property:: atlas_size :type: tuple[int, int] ``(width, height)`` of the atlas texture in pixels. .. py:property:: atlas_data :type: numpy.ndarray | None Raw SDF atlas as a float32 array (for testing).