class

Egui::Backend::AtlasFonts

Inherits Egui::Fonts < Reference < Object

The Egui::Fonts implementation shared by the font backends: CrystalFonts (crystalfonts.cr, primary) and FreetypeFonts (freetype.cr, C-FFI dev accelerator). One RGBA atlas + glyph cache, one walk (fractional advances + kerning) for both measure and draw; a backend implements glyph production and metrics.

Constants

KERN_CACHE_MAX = 65536

Memoized kerning in front of the backend FFI: kerning is a constant per (glyph pair, size) of the immutable font file, so no invalidation is ever needed. Real text touches a few hundred distinct pairs; the cap exists only as a hard bound (a sythetic sweep over every glyph pair of a CJK font would be huge) — clear-on-overflow like the measure cache.

MEASURE_CACHE_MAX = 8192
MEASURE_CACHE_TEXT_MAX = 64

Memoized measure for STATIC text (labels, captions, button texts — strings that return frame after frame unchanged). Anything the user types into (TextEdit/TextArea/…) keeps calling #measure: its content churns per keystroke, and dead entries would only pollute the map.

The same (text, physical size, tracking) always walks to the same width — advances and kerning are per-glyph constants of the font — so no invalidation is ever needed for correctness: every width input (draw size = size * scale, letter_spacing) rides the key. Memory is bounded by TWO guards: a LENGTH filter (unbounded distinct strings — buffer lines, caret prefixes — must never land here) and a COUNT cap with clear-on-overflow (every dropped entry rebuilds in one walk, cheaper than LRU bookkeeping on every hit).

Constructors

new(atlas : GlyphAtlas | Nil = nil)
Source

Instance methods

atlas

The atlas this stack bakes into: its OWN (default — specs, standalone tools) or a SHARED one owned by the backend registry (sokol.cr: one GPU texture for every stack the registry creates, so a font picker flipping through hundreds of families cannot exhaust the shim's atlas cap or VRAM).

Source
atlas_view_id
Source
clear_overflow_flag

Acknowledge an overflow WITHOUT touching the atlas: the registry already reset the SHARED atlas this stack bakes into — the epoch mismatch invalidates the glyph cache lazily in #glyph.

Source
debug_bitmap(ch : Char, size : Float64) : Nil

Rasterized coverage bitmap as text (debug/tests) — works for every backend: glyphs land in the shared atlas either way.

Source
flush

Upload dirty atlas regions to the GPU. Must run outside a pass.

Source
glyph(gid : Int32, size : Float64) : Glyph
Source
glyph_coverage(g : Glyph) : Bytes | Nil

Coverage bytes of a baked glyph's atlas slot (specs/tests); nil for blank glyphs.

Source
glyph_index(codepoint : Int32) : Int32
Source
kern_px(prev_gid : Int32, gid : Int32, size : Float64) : Float64

Kerning between two glyph ids (px) at the given size.

Source
letter_spacing

Extra spacing between letters (px) — added BETWEEN glyphs only, never after the last one, so measure widths stay exact. Backends whose glyph placement reads tighter than their reference open this up (live-tunable: fontpreview exposes it).

Source
letter_spacing=(letter_spacing : Float64)

Extra spacing between letters (px) — added BETWEEN glyphs only, never after the last one, so measure widths stay exact. Backends whose glyph placement reads tighter than their reference open this up (live-tunable: fontpreview exposes it).

Source
loaded?
Source
measure(text : String, size : Float64) : Egui::Vec2
Source
measure_cached(text : String, size : Float64) : Egui::Vec2

Memoized measure for STATIC text (label-like widgets — see AtlasFonts#measure_cached for the cache design). The base class and every non-AtlasFonts backend just measure; only the real font stacks gain a cache, so headless specs see identical behavior either way.

Source
metrics_at(size : Float64) : Tuple(Float64, Float64)

{ascender, descender} in px for a size (descender negative).

Source
needs_reset?

Did a frame's baking overflow the atlas? (Registry-level reset in sokol.cr polls this across every live stack.)

Source
reset_if_full

Wipe the atlas and the glyph cache when a frame overflowed it (fontstash's texture reset): everything visible re-bakes on demand, so dropped letters come back instead of staying blank forever (dropped glyphs are cached as blanks otherwise). Call before flush, outside a render pass; a true result means the caller should re-touch this frame's text commands. For stacks on a SHARED atlas the registry resets the atlas itself and calls #clear_overflow_flag instead (one wipe covers every stack; the epoch bump invalidates the caches lazily in #glyph).

Source
scale

Pixels per point the draw path rasterizes at (set by the backend each frame; 1.0 headless). Hinted advances are per-ppem, NOT linear in size — SF Mono advances 7.0px at 14pt but 15px at the retina draw size (28px) — so measure must walk the run at the same physical size the glyphs will be drawn at and fold the width back to points, or every widget lays out on advances the painter then exceeds (in a terminal grid the cursor visibly drifts off the text).

Source
scale=(scale : Float64)

Pixels per point the draw path rasterizes at (set by the backend each frame; 1.0 headless). Hinted advances are per-ppem, NOT linear in size — SF Mono advances 7.0px at 14pt but 15px at the retina draw size (28px) — so measure must walk the run at the same physical size the glyphs will be drawn at and fold the width back to points, or every widget lays out on advances the painter then exceeds (in a terminal grid the cursor visibly drifts off the text).

Source
touch(cmd : Egui::TextCmd, scale : Float64 = 1.0) : Nil

Rasterize every glyph a text command needs. Called before the render pass: sg_update_image is illegal inside a pass, so the atlas must be uploaded first (see flush). scale = framebuffer pixels per point — glyphs are rasterized at the physical size (crisp on retina); 1.0 for callers without a window (specs, fontpreview tabs).

Source
walk(text : String, size : Float64, & : Float64, Glyph -> Nil) : Float64

Walk the run exactly like the draw path does (fractional advances + kerning), yielding (pen_x, glyph) per char. Returns the final pen.

Source