Embedder primitives: placed-child clipping, offscreen RGBA readback, standalone text measurement
Some checks failed
CI / build + test (push) Has been cancelled
CI / cargo audit (push) Has been cancelled

Three additions an embedder needs to drive ltk as the render backend for a retained, externally-owned widget tree, each kept general rather than tied to one consumer.
Stack placed-child clipping. `Stack::push_placed_clipped(e, rect, clip)` places a child at an exact rect like `push_placed` but clips its subtree's drawing to `clip` (in the Stack's coordinate space) — Android's clipChildren: content that overflows, such as a scrolled list row reaching above the list or an inner card past a rounded bubble, is not painted. The Stack child tuple grows an 8th `Option<Rect>` for the clip, and `layout_and_draw` brackets a clipped child with `set_clip_rects`/restore around the recursion. The clip is shifted by the Stack's own origin to match the placed rect (which `Stack::layout` already offsets), so a Stack laid out at a non-zero origin clips in the right place rather than off by that origin.
Offscreen RGBA readback. `Canvas::read_rgba_pixels(out)` reads any canvas into tightly packed straight-alpha RGBA8, top-left row first. Unlike `read_gles_rgba_pixels` it also serves the software backend, un-premultiplying its pixmap, so an offscreen software canvas (an embedder's scratch bitmap) can be read back into a straight-alpha buffer. `Canvas::is_software()` lets a caller branch on the backend — e.g. to honour a real path clip on software but only a bounding rect on GLES.
Standalone text measurement. `measure_text(text, size)`, re-exported at the crate root, measures one line with the default UI font and the system fallback chain, returning `(width, line_height)` in pixels without a live `Canvas` — for an embedder's measure pass that must produce the same metrics the renderer will later use. It is backed by `system_fonts::primary_handle()`, a process-wide cached handle for the primary UI font (the same default a canvas loads, with the bundled-font fallback), which widens `render::helpers::load_default_font_bytes` to `pub(crate)`.
This commit is contained in:
2026-06-24 22:42:50 +02:00
parent 8809313be1
commit fb3552e9f7
7 changed files with 129 additions and 14 deletions

View File

@@ -147,6 +147,20 @@ pub fn lookup( ch: char ) -> Option<Arc<Font>>
lookup_handle( ch ).map( |h| h.font )
}
/// The process-wide primary UI font — the same default a canvas loads — cached
/// for standalone text measurement (e.g. an embedded measure pass with no live
/// canvas). Falls back to the bundled font when no system font is found.
pub fn primary_handle() -> FontHandle
{
static PRIMARY: OnceLock<FontHandle> = OnceLock::new();
PRIMARY.get_or_init( ||
{
let bytes = crate::render::helpers::load_default_font_bytes();
let font = Font::from_bytes( bytes.as_slice(), FontSettings::default() ).expect( "primary font parses" );
FontHandle { font: Arc::new( font ), bytes: Arc::new( bytes ), face: 0 }
} ).clone()
}
/// Bytes-aware variant of [`lookup`]. Returns the full
/// [`FontHandle`] (fontdue handle + raw bytes + face index) so
/// callers that need to invoke a HarfBuzz-style shaper can do so