Fix newline in text in math

Fixes #1948
This commit is contained in:
Laurenz 2023-09-13 13:45:05 +02:00
parent 8fb225feb4
commit 68b365b351
4 changed files with 59 additions and 31 deletions

View File

@ -2,6 +2,7 @@ use ttf_parser::gsub::SubstitutionSubtable;
use ttf_parser::math::MathValue; use ttf_parser::math::MathValue;
use typst::font::{FontStyle, FontWeight}; use typst::font::{FontStyle, FontWeight};
use typst::model::realize; use typst::model::realize;
use typst::syntax::is_newline;
use unicode_segmentation::UnicodeSegmentation; use unicode_segmentation::UnicodeSegmentation;
use super::*; use super::*;
@ -207,25 +208,50 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
FrameFragment::new(self, frame).into() FrameFragment::new(self, frame).into()
} else { } else {
// Anything else is handled by Typst's standard text layout. // Anything else is handled by Typst's standard text layout.
let spaced = text.graphemes(true).nth(1).is_some();
let mut style = self.style; let mut style = self.style;
if self.style.italic == Smart::Auto { if self.style.italic == Smart::Auto {
style = style.with_italic(false); style = style.with_italic(false);
} }
let text: EcoString = text.chars().map(|c| style.styled_char(c)).collect(); let text: EcoString = text.chars().map(|c| style.styled_char(c)).collect();
let text = TextElem::packed(text) 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_top_edge(TopEdge::Metric(TopEdgeMetric::Bounds)))
.styled(TextElem::set_bottom_edge(BottomEdge::Metric( .styled(TextElem::set_bottom_edge(BottomEdge::Metric(
BottomEdgeMetric::Bounds, BottomEdgeMetric::Bounds,
))) )))
.spanned(span); .spanned(span);
let par = ParElem::new(vec![text]);
// There isn't a natural width for a paragraph in a math environment; // 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 // because it will be placed somewhere probably not at the left margin
// it will overflow. So emulate an `hbox` instead and allow the paragraph // it will overflow. So emulate an `hbox` instead and allow the paragraph
// to extend as far as needed. // to extend as far as needed.
let frame = par let frame = ParElem::new(vec![elem])
.layout( .layout(
self.vt, self.vt,
self.outer.chain(&self.local), self.outer.chain(&self.local),
@ -234,12 +260,10 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
false, false,
)? )?
.into_frame(); .into_frame();
FrameFragment::new(self, frame)
Ok(FrameFragment::new(self, frame)
.with_class(MathClass::Alphabetic) .with_class(MathClass::Alphabetic)
.with_spaced(spaced) .with_spaced(spaced))
.into()
};
Ok(fragment)
} }
pub fn styles(&self) -> StyleChain { pub fn styles(&self) -> StyleChain {

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 B

View File

@ -0,0 +1,4 @@
// Test text with linebreaks in math.
---
$ x := "a\nb\nc\nd\ne" $