use typst_utils::default_math_class;
use unicode_math_class::MathClass;
use crate::foundations::{Content, StyleChain, elem};
use crate::layout::{Length, Rel};
use crate::math::{EquationElem, MathSize, Mathy};
#[elem(Mathy)]
pub struct AttachElem {
#[required]
pub base: Content,
pub t: Option<Content>,
pub b: Option<Content>,
pub tl: Option<Content>,
pub bl: Option<Content>,
pub tr: Option<Content>,
pub br: Option<Content>,
}
#[elem(Mathy)]
pub struct PrimesElem {
#[required]
pub count: usize,
}
#[elem(Mathy)]
pub struct ScriptsElem {
#[required]
pub body: Content,
}
#[elem(Mathy)]
pub struct LimitsElem {
#[required]
pub body: Content,
#[default(true)]
pub inline: bool,
}
#[elem(Mathy)]
pub struct StretchElem {
#[required]
pub body: Content,
#[default(Rel::one())]
pub size: Rel<Length>,
}
#[derive(Debug, Copy, Clone)]
pub enum Limits {
Never,
Display,
Always,
}
impl Limits {
pub fn for_char(c: char) -> Self {
Self::for_char_with_class(c, default_math_class(c))
}
pub fn for_char_with_class(c: char, class: Option<MathClass>) -> Self {
match class {
Some(MathClass::Large) => {
if is_integral_char(c) {
Limits::Never
} else {
Limits::Display
}
}
Some(MathClass::Relation) => Limits::Always,
_ => Limits::Never,
}
}
pub fn for_class(class: MathClass) -> Self {
match class {
MathClass::Large => Self::Display,
MathClass::Relation => Self::Always,
_ => Self::Never,
}
}
pub fn active(&self, styles: StyleChain) -> bool {
match self {
Self::Always => true,
Self::Display => styles.get(EquationElem::size) == MathSize::Display,
Self::Never => false,
}
}
}
fn is_integral_char(c: char) -> bool {
('∫'..='∳').contains(&c) || ('⨋'..='⨜').contains(&c)
}