Skip to main content

Crate lattice_media

Crate lattice_media 

Source
Expand description

Inline media: resolving an image block’s pixels off the UI thread, so the renderer only ever paints decoded pixels or a placeholder (IM.4).

Design: docs/dev/architecture/inline-media.md §5.

§The rule this code exists to serve

Decode never happens on the UI thread. gpui::img() will happily take a path and load it, which means file I/O and PNG decode inside the render pass — precisely the forbidden pattern (paramount goal #1). So the peer never gets a path to draw; it gets pixels that were produced elsewhere, or it gets nothing and paints the placeholder.

That guarantee lives at the CALL SITE, not here. MediaCache::get is async and goes through spawn_blocking, which is the ergonomic path; but decode is public and synchronous, and nothing in this crate’s dependency graph prevents a renderer calling it from inside a paint. The rule is enforced by the caller and by the tests that assert frame time is unaffected — stating otherwise would be a false comfort.

§Why a crate, and why not inside the GPUI peer

Only GPUI draws images today. This is not in lattice-ui-gpui because terminal graphics (kitty / sixel / iTerm2) is deliberately not foreclosed — see docs/dev/architecture/inline-media.md §9 — and the day the TUI grows an image path, both peers need this code. A thing both peers need can live in neither of them.

It is not in lattice-cells either: that crate has one dependency and ten dependents, and none of lattice-completion, lattice-listing or lattice-diff should be compiling PNG decoders.

§Size before pixels

probe reads only enough of the file to learn its dimensions; decode reads and decodes the whole thing. They are separate because a block must be able to reserve the right amount of space before its pixels exist — otherwise the document reflows when an image finishes loading, which breaks the keystroke contract (“no pixel change to content the user did not edit”) on every scroll past it.

A header read is bounded and cheap; it still happens off-thread, because “cheap” and “on the UI thread” are different claims.

§The cache

Keyed by (path, mtime, target). mtime is what makes an edited image reappear rather than serving a stale decode forever, and target is in the key because the same file at two display scales is two different decodes.

Structs§

DecodedImage
Decoded, scaled pixels ready for a peer to upload.
MediaCache
A bounded decode cache.

Enums§

MediaError
Why a block has no pixels. Every variant is a placeholder plus alt text outcome, never a panic and never a stall.
PixelFormat
The byte layout a consumer needs.

Constants§

MAX_PIXELS
Refuse anything above ~64 megapixels.
MIN_BLOCK_LH
A block never draws thinner than this, however extreme its aspect ratio.

Functions§

block_geometry
How much space a block should take, given what it is and where it goes.
decode
Decode path and scale it to fit target (width, height in px), preserving aspect ratio and never scaling up.
fit_within
Scale src down to fit inside bounds, preserving aspect ratio. Returns src unchanged when it already fits — the never-upscale rule.
probe
A file’s natural size, from its header alone.