use alloc::vec::Vec;
use mathtex_ir::{
Fragment, FragmentMetadata, Glue, GlyphRun, Kern, LayoutBox, LayoutList, LayoutNode,
LayoutNodeKind, ListKind, NodeId, Point, Rect, Rule, Style, Surface,
};
#[derive(Clone, Debug)]
pub struct IrEmitter {
fragment: Fragment,
next_node: u32,
}
impl IrEmitter {
#[must_use]
pub fn new(metadata: FragmentMetadata) -> Self {
Self {
fragment: Fragment {
metadata,
..Fragment::default()
},
next_node: 0,
}
}
pub fn set_surface(&mut self, surface: Surface) {
self.fragment.surface = surface;
}
pub fn emit_box(&mut self, node: EmitNode, layout_box: LayoutBox) -> NodeId {
self.emit(node, LayoutNodeKind::Box(layout_box))
}
pub fn emit_list(&mut self, node: EmitNode, kind: ListKind, children: Vec<NodeId>) -> NodeId {
self.emit(node, LayoutNodeKind::List(LayoutList { kind, children }))
}
pub fn emit_glyph_run(&mut self, node: EmitNode, glyph_run: GlyphRun) -> NodeId {
self.emit(node, LayoutNodeKind::GlyphRun(glyph_run))
}
pub fn emit_rule(&mut self, node: EmitNode, rule: Rule) -> NodeId {
self.emit(node, LayoutNodeKind::Rule(rule))
}
pub fn emit_glue(&mut self, node: EmitNode, glue: Glue) -> NodeId {
self.emit(node, LayoutNodeKind::Glue(glue))
}
pub fn emit_kern(&mut self, node: EmitNode, kern: Kern) -> NodeId {
self.emit(node, LayoutNodeKind::Kern(kern))
}
#[must_use]
pub fn finish(self) -> Fragment {
self.fragment
}
fn emit(&mut self, node: EmitNode, kind: LayoutNodeKind) -> NodeId {
let id = NodeId(self.next_node);
self.next_node += 1;
self.fragment.nodes.push(LayoutNode {
id,
origin: node.origin,
bounds: node.bounds,
primary_source: None,
style: node.style,
kind,
});
id
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct EmitNode {
pub origin: Point,
pub bounds: Rect,
pub style: Style,
}
impl EmitNode {
#[must_use]
pub fn with_style(mut self, style: Style) -> Self {
self.style = style;
self
}
}