summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2023-09-13 13:45:05 +0200
committerLaurenz <laurmaedje@gmail.com>2023-09-13 13:45:05 +0200
commit68b365b35197dd2f7aca04f7fa9d712f7cee621d (patch)
treea92e3c1ea00901c45dadc294fb70a22e2528253d
parent8fb225feb4a10a916c239faaa130cf5aae164284 (diff)
Fix newline in text in math
Fixes #1948
-rw-r--r--crates/typst-library/src/math/ctx.rs76
-rw-r--r--tests/ref/bugs/math-text-break.pngbin0 -> 900 bytes
-rw-r--r--tests/typ/bugs/math-text-break.typ4
-rw-r--r--tests/typ/math/content.typ10
4 files changed, 59 insertions, 31 deletions
diff --git a/crates/typst-library/src/math/ctx.rs b/crates/typst-library/src/math/ctx.rs
index c992c0eb..59ba057f 100644
--- a/crates/typst-library/src/math/ctx.rs
+++ b/crates/typst-library/src/math/ctx.rs
@@ -2,6 +2,7 @@ use ttf_parser::gsub::SubstitutionSubtable;
use ttf_parser::math::MathValue;
use typst::font::{FontStyle, FontWeight};
use typst::model::realize;
+use typst::syntax::is_newline;
use unicode_segmentation::UnicodeSegmentation;
use super::*;
@@ -207,41 +208,64 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
FrameFragment::new(self, frame).into()
} else {
// Anything else is handled by Typst's standard text layout.
- let spaced = text.graphemes(true).nth(1).is_some();
let mut style = self.style;
if self.style.italic == Smart::Auto {
style = style.with_italic(false);
}
let text: EcoString = text.chars().map(|c| style.styled_char(c)).collect();
- let text = TextElem::packed(text)
- .styled(TextElem::set_top_edge(TopEdge::Metric(TopEdgeMetric::Bounds)))
- .styled(TextElem::set_bottom_edge(BottomEdge::Metric(
- BottomEdgeMetric::Bounds,
- )))
- .spanned(span);
- let par = ParElem::new(vec![text]);
-
- // There isn't a natural width for a paragraph in a math environment;
- // because it will be placed somewhere probably not at the left margin
- // it will overflow. So emulate an `hbox` instead and allow the paragraph
- // to extend as far as needed.
- let frame = par
- .layout(
- self.vt,
- self.outer.chain(&self.local),
- false,
- Size::splat(Abs::inf()),
- false,
- )?
- .into_frame();
- FrameFragment::new(self, frame)
- .with_class(MathClass::Alphabetic)
- .with_spaced(spaced)
- .into()
+ if text.contains(is_newline) {
+ let mut fragments = vec![];
+ for (i, piece) in text.split(is_newline).enumerate() {
+ if i != 0 {
+ fragments.push(MathFragment::Linebreak);
+ }
+ if !piece.is_empty() {
+ fragments.push(self.layout_complex_text(piece, span)?.into());
+ }
+ }
+ let mut frame = MathRow::new(fragments).into_frame(self);
+ let axis = scaled!(self, axis_height);
+ frame.set_baseline(frame.height() / 2.0 + axis);
+ FrameFragment::new(self, frame).into()
+ } else {
+ self.layout_complex_text(&text, span)?.into()
+ }
};
Ok(fragment)
}
+ pub fn layout_complex_text(
+ &mut self,
+ text: &str,
+ span: Span,
+ ) -> SourceResult<FrameFragment> {
+ let spaced = text.graphemes(true).nth(1).is_some();
+ let elem = TextElem::packed(text)
+ .styled(TextElem::set_top_edge(TopEdge::Metric(TopEdgeMetric::Bounds)))
+ .styled(TextElem::set_bottom_edge(BottomEdge::Metric(
+ BottomEdgeMetric::Bounds,
+ )))
+ .spanned(span);
+
+ // There isn't a natural width for a paragraph in a math environment;
+ // because it will be placed somewhere probably not at the left margin
+ // it will overflow. So emulate an `hbox` instead and allow the paragraph
+ // to extend as far as needed.
+ let frame = ParElem::new(vec![elem])
+ .layout(
+ self.vt,
+ self.outer.chain(&self.local),
+ false,
+ Size::splat(Abs::inf()),
+ false,
+ )?
+ .into_frame();
+
+ Ok(FrameFragment::new(self, frame)
+ .with_class(MathClass::Alphabetic)
+ .with_spaced(spaced))
+ }
+
pub fn styles(&self) -> StyleChain {
self.outer.chain(&self.local)
}
diff --git a/tests/ref/bugs/math-text-break.png b/tests/ref/bugs/math-text-break.png
new file mode 100644
index 00000000..a9842f25
--- /dev/null
+++ b/tests/ref/bugs/math-text-break.png
Binary files differ
diff --git a/tests/typ/bugs/math-text-break.typ b/tests/typ/bugs/math-text-break.typ
new file mode 100644
index 00000000..a8aa1d0a
--- /dev/null
+++ b/tests/typ/bugs/math-text-break.typ
@@ -0,0 +1,4 @@
+// Test text with linebreaks in math.
+
+---
+$ x := "a\nb\nc\nd\ne" $
diff --git a/tests/typ/math/content.typ b/tests/typ/math/content.typ
index 49f39733..e04ebb30 100644
--- a/tests/typ/math/content.typ
+++ b/tests/typ/math/content.typ
@@ -21,11 +21,11 @@ $#here[f] := #here[Hi there]$.
---
// Test boxes without a baseline act as if the baseline is at the base
#{
- box(stroke: 0.2pt, $a #box(stroke: 0.2pt, $a$)$)
- h(12pt)
- box(stroke: 0.2pt, $a #box(stroke: 0.2pt, $g$)$)
- h(12pt)
- box(stroke: 0.2pt, $g #box(stroke: 0.2pt, $g$)$)
+ box(stroke: 0.2pt, $a #box(stroke: 0.2pt, $a$)$)
+ h(12pt)
+ box(stroke: 0.2pt, $a #box(stroke: 0.2pt, $g$)$)
+ h(12pt)
+ box(stroke: 0.2pt, $g #box(stroke: 0.2pt, $g$)$)
}
---