Alternate between right/left alignment in equations (#936)

This commit is contained in:
Alex Saveau 2023-05-11 05:56:17 -07:00 committed by GitHub
parent 27771bc329
commit e472b0347f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 55 additions and 19 deletions

View File

@ -1,3 +1,5 @@
use std::iter::once;
use crate::layout::AlignElem;
use super::*;
@ -172,31 +174,46 @@ impl MathRow {
fn into_line_frame(self, points: &[Abs], align: Align) -> Frame {
let ascent = self.ascent();
let descent = self.descent();
let size = Size::new(Abs::zero(), ascent + descent);
let mut frame = Frame::new(size);
let mut x = Abs::zero();
let mut frame = Frame::new(Size::new(Abs::zero(), ascent + self.descent()));
frame.set_baseline(ascent);
if let (Some(&first), Align::Center) = (points.first(), align) {
let mut offset = first;
for fragment in self.iter() {
offset -= fragment.width();
if matches!(fragment, MathFragment::Align) {
x = offset;
break;
let mut next_x = {
let mut widths = Vec::new();
if !points.is_empty() && align != Align::Left {
let mut width = Abs::zero();
for fragment in self.iter() {
if matches!(fragment, MathFragment::Align) {
widths.push(width);
width = Abs::zero();
} else {
width += fragment.width();
}
}
widths.push(width);
}
}
let widths = widths;
let fragments = self.0.into_iter().peekable();
let mut i = 0;
for fragment in fragments {
let mut prev_points = once(Abs::zero()).chain(points.iter().copied());
let mut point_widths = points.iter().copied().zip(widths);
let mut alternator = LeftRightAlternator::Right;
move || match align {
Align::Left => prev_points.next(),
Align::Right => point_widths.next().map(|(point, width)| point - width),
_ => point_widths
.next()
.zip(prev_points.next())
.zip(alternator.next())
.map(|(((point, width), prev_point), alternator)| match alternator {
LeftRightAlternator::Left => prev_point,
LeftRightAlternator::Right => point - width,
}),
}
};
let mut x = next_x().unwrap_or_default();
for fragment in self.0.into_iter() {
if matches!(fragment, MathFragment::Align) {
if let Some(&point) = points.get(i) {
x = point;
}
i += 1;
x = next_x().unwrap_or(x);
continue;
}

View File

@ -183,3 +183,22 @@ impl Fold for GenAlign {
self
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum LeftRightAlternator {
Left,
Right,
}
impl Iterator for LeftRightAlternator {
type Item = LeftRightAlternator;
fn next(&mut self) -> Option<Self::Item> {
let r = Some(*self);
match self {
Self::Left => *self = Self::Right,
Self::Right => *self = Self::Left,
}
r
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB