rpic_core/math.rs
1//! Math-label rendering hook (rpic `texlabels` extension).
2//!
3//! The core stays free of any typesetting dependency: a renderer is a plain
4//! function registered once per process (the CLI and bindings register the
5//! RaTeX-backed implementation from `rpic-render`; the wasm build registers
6//! nothing and math labels fall back to literal text). The hook is
7//! deliberately neutral so an alternative backend — e.g. Typst + mitex, the
8//! documented second choice in `docs/tex-labels.md` — can slot in without
9//! touching the core.
10
11use std::sync::OnceLock;
12
13/// A typeset math label: a self-contained SVG fragment (glyph paths only,
14/// rasterizable with no font database) plus exact metrics in inches.
15#[derive(Debug, Clone, PartialEq)]
16pub struct MathSpan {
17 /// Complete `<svg …>` document for the formula, tight box, origin at the
18 /// top-left. Embedded into the drawing as a nested `<svg>` element.
19 pub svg: String,
20 /// Advance width in inches.
21 pub width: f64,
22 /// Extent above the baseline in inches.
23 pub height: f64,
24 /// Extent below the baseline in inches.
25 pub depth: f64,
26}
27
28/// Typeset `tex` (math mode, no delimiters) at the given font size in points.
29pub type MathRenderFn = fn(tex: &str, font_pt: f64) -> Result<MathSpan, String>;
30
31static MATH_RENDERER: OnceLock<MathRenderFn> = OnceLock::new();
32
33/// Register the process-wide math renderer. The first call wins; later calls
34/// are ignored (returns whether this call installed the renderer).
35pub fn set_math_renderer(f: MathRenderFn) -> bool {
36 MATH_RENDERER.set(f).is_ok()
37}
38
39/// The registered renderer, if any.
40pub(crate) fn math_renderer() -> Option<MathRenderFn> {
41 MATH_RENDERER.get().copied()
42}