Multi-line alignment with &
This commit is contained in:
parent
203d5779f8
commit
2c48c8d7a1
60
library/src/math/align.rs
Normal file
60
library/src/math/align.rs
Normal file
@ -0,0 +1,60 @@
|
||||
use super::*;
|
||||
|
||||
/// # Alignment Point
|
||||
/// A math alignment point: `&`, `&&`.
|
||||
///
|
||||
/// ## Parameters
|
||||
/// - index: usize (positional, required)
|
||||
/// The alignment point's index.
|
||||
///
|
||||
/// ## Category
|
||||
/// math
|
||||
#[func]
|
||||
#[capable(LayoutMath)]
|
||||
#[derive(Debug, Hash)]
|
||||
pub struct AlignPointNode;
|
||||
|
||||
#[node]
|
||||
impl AlignPointNode {}
|
||||
|
||||
impl LayoutMath for AlignPointNode {
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
ctx.push(MathFragment::Align);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Determine the position of the alignment points.
|
||||
pub(super) fn alignments(rows: &[MathRow]) -> Vec<Abs> {
|
||||
let count = rows
|
||||
.iter()
|
||||
.map(|row| {
|
||||
row.0
|
||||
.iter()
|
||||
.filter(|fragment| matches!(fragment, MathFragment::Align))
|
||||
.count()
|
||||
})
|
||||
.max()
|
||||
.unwrap_or(0);
|
||||
|
||||
let mut points = vec![Abs::zero(); count];
|
||||
for current in 0..count {
|
||||
for row in rows {
|
||||
let mut x = Abs::zero();
|
||||
let mut i = 0;
|
||||
for fragment in &row.0 {
|
||||
if matches!(fragment, MathFragment::Align) {
|
||||
if i < current {
|
||||
x = points[i];
|
||||
} else if i == current {
|
||||
points[i].set_max(x);
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
x += fragment.width();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
points
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
#[macro_use]
|
||||
mod ctx;
|
||||
mod accent;
|
||||
mod align;
|
||||
mod atom;
|
||||
mod frac;
|
||||
mod group;
|
||||
|
Loading…
Reference in New Issue
Block a user