Skip to main content

RhythmLineMetrics

Struct RhythmLineMetrics 

Source
pub struct RhythmLineMetrics { /* private fields */ }
Expand description

Vertical metrics of one shaped line on the rhythm grid.

Unlike FontRhythm, which carries a resolved style (with its font size and optional cap/x heights), this is the minimal value a renderer needs to place one already-shaped line: the line’s reported ascent/descent, its height in whole rhythm units, and the grid. In gpui, feed it WrappedLine::ascent() / descent() — the shaped maxima over the line’s explicit font runs — and every visual line of that WrappedLine lands on the grid, because wrapped lines advance by the same whole-row line height.

The renderer chooses line_rhythms; min_line_rhythms suggests the smallest count whose line box contains that metric envelope, and overflows_line_box reports when the chosen count is smaller. Keeping a smaller count is valid — the baseline stays on the grid and the reported envelope overflows symmetrically via negative half-leading, exactly as CSS line boxes behave. This does not claim that every glyph’s typographic or raster ink stays inside the line box. covering picks the count the other way round: over a known set of faces, before anything is shaped.

A shaped empty line has zero ascent and descent; place empty lines with the style’s FontRhythm metrics instead so blank lines keep the style’s baseline position.

§Examples

use rhythm_gpui::{Rhythm, RhythmLineMetrics};

let grid = Rhythm::new(8.0);
// A shaped line whose tallest run gives ascent 15.2, descent 4.1.
let line = RhythmLineMetrics::new(15.2, 4.1, 3, grid);

// Land its baseline on the 5th grid line below the block top: the paint
// origin is where the line box's top edge goes.
let origin_y = line.paint_origin_for(grid.height(5));
assert!((origin_y + line.baseline_above() - grid.height(5)).abs() < 1e-4);

Implementations§

Source§

impl RhythmLineMetrics

Source

pub fn new(ascent: f32, descent: f32, line_rhythms: u32, grid: Rhythm) -> Self

Build from a shaped line’s metrics: ascent and descent in logical pixels (both non-negative, e.g. gpui’s WrappedLine::ascent() / descent()), and the line height in whole rhythm units.

§Panics

Panics when ascent or descent is negative or non-finite, or when line_rhythms is zero.

Source

pub fn at_least( ascent: f32, descent: f32, line_rhythms: u32, grid: Rhythm, ) -> Self

Like new, but grows the line box to min_line_rhythms when line_rhythms is too small to contain the reported ascent/descent envelope. Use it when the configured line height is a floor rather than a fixed virtualization budget.

§Panics

Panics under the same conditions as new, or when the minimum fitting count does not fit in u32.

Source

pub fn covering(metrics: &[RhythmLineMetrics], grid: Rhythm) -> Self

The smallest line box on grid containing every line in metrics: the maximum ascent and the maximum descent over the set, in the largest of their line heights, grown to min_line_rhythms when that combined metric envelope no longer fits.

A line shapes to the maxima over its explicit font runs, so no line drawn from a caller-supplied set of face metrics can exceed the box covering that set. Folding a style’s whole known set — its own face and the faces its runs explicitly use (bold, inline code, or an explicit CJK or emoji face) — at catalog-build time makes the line’s metric envelope a property of construction rather than one each shaped line has to be checked for. Glyph-level fallback faces selected later by a platform shaper are outside this set unless the caller supplies their metrics. Nothing here shapes text: the count is known at startup, so a block’s height follows from its line count alone, which is what a virtualized renderer needs.

Take the count, not the box, into placement: this value’s ascent/descent describe a hypothetical line reaching both maxima at once, so keep building each line’s metrics from its own shaped values — at this line_rhythms — and every baseline still lands on the grid.

§Examples
use rhythm_gpui::{Rhythm, RhythmLineMetrics};

let grid = Rhythm::new(8.0);
// A body style, and a display face its lines can mix in.
let body = RhythmLineMetrics::new(14.67, 3.51, 3, grid);
let display = RhythmLineMetrics::new(28.8, 6.4, 3, grid);

// One static row budget for the style: three rows cannot hold the
// display face's ascent/descent envelope, so the covering box is five.
let budget = RhythmLineMetrics::covering(&[body, display], grid);
assert_eq!(budget.line_rhythms(), 5);

// Every mixture of the two fits it, including the worst case.
let worst = RhythmLineMetrics::new(28.8, 6.4, budget.line_rhythms(), grid);
assert!(!worst.overflows_line_box());
§Panics

Panics when metrics is empty, when an entry was built on a different grid, or when the minimum fitting count does not fit in u32.

Source

pub const fn ascent(&self) -> f32

The reported shaped ascent above the baseline, non-negative.

Source

pub const fn descent(&self) -> f32

The reported shaped descent below the baseline, non-negative.

Source

pub const fn line_rhythms(&self) -> u32

Line height in whole rhythm units.

Source

pub const fn grid(&self) -> Rhythm

The grid the line is placed on.

Source

pub fn line_height(&self) -> f32

The line height in logical pixels: line_rhythms × grid size.

Source

pub fn half_leading(&self) -> f32

Extra space split above and below the ascent + descent box; negative when that metric envelope is taller than the line box.

Source

pub fn baseline_above(&self) -> f32

Distance from the line box’s top edge down to the baseline, as gpui paints it: half_leading + ascent.

Source

pub fn baseline_below(&self) -> f32

Distance from the baseline down to the line box’s bottom edge.

Source

pub fn paint_origin_for(&self, target_baseline: f32) -> f32

Where to place the line box’s top edge — the origin.y passed to gpui’s WrappedLine::paint — so the baseline lands exactly on target_baseline (both in the same coordinate space): target_baseline − baseline_above.

Source

pub fn min_line_rhythms(&self) -> u32

The smallest line_rhythms whose line box contains the reported ascent + descent envelope, at least 1. Applies the same snapping rule as Rhythm::snap_up — at f64 precision, since shaped metrics are summed rather than measured — so an envelope within a few rounding steps of a whole-row height does not claim an extra row.

Advisory: the renderer decides whether to grow the line or keep its chosen height and accept the overflow.

§Panics

Panics when the minimum fitting count does not fit in u32.

Source

pub fn overflows_line_box(&self) -> bool

Whether the reported ascent + descent envelope is taller than the chosen line box — equivalently, whether half_leading is negative beyond Rhythm::snap_up’s tolerance.

Source§

impl RhythmLineMetrics

Pixels-typed mirrors of the two line values that stay inside a paint path’s Pixels chain: both reach WrappedLine::paint.

Only four values across this type and RhythmBlockMetrics are mirrored. The rest of the f32 surface is read once and converted once, so it is not mirrored: px(line.ascent()) at the call site is one conversion, while a mirror per accessor doubles the surface to save it. Row counts are never mirrored because they identify grid rows rather than pixel lengths.

Source

pub fn line_height_px(&self) -> Pixels

Available on crate feature gpui only.

line_height in Pixels — the value WrappedLine::paint takes.

Source

pub fn paint_origin_for_px(&self, target_baseline: Pixels) -> Pixels

Available on crate feature gpui only.

paint_origin_for in Pixels — the origin.y for WrappedLine::paint, from a Pixels target baseline.

Trait Implementations§

Source§

impl Clone for RhythmLineMetrics

Source§

fn clone(&self) -> RhythmLineMetrics

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 Copy for RhythmLineMetrics

Source§

impl Debug for RhythmLineMetrics

Source§

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

Formats the value using the given formatter. Read more
Source§

impl PartialEq for RhythmLineMetrics

Source§

fn eq(&self, other: &RhythmLineMetrics) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for RhythmLineMetrics

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