summaryrefslogtreecommitdiff
path: root/library/src/math
diff options
context:
space:
mode:
authorAlex Saveau <saveau.alexandre@gmail.com>2023-05-11 05:56:17 -0700
committerGitHub <noreply@github.com>2023-05-11 14:56:17 +0200
commite472b0347f84f39edf4655d39f8b5484870d0a76 (patch)
treed722a59d87a2e438b06ed88eab2a313d2e4bfd13 /library/src/math
parent27771bc329ab23cc551637fb3feac7b5689e64c7 (diff)
Alternate between right/left alignment in equations (#936)
Diffstat (limited to 'library/src/math')
-rw-r--r--library/src/math/row.rs55
1 files changed, 36 insertions, 19 deletions
diff --git a/library/src/math/row.rs b/library/src/math/row.rs
index a25178af..9b693bc1 100644
--- a/library/src/math/row.rs
+++ b/library/src/math/row.rs
@@ -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 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();
- let fragments = self.0.into_iter().peekable();
- let mut i = 0;
- for fragment in fragments {
+ 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;
}