mod engine;
mod metrics;
mod numbering;
mod space;
mod style;
pub use engine::{layout, layout_with_numbering};
pub use metrics::MathParams;
pub use numbering::{NumberFormat, NumberStyle, NumberingConfig, NumberingState};
pub use style::MathStyle;
use crate::color::Color;
use crate::dim::Dim;
use crate::error::Error;
use crate::font::MathFont;
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum BoxContent {
Empty,
Rule,
Glyph {
ch: char,
glyph_id: u16,
},
HList(Vec<MathBox>),
VList(Vec<MathBox>),
Kern(Dim),
Color(Color, Box<MathBox>),
BackColor(Color, Box<MathBox>),
Overlap(Vec<MathBox>),
Line {
x1: Dim,
y1: Dim,
x2: Dim,
y2: Dim,
thickness: Dim,
},
Frame {
thickness: Dim,
stroke: Option<Color>,
inner: Box<MathBox>,
},
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MathBox {
pub width: Dim,
pub height: Dim,
pub depth: Dim,
pub italic: Dim,
pub shift: Dim,
pub content: BoxContent,
}
impl MathBox {
#[must_use]
pub fn empty() -> Self {
Self {
width: Dim::zero(),
height: Dim::zero(),
depth: Dim::zero(),
italic: Dim::zero(),
shift: Dim::zero(),
content: BoxContent::Empty,
}
}
#[must_use]
pub fn rule(width: Dim, height: Dim, depth: Dim) -> Self {
Self {
width,
height,
depth,
italic: Dim::zero(),
shift: Dim::zero(),
content: BoxContent::Rule,
}
}
#[must_use]
pub fn kern(width: Dim) -> Self {
Self {
width: width.clone(),
height: Dim::zero(),
depth: Dim::zero(),
italic: Dim::zero(),
shift: Dim::zero(),
content: BoxContent::Kern(width),
}
}
pub fn from_glyph(font: &MathFont, ch: char) -> Result<Self, Error> {
let g = font.glyph(ch)?;
Ok(Self {
width: g.advance,
height: g.height,
depth: g.depth,
italic: font.italic_correction(g.glyph_id),
shift: Dim::zero(),
content: BoxContent::Glyph {
ch,
glyph_id: g.glyph_id,
},
})
}
#[must_use]
pub fn hpack(children: Vec<Self>) -> Self {
let mut width = Dim::zero();
let mut height = Dim::zero();
let mut depth = Dim::zero();
for c in &children {
width = &width + &c.width;
height = height.max(&c.height);
depth = depth.max(&c.depth);
}
Self {
width,
height,
depth,
italic: Dim::zero(),
shift: Dim::zero(),
content: BoxContent::HList(children),
}
}
#[must_use]
pub fn vpack(children: Vec<Self>) -> Self {
if children.is_empty() {
return Self::empty();
}
let mut width = Dim::zero();
let height = children[0].height.clone();
let mut depth = children[0].depth.clone();
for c in children.iter().skip(1) {
width = width.max(&c.width);
depth = &depth + &c.height;
depth = &depth + &c.depth;
}
width = width.max(&children[0].width);
Self {
width,
height,
depth,
italic: Dim::zero(),
shift: Dim::zero(),
content: BoxContent::VList(children),
}
}
#[must_use]
pub fn with_shift(mut self, shift: Dim) -> Self {
self.shift = shift;
self
}
#[must_use]
pub fn dim_gold(&self) -> String {
format!(
"w={} h={} d={}",
self.width.to_dec_string(),
self.height.to_dec_string(),
self.depth.to_dec_string()
)
}
}