Merge e7d5a293045022ea0aa28e10ac2f5e3b970d7ad5 into 9b09146a6b5e936966ed7ee73bce9dd2df3810ae

This commit is contained in:
Ian Wrzesinski 2025-05-07 08:55:36 +02:00 committed by GitHub
commit 4d23807b2b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 21 additions and 13 deletions

View File

@ -278,6 +278,9 @@ impl MathRun {
frame frame
} }
/// Convert this run of math fragments into a vector of inline items for
/// paragraph layout. Creates multiple fragments when relation or binary
/// operators are present to allow for line-breaking opportunities later.
pub fn into_par_items(self) -> Vec<InlineItem> { pub fn into_par_items(self) -> Vec<InlineItem> {
let mut items = vec![]; let mut items = vec![];
@ -295,21 +298,24 @@ impl MathRun {
let mut space_is_visible = false; let mut space_is_visible = false;
let is_relation = |f: &MathFragment| matches!(f.class(), MathClass::Relation);
let is_space = |f: &MathFragment| { let is_space = |f: &MathFragment| {
matches!(f, MathFragment::Space(_) | MathFragment::Spacing(_, _)) matches!(f, MathFragment::Space(_) | MathFragment::Spacing(_, _))
}; };
let is_line_break_opportunity = |class, next_fragment| match class {
// Don't split when two relations are in a row or when preceding a
// closing parenthesis.
MathClass::Binary => next_fragment != Some(MathClass::Closing),
MathClass::Relation => {
!matches!(next_fragment, Some(MathClass::Relation | MathClass::Closing))
}
_ => false,
};
let mut iter = self.0.into_iter().peekable(); let mut iter = self.0.into_iter().peekable();
while let Some(fragment) = iter.next() { while let Some(fragment) = iter.next() {
if space_is_visible { if space_is_visible && is_space(&fragment) {
match fragment { items.push(InlineItem::Space(fragment.width(), true));
MathFragment::Space(width) | MathFragment::Spacing(width, _) => { continue;
items.push(InlineItem::Space(width, true));
continue;
}
_ => {}
}
} }
let class = fragment.class(); let class = fragment.class();
@ -323,10 +329,9 @@ impl MathRun {
frame.push_frame(pos, fragment.into_frame()); frame.push_frame(pos, fragment.into_frame());
empty = false; empty = false;
if class == MathClass::Binary // Split our current frame when we encounter a binary operator or
|| (class == MathClass::Relation // relation so that there is a line-breaking opportunity.
&& !iter.peek().map(is_relation).unwrap_or_default()) if is_line_break_opportunity(class, iter.peek().map(|f| f.class())) {
{
let mut frame_prev = let mut frame_prev =
std::mem::replace(&mut frame, Frame::soft(Size::zero())); std::mem::replace(&mut frame, Frame::soft(Size::zero()));

Binary file not shown.

Before

Width:  |  Height:  |  Size: 439 B

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -99,6 +99,9 @@ Multiple trailing line breaks.
#let hrule(x) = box(line(length: x)) #let hrule(x) = box(line(length: x))
#hrule(90pt)$<;$\ #hrule(90pt)$<;$\
#hrule(95pt)$<;$\ #hrule(95pt)$<;$\
// We don't linebreak before a closing paren, but do before an opening paren.
#hrule(90pt)$<($\
#hrule(95pt)$<($
#hrule(90pt)$<)$\ #hrule(90pt)$<)$\
#hrule(95pt)$<)$ #hrule(95pt)$<)$