pub struct RhythmFont { /* private fields */ }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
impl RhythmFont
Sourcepub fn resolve(
text_system: &TextSystem,
font: Font,
font_size: Pixels,
line_rhythms: u32,
grid: RhythmGrid,
) -> Self
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.
Sourcepub fn from_baseline_ratio(
font: Font,
font_size: Pixels,
line_rhythms: u32,
baseline_ratio: f32,
grid: RhythmGrid,
) -> Self
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.
Sourcepub fn measure_icf(
&self,
text_system: &TextSystem,
probes: &str,
) -> Result<RhythmIcfAnchor, IcfMeasurementError>
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.
Sourcepub fn font(&self) -> &Font
pub fn font(&self) -> &Font
The requested gpui font configuration applied by
RhythmStyled::rhythm_font.
Sourcepub const fn resolved_font_id(&self) -> Option<FontId>
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.
Sourcepub fn spec(&self) -> Option<RhythmFontSpec>
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.
Sourcepub fn line_metrics(&self) -> RhythmLineMetrics
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.
Sourcepub const fn grid(&self) -> RhythmGrid
pub const fn grid(&self) -> RhythmGrid
The grid this font was resolved against.
Sourcepub fn baseline_top(&self, n: i32) -> Pixels
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.
Sourcepub fn baseline_bottom(&self, n: i32) -> Pixels
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.
Sourcepub fn baseline_between(&self, below: &RhythmFont, n: i32) -> Pixels
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.
Sourcepub fn cap_top(&self, n: i32) -> Option<Pixels>
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.
Sourcepub fn cap_bottom(&self, n: i32) -> Option<Pixels>
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.
Sourcepub fn cap_span(&self, top: i32, bottom: i32) -> Option<(Pixels, Pixels)>
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)),
})Sourcepub fn drop_cap(
&self,
text_system: &TextSystem,
font: Font,
lines: u32,
) -> RhythmDropCap
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.
Sourcepub const fn metrics(&self) -> &FontRhythm
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.
Sourcepub fn line_height(&self) -> Pixels
pub fn line_height(&self) -> Pixels
The rhythm line height: line_rhythms × grid size.
Sourcepub fn baseline_above(&self) -> Pixels
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.
Sourcepub fn baseline_below(&self) -> Pixels
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.
Sourcepub fn cap_trim_top(&self) -> Option<Pixels>
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.
Sourcepub fn x_trim_top(&self) -> Option<Pixels>
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
impl Clone for RhythmFont
Source§fn clone(&self) -> RhythmFont
fn clone(&self) -> RhythmFont
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for RhythmFont
impl RefUnwindSafe for RhythmFont
impl Send for RhythmFont
impl Sync for RhythmFont
impl Unpin for RhythmFont
impl UnsafeUnpin for RhythmFont
impl UnwindSafe for RhythmFont
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
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>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
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)
fn as_any(&self) -> &(dyn Any + 'static)
&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)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&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
impl<T> DowncastSync for T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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