mirror of
https://github.com/typst/typst
synced 2025-05-16 18:15:29 +08:00
Alternate between right/left alignment in equations (#936)
This commit is contained in:
parent
27771bc329
commit
e472b0347f
@ -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();
|
||||||
for fragment in self.iter() {
|
if !points.is_empty() && align != Align::Left {
|
||||||
offset -= fragment.width();
|
let mut width = Abs::zero();
|
||||||
if matches!(fragment, MathFragment::Align) {
|
for fragment in self.iter() {
|
||||||
x = offset;
|
if matches!(fragment, MathFragment::Align) {
|
||||||
break;
|
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 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;
|
||||||
|
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 matches!(fragment, MathFragment::Align) {
|
||||||
if let Some(&point) = points.get(i) {
|
x = next_x().unwrap_or(x);
|
||||||
x = point;
|
|
||||||
}
|
|
||||||
i += 1;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 |
Loading…
x
Reference in New Issue
Block a user