diff --git a/src/font.rs b/src/font.rs index ce1c48f89..9280ff8d5 100644 --- a/src/font.rs +++ b/src/font.rs @@ -6,6 +6,8 @@ use std::fmt::{self, Debug, Formatter}; use std::path::{Path, PathBuf}; use std::sync::Arc; +use once_cell::sync::OnceCell; +use rex::font::MathFont; use serde::{Deserialize, Serialize}; use ttf_parser::{name_id, GlyphId, PlatformId, Tag}; use unicode_segmentation::UnicodeSegmentation; @@ -246,6 +248,8 @@ pub struct Face { ttf: rustybuzz::Face<'static>, /// The faces metrics. metrics: FaceMetrics, + /// The parsed ReX math font. + math: OnceCell>, } impl Face { @@ -263,7 +267,13 @@ impl Face { let ttf = rustybuzz::Face::from_slice(slice, index)?; let metrics = FaceMetrics::from_ttf(&ttf); - Some(Self { buffer, index, ttf, metrics }) + Some(Self { + buffer, + index, + ttf, + metrics, + math: OnceCell::new(), + }) } /// The underlying buffer. @@ -293,6 +303,11 @@ impl Face { &self.metrics } + /// Access the math font, if any. + pub fn math(&self) -> Option<&MathFont> { + self.math.get_or_init(|| MathFont::parse(self.buffer()).ok()).as_ref() + } + /// Convert from font units to an em length. pub fn to_em(&self, units: impl Into) -> Em { Em::from_units(units, self.units_per_em()) diff --git a/src/library/math/rex.rs b/src/library/math/rex.rs index addf56b6b..0268fb9c8 100644 --- a/src/library/math/rex.rs +++ b/src/library/math/rex.rs @@ -35,13 +35,13 @@ impl Layout for RexNode { .at(span)?; // Prepare the font. - let data = ctx.fonts.get(face_id).buffer(); - let font = MathFont::parse(data) - .map_err(|_| "failed to parse math font") + let face = ctx.fonts.get(face_id); + let ctx = face + .math() + .and_then(FontContext::new) + .ok_or("font is not suitable for math") .at(span)?; - let ctx = FontContext::new(&font).ok_or("failed to parse math font").at(span)?; - // Layout the formula. let em = styles.get(TextNode::SIZE); let style = if self.display { Style::Display } else { Style::Text }; diff --git a/tests/typ/math/basic.typ b/tests/typ/math/basic.typ index 051dbaf32..df05a5678 100644 --- a/tests/typ/math/basic.typ +++ b/tests/typ/math/basic.typ @@ -15,6 +15,12 @@ $[ \sum_{k=0}^n k = \frac{n(n+1)}{2} ]$ // Test that blackboard style looks nice. $[ f: \mathbb{N} \rightarrow \mathbb{R} ]$ +--- +#set math(family: "IBM Plex Sans") + +// Error: 1-4 font is not suitable for math +$a$ + --- // Error: 1-10 expected '}' found EOF $\sqrt{x$