diff --git a/src/font.rs b/src/font.rs index 7113026be..8519d4501 100644 --- a/src/font.rs +++ b/src/font.rs @@ -8,7 +8,7 @@ use std::rc::Rc; use serde::{Deserialize, Serialize}; use ttf_parser::{name_id, GlyphId, PlatformId}; -use crate::geom::Em; +use crate::geom::{Em, Length, Linear}; use crate::loading::{FileHash, Loader}; use crate::util::decode_mac_roman; @@ -269,20 +269,21 @@ impl Face { .map(|units| self.to_em(units)) } - /// Look up a vertical metric. - pub fn vertical_metric(&self, metric: VerticalFontMetric) -> Em { + /// Look up a vertical metric at the given font size. + pub fn vertical_metric(&self, metric: VerticalFontMetric, size: Length) -> Length { match metric { - VerticalFontMetric::Ascender => self.ascender, - VerticalFontMetric::CapHeight => self.cap_height, - VerticalFontMetric::XHeight => self.x_height, - VerticalFontMetric::Baseline => Em::zero(), - VerticalFontMetric::Descender => self.descender, + VerticalFontMetric::Ascender => self.ascender.to_length(size), + VerticalFontMetric::CapHeight => self.cap_height.to_length(size), + VerticalFontMetric::XHeight => self.x_height.to_length(size), + VerticalFontMetric::Baseline => Length::zero(), + VerticalFontMetric::Descender => self.descender.to_length(size), + VerticalFontMetric::Linear(v) => v.resolve(size), } } } /// Identifies a vertical metric of a font. -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive(Copy, Clone, Eq, PartialEq, Hash)] pub enum VerticalFontMetric { /// The distance from the baseline to the typographic ascender. /// @@ -300,17 +301,21 @@ pub enum VerticalFontMetric { /// Corresponds to the typographic descender from the `OS/2` table if /// present and falls back to the descender from the `hhea` table otherwise. Descender, + /// An font-size dependent distance from the baseline (positive goes up, negative + /// down). + Linear(Linear), } impl Debug for VerticalFontMetric { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - f.pad(match self { - Self::Ascender => "ascender", - Self::CapHeight => "cap-height", - Self::XHeight => "x-height", - Self::Baseline => "baseline", - Self::Descender => "descender", - }) + match self { + Self::Ascender => f.pad("ascender"), + Self::CapHeight => f.pad("cap-height"), + Self::XHeight => f.pad("x-height"), + Self::Baseline => f.pad("baseline"), + Self::Descender => f.pad("descender"), + Self::Linear(v) => v.fmt(f), + } } } diff --git a/src/layout/shaping.rs b/src/layout/shaping.rs index eebeacbf7..dc6802765 100644 --- a/src/layout/shaping.rs +++ b/src/layout/shaping.rs @@ -342,8 +342,8 @@ fn measure( // Expand top and bottom by reading the face's vertical metrics. let mut expand = |face: &Face| { - top.set_max(face.vertical_metric(state.top_edge).to_length(state.size)); - bottom.set_max(-face.vertical_metric(state.bottom_edge).to_length(state.size)); + top.set_max(face.vertical_metric(state.top_edge, state.size)); + bottom.set_max(-face.vertical_metric(state.bottom_edge, state.size)); }; if glyphs.is_empty() { diff --git a/src/library/mod.rs b/src/library/mod.rs index c42b82d61..13c8fd5c5 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -127,16 +127,19 @@ dynamic! { dynamic! { FontWeight: "font weight", - Value::Int(number) => { - u16::try_from(number).map_or(Self::BLACK, Self::from_number) + Value::Int(v) => { + u16::try_from(v).map_or(Self::BLACK, Self::from_number) }, } dynamic! { FontStretch: "font stretch", - Value::Relative(relative) => Self::from_ratio(relative.get() as f32), + Value::Relative(v) => Self::from_ratio(v.get() as f32), } dynamic! { VerticalFontMetric: "vertical font metric", + Value::Length(v) => Self::Linear(v.into()), + Value::Relative(v) => Self::Linear(v.into()), + Value::Linear(v) => Self::Linear(v), } diff --git a/tests/ref/text/font.png b/tests/ref/text/font.png index b8e0775a6..2dfab8704 100644 Binary files a/tests/ref/text/font.png and b/tests/ref/text/font.png differ diff --git a/tests/typ/text/font.typ b/tests/typ/text/font.typ index 98643565e..6457f7a7c 100644 --- a/tests/typ/text/font.typ +++ b/tests/typ/text/font.typ @@ -58,6 +58,8 @@ Emoji: 🐪, 🌋, 🏞 #try(ascender, baseline) #try(cap-height, baseline) #try(x-height, baseline) +#try(4pt, -2pt) +#try(1pt + 27%, -18%) --- // Error: 7-12 unexpected argument