pub struct FontRhythm { /* private fields */ }Expand description
Vertical metrics of one text style participating in the rhythm grid.
ascent and descent are resolved at font_size (logical pixels, both
positive). Line height is expressed in whole rhythm units, which is what keeps
consecutive lines of the same style on the grid.
Implementations§
Source§impl FontRhythm
impl FontRhythm
Sourcepub fn from_metrics(
font_size: f32,
line_rhythms: u32,
ascent: f32,
descent: f32,
) -> Self
pub fn from_metrics( font_size: f32, line_rhythms: u32, ascent: f32, descent: f32, ) -> Self
Build from real font metrics resolved at font_size.
§Panics
Panics when font_size or ascent is not finite and positive, when
line_rhythms is zero, or when descent is not finite and non-negative.
Sourcepub fn from_platform_metrics(
font_size: f32,
line_rhythms: u32,
ascent: f32,
descent: f32,
cap_height: f32,
x_height: f32,
) -> Self
pub fn from_platform_metrics( font_size: f32, line_rhythms: u32, ascent: f32, descent: f32, cap_height: f32, x_height: f32, ) -> Self
Build from platform-reported metrics, normalizing conventions.
Some platforms report table metrics in the OpenType sign convention where
descent is negative below the baseline (gpui on macOS does), so ascent
and descent are taken by magnitude. Non-finite or non-positive cap and
x heights are treated as unavailable and become None.
§Panics
Panics under the same conditions as Self::from_metrics after
normalization (e.g. a zero ascent).
Sourcepub fn from_baseline_ratio(
font_size: f32,
line_rhythms: u32,
baseline_ratio: f32,
) -> Self
pub fn from_baseline_ratio( font_size: f32, line_rhythms: u32, baseline_ratio: f32, ) -> Self
Compatibility constructor for a Plumber/rhythm-sass baseline-ratio
(0 < ratio < 1), using the em-box approximation the Sass library assumed:
ascent = (1 - ratio) * font_size, descent = ratio * font_size.
Prefer Self::from_metrics: the ratio is itself derived from metrics
((em + descent - ascent) / (2 * em)) and the em-box model slightly
misplaces the baseline for fonts whose ascent + descent != em.
§Panics
Panics when baseline_ratio is not strictly between 0 and 1, when
font_size is not finite and positive, or when line_rhythms is zero.
Sourcepub const fn line_rhythms(&self) -> u32
pub const fn line_rhythms(&self) -> u32
Line height in whole rhythm units.
Sourcepub const fn ascent(&self) -> f32
pub const fn ascent(&self) -> f32
Distance from the baseline up to the top of the ascent box, positive.
Sourcepub const fn descent(&self) -> f32
pub const fn descent(&self) -> f32
Distance from the baseline down to the bottom of the descent box, positive.
Sourcepub const fn cap_height(&self) -> Option<f32>
pub const fn cap_height(&self) -> Option<f32>
Height of capital letters above the baseline, if known.
Sourcepub const fn x_height(&self) -> Option<f32>
pub const fn x_height(&self) -> Option<f32>
Height of a lowercase x above the baseline, if known.
Sourcepub fn baseline_ratio(&self) -> f32
pub fn baseline_ratio(&self) -> f32
The Plumber-style baseline ratio implied by these metrics.
Sourcepub fn line_height(&self, grid: Rhythm) -> f32
pub fn line_height(&self, grid: Rhythm) -> f32
The line height on grid: line_rhythms whole rhythm units.
Sourcepub fn half_leading(&self, grid: Rhythm) -> f32
pub fn half_leading(&self, grid: Rhythm) -> f32
Extra space split above and below the ascent + descent box.
Sourcepub fn baseline_above(&self, grid: Rhythm) -> f32
pub fn baseline_above(&self, grid: Rhythm) -> f32
Distance from the top of the line box down to the baseline.
Sourcepub fn baseline_below(&self, grid: Rhythm) -> f32
pub fn baseline_below(&self, grid: Rhythm) -> f32
Distance from the baseline down to the bottom of the line box.
Sourcepub fn cap_trim_top(&self, grid: Rhythm) -> Option<f32>
pub fn cap_trim_top(&self, grid: Rhythm) -> Option<f32>
Invisible space between the top of the line box and the cap top: the amount
a leading-trim (CSS text-box-trim) would remove. Subtract it from a top
spacing (or apply as negative margin) to visually butt capitals against an
edge or grid line.
Sourcepub fn x_trim_top(&self, grid: Rhythm) -> Option<f32>
pub fn x_trim_top(&self, grid: Rhythm) -> Option<f32>
Like Self::cap_trim_top but trimming to the x-height.
Sourcepub fn baseline_top(&self, grid: Rhythm, n: i32) -> f32
pub fn baseline_top(&self, grid: Rhythm, n: i32) -> f32
Spacing from an element’s top edge up to the nth grid line above the first
baseline. Equivalent to rhythm-sass baseline-top() / rhythm-bottom().
Applied as padding-top (or margin-top), it makes the first baseline land
exactly n rhythm units below the grid line at the element’s padding edge.
The result is negative when n × size is smaller than
baseline_above; a negative value is meaningful
as a margin but not as a padding, so pick n accordingly.
Sourcepub fn baseline_bottom(&self, grid: Rhythm, n: i32) -> f32
pub fn baseline_bottom(&self, grid: Rhythm, n: i32) -> f32
Spacing from an element’s bottom edge down to the nth grid line below the
last baseline. Equivalent to rhythm-sass baseline-bottom() / rhythm-top().
The result is negative when n × size is smaller than
baseline_below; a negative value is meaningful
as a margin but not as a padding, so pick n accordingly.
Sourcepub fn baseline_between(&self, grid: Rhythm, below: &FontRhythm, n: i32) -> f32
pub fn baseline_between(&self, grid: Rhythm, below: &FontRhythm, n: i32) -> f32
Spacing from a block set in this style down to a following block set in
below, measured from the bottom of this line box to the top of the
below font’s line box, such that the two adjacent baselines are exactly
n rhythm units apart. Equivalent to rhythm-sass baseline-between().
The result is negative when n rhythm units cannot fit both fonts’
baseline distances; negative values overlap the blocks when applied.
Sourcepub fn cap_top(&self, grid: Rhythm, n: i32) -> Option<f32>
pub fn cap_top(&self, grid: Rhythm, n: i32) -> Option<f32>
Top spacing that lands the cap ink top — not the baseline — on the
nth grid line: n × size − cap_trim_top. The grid-woven analog of CSS
text-box-trim: trim-start with text-box-edge: cap, for openings
where the eye measures ink to edge (heroes, cards, page tops).
The block’s baselines shift off the grid by cap_height mod size;
close the block with Self::cap_bottom — not
Self::baseline_bottom — so it still occupies a whole number of
rhythm rows and everything after it stays in rhythm.
None when this style has no usable cap height. CJK faces report one
anyway, so on ideographic text this anchor returns Some while
trimming to the wrong ink: ideographs are not seated on the baseline,
and the envelope their ink is drawn to is the ideographic character
face, not a cap height. Anchor those with
RhythmBlockMetrics::ink_anchored,
or with RhythmIcfAnchor::span under the gpui feature. Worse, the
reported value need not describe any glyph:
PingFang SC publishes sCapHeight 0.860 em, a copy of its
sTypoAscender, while its Latin H actually reaches 0.714 em
(Hiragino Sans GB, by contrast, reports its true 0.766 em). Treat a
CJK face’s cap and x heights as unverified.
§Examples
use rhythm_gpui::{FontRhythm, Rhythm};
let grid = Rhythm::new(8.0);
// Georgia-like 28px heading on a 5-unit (40px) line.
let heading = FontRhythm::from_platform_metrics(28.0, 5, 25.68, -6.14, 19.40, 13.48);
// Open: the capitals' ink starts exactly on the 3rd grid line…
let pt = heading.cap_top(grid, 3).unwrap();
assert!((pt + heading.cap_trim_top(grid).unwrap() - grid.height(3)).abs() < 1e-3);
// …and the paired closer returns the trim, so the block spans whole rows.
let pb = heading.cap_bottom(grid, 0).unwrap();
let block = pt + heading.line_height(grid) + pb;
assert!((block - 64.0).abs() < 1e-3); // 8 whole rows: what follows stays in rhythmSourcepub fn cap_bottom(&self, grid: Rhythm, n: i32) -> Option<f32>
pub fn cap_bottom(&self, grid: Rhythm, n: i32) -> Option<f32>
Bottom spacing pairing Self::cap_top: n × size + cap_trim_top,
returning at the bottom exactly what cap_top trimmed at the top so
the block occupies a whole number of rhythm rows — for any number of
wrapped lines, since lines advance by whole rows. Equivalently, the
bottom edge lands n + line_rhythms units below the last line’s cap
top.
None when this style has no usable cap height.
Sourcepub fn line_metrics(&self, grid: Rhythm) -> RhythmLineMetrics
pub fn line_metrics(&self, grid: Rhythm) -> RhythmLineMetrics
This style’s line placement on grid as a
RhythmLineMetrics — the same value a
shaped line produces, so a custom renderer can place single-style
text (and empty lines) through one code path.
Sourcepub fn drop_cap(
&self,
grid: Rhythm,
cap: &FontRhythm,
lines: u32,
) -> DropCapRhythm
pub fn drop_cap( &self, grid: Rhythm, cap: &FontRhythm, lines: u32, ) -> DropCapRhythm
Solve a drop cap sunk lines lines deep into text set in self.
cap carries the cap face’s metrics resolved at any font size (metrics
scale linearly, so the probe size is irrelevant); its line_rhythms is
ignored. The solved font size makes the cap face’s capital span from the
first line’s cap top down to the lines-th baseline, and
DropCapRhythm::top anchors the baseline there. A face without a
usable cap height falls back to the classic 0.7 em approximation, which
can only misplace the visual top — the baseline anchor stays exact.
Drop caps are a Latin convention; CJK paragraphs conventionally open
with a first-line indent instead, so there is deliberately no
ideographic dual of this solver. A CJK face passed as cap is solved
from its reported (Latin-glyph) cap height like any other face.
§Examples
use rhythm_gpui::{FontRhythm, Rhythm};
let grid = Rhythm::new(8.0);
// Georgia-like metrics at 16px on a 3-unit (24px) line.
let body = FontRhythm::from_platform_metrics(16.0, 3, 14.67, -3.51, 11.09, 7.70);
let cap = body.drop_cap(grid, &body, 3);
// The capital spans two body lines plus the body cap height…
let span = 2.0 * body.line_height(grid) + body.cap_height().unwrap();
assert!((cap.metrics().cap_height().unwrap() - span).abs() < 1e-3);
// …and `top` lands its baseline exactly on the third body baseline.
let target = body.baseline_above(grid) + 2.0 * body.line_height(grid);
assert!((cap.top() + cap.metrics().baseline_above(grid) - target).abs() < 1e-3);§Panics
Panics when lines is zero or lines × line_rhythms overflows u32.
Trait Implementations§
Source§impl Clone for FontRhythm
impl Clone for FontRhythm
Source§fn clone(&self) -> FontRhythm
fn clone(&self) -> FontRhythm
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreimpl Copy for FontRhythm
Source§impl Debug for FontRhythm
impl Debug for FontRhythm
Source§impl PartialEq for FontRhythm
impl PartialEq for FontRhythm
impl StructuralPartialEq for FontRhythm
Auto Trait Implementations§
impl Freeze for FontRhythm
impl RefUnwindSafe for FontRhythm
impl Send for FontRhythm
impl Sync for FontRhythm
impl Unpin for FontRhythm
impl UnsafeUnpin for FontRhythm
impl UnwindSafe for FontRhythm
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