Convert math alignment to single-pass algorithm (#891)

This commit is contained in:
Alex Saveau 2023-04-20 10:48:11 -07:00 committed by GitHub
parent 42b93b7b53
commit 851b154a6c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 47 additions and 23 deletions

View File

@ -16,34 +16,30 @@ impl LayoutMath for AlignPointElem {
/// Determine the position of the alignment points.
pub(super) fn alignments(rows: &[MathRow]) -> Vec<Abs> {
let count = rows
.iter()
.map(|row| {
row.iter()
.filter(|fragment| matches!(fragment, MathFragment::Align))
.count()
})
.max()
.unwrap_or(0);
let mut widths = Vec::<Abs>::new();
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;
let mut width = Abs::zero();
let mut alignment_index = 0;
for fragment in row.iter() {
if matches!(fragment, MathFragment::Align) {
if i < current {
x = points[i];
} else if i == current {
points[i].set_max(x);
if alignment_index < widths.len() {
widths[alignment_index].set_max(width);
} else {
widths.push(width);
}
i += 1;
}
x += fragment.width();
width = Abs::zero();
alignment_index += 1;
} else {
width += fragment.width();
}
}
}
let mut points = widths;
for i in 1..points.len() {
let prev = points[i - 1];
points[i] += prev;
}
points
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

@ -0,0 +1,28 @@
// Test implicit alignment math.
---
// Test alignment step functions.
#set page(width: 300pt)
$
"abc" &= c \
&= c + 1 & "By definition" \
&= d + 100 + 1000 \
&= x && "Even longer" \
$
---
// Test post-fix alignment.
#set page(width: 300pt)
$
& "right" \
"a very long line" \
$
---
// Test alternating alignment.
#set page(width: 300pt)
$
"abc" & "abc abc abc" & "abc abc" \
"abc abc" & "abc abc" & "abc" \
"abc abc abc" & "abc" & "abc abc abc" \
$