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

View File

@ -183,3 +183,22 @@ impl Fold for GenAlign {
self 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