diff options
| author | Ian Wrzesinski <133046678+wrzian@users.noreply.github.com> | 2025-05-28 09:44:44 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-05-28 13:44:44 +0000 |
| commit | 9a95966302bae4d795cd2fba4b3beb6f41629221 (patch) | |
| tree | f98132c0cfab0c14748efad4d6ba089315cfb4d6 /crates/typst-layout/src | |
| parent | 9ac21b8524632c70ab9e090488a70085eabe4189 (diff) | |
Remove line break opportunity when math operator precededes a closing paren (#6216)
Diffstat (limited to 'crates/typst-layout/src')
| -rw-r--r-- | crates/typst-layout/src/math/run.rs | 31 |
1 files changed, 18 insertions, 13 deletions
diff --git a/crates/typst-layout/src/math/run.rs b/crates/typst-layout/src/math/run.rs index ae64368d..4ec76c25 100644 --- a/crates/typst-layout/src/math/run.rs +++ b/crates/typst-layout/src/math/run.rs @@ -278,6 +278,9 @@ impl MathRun { 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> { let mut items = vec![]; @@ -295,21 +298,24 @@ impl MathRun { let mut space_is_visible = false; - let is_relation = |f: &MathFragment| matches!(f.class(), MathClass::Relation); let is_space = |f: &MathFragment| { 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(); while let Some(fragment) = iter.next() { - if space_is_visible { - match fragment { - MathFragment::Space(width) | MathFragment::Spacing(width, _) => { - items.push(InlineItem::Space(width, true)); - continue; - } - _ => {} - } + if space_is_visible && is_space(&fragment) { + items.push(InlineItem::Space(fragment.width(), true)); + continue; } let class = fragment.class(); @@ -323,10 +329,9 @@ impl MathRun { frame.push_frame(pos, fragment.into_frame()); empty = false; - if class == MathClass::Binary - || (class == MathClass::Relation - && !iter.peek().map(is_relation).unwrap_or_default()) - { + // Split our current frame when we encounter a binary operator or + // relation so that there is a line-breaking opportunity. + if is_line_break_opportunity(class, iter.peek().map(|f| f.class())) { let mut frame_prev = std::mem::replace(&mut frame, Frame::soft(Size::zero())); |
