58 lines
1.7 KiB
Rust
58 lines
1.7 KiB
Rust
use super::*;
|
|
|
|
/// # Atom
|
|
/// An atom in a math formula: `x`, `+`, `12`.
|
|
///
|
|
/// ## Parameters
|
|
/// - text: EcoString (positional, required)
|
|
/// The atom's text.
|
|
///
|
|
/// ## Category
|
|
/// math
|
|
#[func]
|
|
#[capable(LayoutMath)]
|
|
#[derive(Debug, Hash)]
|
|
pub struct AtomNode(pub EcoString);
|
|
|
|
#[node]
|
|
impl AtomNode {
|
|
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
|
|
Ok(Self(args.expect("text")?).pack())
|
|
}
|
|
}
|
|
|
|
impl LayoutMath for AtomNode {
|
|
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
|
let mut chars = self.0.chars();
|
|
if let Some(glyph) = chars
|
|
.next()
|
|
.filter(|_| chars.next().is_none())
|
|
.and_then(|c| GlyphFragment::try_new(ctx, c))
|
|
{
|
|
// A single letter that is available in the math font.
|
|
if ctx.style.size == MathSize::Display
|
|
&& glyph.class() == Some(MathClass::Large)
|
|
{
|
|
let height = scaled!(ctx, display_operator_min_height);
|
|
ctx.push(glyph.stretch_vertical(ctx, height, Abs::zero()));
|
|
} else {
|
|
ctx.push(glyph);
|
|
}
|
|
} else if self.0.chars().all(|c| c.is_ascii_digit()) {
|
|
// A number that should respect math styling and can therefore
|
|
// not fall back to the normal text layout.
|
|
let mut vec = vec![];
|
|
for c in self.0.chars() {
|
|
vec.push(GlyphFragment::new(ctx, c).into());
|
|
}
|
|
let frame = MathRow(vec).to_frame(ctx);
|
|
ctx.push(frame);
|
|
} else {
|
|
// Anything else is handled by Typst's standard text layout.
|
|
TextNode(self.0.clone()).pack().layout_math(ctx)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|