Skip to main content

RhythmFont

Struct RhythmFont 

Source
pub struct RhythmFont { /* private fields */ }
Available on crate feature gpui only.
Expand description

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.

§Lifecycle

A RhythmFont is an immutable resolved value. Self::resolve touches gpui’s TextSystem; optional ideographic-character-face measurement reads it separately through Self::measure_icf and returns a RhythmIcfAnchor without changing this value. Metric and spacing methods are pure geometry on the stored values, allocation-free and lock-free, while style application reuses the stored Font without querying the text system. Register each font family (TextSystem::add_fonts) before its first resolution: gpui caches failed lookups by Font, so adding a family later and clearing a caller-owned cache does not repair that miss in the same TextSystem. Resolution silently falls back otherwise. Re-resolve affected values when typography settings produce a new request key; nothing revalidates an existing value against the text system. The crate keeps no font cache of its own: gpui already caches Font → FontId and metrics, so a caller wanting to reuse resolved values owns that map, keyed by RhythmFontSpec, along with its invalidation.

Implementations§

Source§

impl RhythmFont

Source

pub fn resolve( text_system: &TextSystem, font: Font, font_size: Pixels, line_rhythms: u32, grid: RhythmGrid, ) -> Self

Resolve font’s metrics at font_size through gpui’s text system.

If gpui cannot load the requested font, its TextSystem::resolve_font silently tries the configured fallback stack. The returned value retains the requested Font configuration, while its metrics come from the resolved fallback; applying it through RhythmStyled::rhythm_font follows gpui’s same resolution policy. Check TextSystem::all_font_names before calling this method when using the exact family is a requirement.

Metrics come from the resolved primary font only — what an element that sets one text style paints with. A line that explicitly mixes fonts (bold/italic runs, inline code, an explicit CJK or emoji face) has one baseline placed from the maximum ascent and descent over its runs; shape it and place the result through RhythmLineMetrics so that shared baseline still lands on the grid. Glyph-level fallback is different: on the validated macOS/CoreText backend, substituted glyphs borrow the primary font’s baseline and do not enlarge the shaped line’s ascent/descent. That is a line-metrics contract, not proof that every fallback glyph’s typographic or raster ink stays inside the primary line box; other gpui text backends need their own native validation.

§Panics

Panics when the font weight is zero, negative, or non-finite, when font_size is zero, negative, or non-finite, or when line_rhythms is zero. Validation happens before the text system is queried.

Source

pub fn from_baseline_ratio( font: Font, font_size: Pixels, line_rhythms: u32, baseline_ratio: f32, grid: RhythmGrid, ) -> Self

Compatibility constructor for a Plumber/rhythm-sass baseline-ratio. Prefer Self::resolve; see FontRhythm::from_baseline_ratio.

§Panics

Panics when the font weight is zero, negative, or non-finite, when font_size is zero, negative, or non-finite, when line_rhythms is zero, or when baseline_ratio is not strictly between 0 and 1.

Source

pub fn measure_icf( &self, text_system: &TextSystem, probes: &str, ) -> Result<RhythmIcfAnchor, IcfMeasurementError>

Measure an ideographic character-face anchor from this resolved font.

The result owns a clone of this font together with the tallest ink over probes, which should be full-frame glyphs of the script being set ("字永語国" for han, "곽뻠한" for hangul). Bounds that do not straddle the alphabetic baseline are ignored because they cannot establish that full frame. Only the returned RhythmIcfAnchor exposes the infallible RhythmIcfAnchor::span and RhythmIcfAnchor::trim_top operations.

Measuring beats reading the font’s BASE table. BASE is absent from some faces (SimSong ships none), and where present its icft is a declaration the ink need not match: measured against their own tables, PingFang SC and Toppan Bunkyu Gothic agree within 0.003 em, but Apple SD Gothic Neo’s hangul overshoots its declared icft by 0.054 em. A measurement adapts to the face and the script; a table lookup does not.

Like a cap anchor, this anchors one ink envelope: glyphs that reach it land on the grid line and shorter ones sit below, exactly as Latin lowercase sits below a cap_top anchor. Kana are the case to know about — their dakuten ride above the han envelope by up to 0.058 em on the faces measured here, like Latin ascenders above cap height, though the overshoot belongs to the face and some versions show none — so include kana in probes when setting Japanese that must not exceed the line.

Measurement happens only at this boundary; spacing on a successful anchor stays pure geometry. Use the same TextSystem that resolved this font because its FontId is local to that text system. The base RhythmFont remains determined entirely by Self::spec and is safe to cache normally. Cache a measured anchor separately only when useful, keyed by both the spec and probes.

Availability follows gpui’s text backend. In gpui 0.2.2, CoreText and DirectWrite expose glyph ink bounds, while Linux returns advance-only placeholder bounds that produce IcfMeasurementError::NoUsableBounds. When every bounds query fails instead, this returns IcfMeasurementError::NoProbeBounds. If failures and rejected bounds are mixed, the returned-bounds distinction wins and the result is NoUsableBounds. Probe with glyphs the resolved face actually covers: CoreText and Linux report a missing glyph as absent, while DirectWrite substitutes .notdef, whose box can pass for ink.

Source

pub fn font(&self) -> &Font

The requested gpui font configuration applied by RhythmStyled::rhythm_font.

Source

pub const fn resolved_font_id(&self) -> Option<FontId>

The font identity gpui resolved the metrics from — the fallback font’s when the requested family was unavailable. None when the value was built without a text system (Self::from_baseline_ratio).

A FontId is an index into the resolving TextSystem: compare it with shaped-run font ids from the same system, but do not persist it or carry it across windows or font registrations — use Self::spec for durable request keys. “Did fallback happen” has no precise reverse lookup: TextSystem::get_font_for_id returns one cached font request for an id, not an authoritative platform-face identity, and can be ambiguous when several requests resolve to the same face. Check TextSystem::all_font_names before resolving when using the exact family is a requirement.

Source

pub fn spec(&self) -> Option<RhythmFontSpec>

The TextSystem resolution request that produced this font, as a hashable cache key. Returns None for values synthesized by Self::from_baseline_ratio, because their ratio-derived metrics cannot be reproduced by RhythmFontSpec::resolve.

Source

pub fn line_metrics(&self) -> RhythmLineMetrics

This font’s line placement as a RhythmLineMetrics — the same value a shaped line produces, so a direct-paint renderer places single-style text, empty lines, and mixed-run shaped lines through one code path.

Source

pub const fn grid(&self) -> RhythmGrid

The grid this font was resolved against.

Source

pub fn baseline_top(&self, n: i32) -> Pixels

Top spacing that lands the first baseline n rhythm units below the element’s padding edge (rhythm-sass baseline-top() / rhythm-bottom()).

Negative when n × grid size is smaller than baseline_above — meaningful as a margin, not as a padding.

Source

pub fn baseline_bottom(&self, n: i32) -> Pixels

Bottom spacing that puts the nth grid line below the last baseline at the element’s padding edge (rhythm-sass baseline-bottom() / rhythm-top()).

Negative when n × grid size is smaller than the baseline-to-bottom distance — meaningful as a margin, not as a padding.

Source

pub fn baseline_between(&self, below: &RhythmFont, n: i32) -> Pixels

Spacing from a block set in this font down to a following block set in below, so the two adjacent baselines are exactly n rhythm units apart (rhythm-sass baseline-between()).

gpui’s flex layout never collapses margins, so apply the result to exactly one side (or as a gap), unlike the CSS original. Negative results overlap the blocks when applied.

§Panics

Panics when below was resolved against a different grid size; its line height would no longer match the calculated spacing.

Source

pub fn cap_top(&self, n: i32) -> Option<Pixels>

Top spacing that lands the capitals’ ink top — not the baseline — on the nth grid line, for optically-aligned openings. Close the block with Self::cap_bottom, not Self::baseline_bottom; see FontRhythm::cap_top for the contract, or use Self::cap_span to get the pair in one call. None when the font has no usable cap height.

CJK faces usually resolve with a cap height — for their embedded Latin glyphs — so on ideographic text this returns Some while trimming to the wrong ink; use Self::measure_icf for CJK openings.

Source

pub fn cap_bottom(&self, n: i32) -> Option<Pixels>

Bottom spacing pairing Self::cap_top, returning the trimmed space so the block closes on whole rhythm rows; see FontRhythm::cap_bottom. None when the font has no usable cap height.

Source

pub fn cap_span(&self, top: i32, bottom: i32) -> Option<(Pixels, Pixels)>

The cap-anchored opening as one paired value: (cap_top(top), cap_bottom(bottom)). Taking the pair from a single call keeps the matching anchors together and reduces the chance of closing a cap opening with Self::baseline_bottom by mistake.

None when the font has no usable cap height. The baseline fallback is a design choice (the equivalent baseline count differs from top by the cap height), so pick it explicitly, e.g. with gpui’s .map():

div().map(|d| match heading.cap_span(4, 0) {
    Some((pt, pb)) => d.pt(pt).pb(pb),
    None => d.pt(heading.baseline_top(7)),
})
Source

pub fn drop_cap( &self, text_system: &TextSystem, font: Font, lines: u32, ) -> RhythmDropCap

Resolve font as a drop cap sunk lines lines deep into text set in this font — RhythmDropCap::resolve with the body slot filled in; see it for the solving contract.

§Panics

Panics when lines is zero or lines × line_rhythms overflows u32.

Source

pub const fn metrics(&self) -> &FontRhythm

Resolved vertical metrics in logical pixels.

These belong to the fallback font when gpui could not load the requested family; see Self::resolve.

Source

pub fn font_size(&self) -> Pixels

The font size the metrics were resolved at.

Source

pub fn line_height(&self) -> Pixels

The rhythm line height: line_rhythms × grid size.

Source

pub fn baseline_above(&self) -> Pixels

Distance from the top of the line box down to the baseline, as gpui will paint it. Useful for custom elements and debug overlays.

Source

pub fn baseline_below(&self) -> Pixels

Distance from the baseline down to the bottom of the line box, as gpui will paint it — the counterpart of Self::baseline_above.

Source

pub fn cap_trim_top(&self) -> Option<Pixels>

Invisible space above the cap height; subtract from a top spacing (or apply as a negative margin) for CSS text-box-trim-style optical alignment. None when the metrics source has no usable cap height, including values created with Self::from_baseline_ratio.

Source

pub fn x_trim_top(&self) -> Option<Pixels>

Like Self::cap_trim_top but trimming to the x-height. None when the metrics source has no usable x-height.

Trait Implementations§

Source§

impl Clone for RhythmFont

Source§

fn clone(&self) -> RhythmFont

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for RhythmFont

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more