Parse math fonts only once

This commit is contained in:
Laurenz 2022-05-24 19:30:09 +02:00
parent acdde6d326
commit 018860da9c
3 changed files with 27 additions and 6 deletions

View File

@ -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<Option<MathFont>>,
}
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<f64>) -> Em {
Em::from_units(units, self.units_per_em())

View File

@ -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 };

View File

@ -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$