Skip to main content

Crate rhythm_gpui

Crate rhythm_gpui 

Source
Expand description

Vertical rhythm typography for gpui, ported from rhythm-sass.

gpui’s WrappedLine paint path follows the model in math: the ascent + descent box is centered in the line height and the baseline sits at (line_height - ascent - descent) / 2 + ascent. This crate resolves real font metrics through gpui’s text system, so baseline-anchored text lands on the rhythm grid without the manually measured baseline-ratio that the original Sass library required. Cap-anchored helpers instead align the capitals’ ink while preserving whole-row block geometry, and the ICF anchors do the same for the CJK ideographic character face.

§Feature flags

  • gpui (default) — the gpui integration: RhythmGrid, RhythmFont (with RhythmFontSpec cache keys), measured RhythmIcfAnchors, RhythmDropCap, the RhythmStyled extension trait, the rhythm_frame media container (with the RhythmFit pad/crop mode), and the configurable rhythm_overlay / RhythmOverlay debug grid.

  • Disable default features to build only the dependency-free rhythm math (Rhythm, FontRhythm, RhythmLineMetrics, RhythmBlockMetrics, DropCapRhythm, snap), usable from any renderer that centers ascent + descent inside the line height:

    rhythm-gpui = { version = "0.2", default-features = false }

§Example

use gpui::{div, font, px, prelude::*};
use rhythm_gpui::{RhythmGrid, RhythmStyled};

fn body(text_system: &gpui::TextSystem) -> impl IntoElement {
    let grid = RhythmGrid::new(px(8.));
    let para = grid.font(text_system, font("Georgia"), px(16.), 3);
    div()
        .rhythm_block(&para, 3, 1)
        .child("Aligned to the grid.")
}

The repository’s recipes example doubles as a recipe collection: a page scaffold, baseline- and cap-anchored openings, a drop cap with true wrap-around, fluid-width media padded or cropped to whole rhythm rows, and mixed fonts (sizes, families, scripts) sharing one alphabetic baseline.

§Custom renderers

Document renderers that shape text themselves and paint cached WrappedLines skip the element layer entirely: build RhythmLineMetrics from each shaped line’s reported ascent() / descent() — the maxima over its explicit font runs, which is how lines mixing bold, inline code, CJK, or emoji faces actually shape. Those are line metrics, not a guarantee that platform-selected fallback glyph ink stays inside the box. Lay blocks out with RhythmBlockMetrics and place every baseline with paint_origin_for. Under the gpui feature, the four values that stay inside a paint path’s Pixels chain have Pixels-typed _px mirrors. The direct_paint example is the complete non-virtualized shape/cache/paint recipe. A virtualizer additionally accumulates first_rows / middle_rows / last_rows in an i64 and rebases that row cursor near the viewport before converting visible positions to f32.

§Performance contract

  • Rhythm, FontRhythm, and line/block geometry are small Copy values. Their pure geometry and spacing methods are O(1), allocation-free (enforced by a counting-allocator test), and lock-free by construction, with hot methods #[inline] across the crate boundary.
  • gpui TextSystem access is confined to font/spec/drop-cap resolution and optional ICF measurement; geometry and spacing on stored values never query it.
  • The shaped-line adapter reads a line’s already-computed ascent/descent and never walks glyphs.
  • cargo bench --bench resolve tracks warm font resolution (gpui’s request cache hit plus metric reads). There is deliberately no ns-level CI threshold: pure f32 math varies below measurement noise, so the guarantees above are structural, not benchmarked.

§Platform scope

The math layer is renderer- and platform-agnostic, and the resolved-font path uses cross-platform gpui API. The default integration is compile-checked on Linux and Windows. The mixed-run maximum and glyph-fallback behaviors are verified against macOS/CoreText by the shaping integration suite; the DirectWrite and cosmic-text runtime behaviors are not yet verified and must not be assumed identical.

Structs§

DropCapRhythm
A drop cap solved by FontRhythm::drop_cap: the cap face’s metrics at the solved size plus the offset anchoring its baseline.
FontRhythm
Vertical metrics of one text style participating in the rhythm grid.
Rhythm
The vertical rhythm grid: a stack of rows, each size logical pixels tall.
RhythmBlockMetrics
A text block on the rhythm grid as pure geometry: one line’s metrics plus baseline or ink-top anchors, with both fragment geometry and the exact row arithmetic a virtualized renderer needs. new is the pure form of rhythm_block; ink_anchored pairs an ink opening with its whole-row close. Either mode spans a whole number of rhythm rows for any number of lines, so blocks and fragments compose without breaking the page rhythm.
RhythmDropCapgpui
A drop cap bound to the grid: the cap face at the size solved by FontRhythm::drop_cap, plus the inset anchoring its baseline. Apply with RhythmStyled::rhythm_drop_cap; for wrap-around text, measure the letter with shape_line (see drop_cap_paragraph in the recipes example).
RhythmFontgpui
A requested gpui font bound to the rhythm grid, with vertical metrics from the font gpui actually resolved. When the requested family is unavailable, that may be a fallback font; see Self::resolve.
RhythmFontSpecgpui
The pre-resolve identity of a RhythmFont: the requested Font, size, line rhythms, and grid size as one hashable value — the cache key for caller-owned typography catalogs.
RhythmFramegpui
A container that fits fluid-width media — images, video, embeds, any content whose height follows its width instead of the rhythm — into a whole number of rhythm rows, so everything after it stays on the grid at any width.
RhythmGridgpui
The vertical rhythm grid in gpui units.
RhythmIcfAnchorgpui
A measured ideographic character-face anchor bound to the exact RhythmFont it was measured from.
RhythmLineMetrics
Vertical metrics of one shaped line on the rhythm grid.
RhythmOverlaygpui
A draw-rhythms debug overlay: every other grid row in one color. Place it as the last child of the container it should cover; it fills that container and ignores mouse events. An ordinary gpui container already uses relative positioning by default, so no extra .relative() call is needed, and this element does not alter the container’s position style.

Enums§

IcfMeasurementErrorgpui
Why an ideographic character-face measurement could not produce an anchor.
RhythmFitgpui
How a RhythmFrame reconciles its content’s natural height with whole rhythm rows.

Traits§

RhythmStyledgpui
Extension methods for applying rhythm fonts through gpui’s fluent style API.

Functions§

rhythm_framegpui
Create a RhythmFrame for content with a width / height ratio of ratio; add the content with .child().
rhythm_overlaygpui
Create a RhythmOverlay painting every other grid row in color — the rhythm-sass draw-rhythms() mixin. Add RhythmOverlay::phase for a renderer that scrolls by painting at an offset.
snap
Round value to the nearest multiple of step (e.g. 1.0 / scale_factor to snap a spacing to whole device pixels). The core functions never round, so baseline-anchored results stay exact; snap only final applied values.