summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2024-12-11 16:46:10 +0100
committerGitHub <noreply@github.com>2024-12-11 15:46:10 +0000
commit521ceae889f15f2a93683ab776cd86a423e5dbed (patch)
tree9f81b78aef566843df943224aee8f661854b376b
parent5e0e58d26ef656836aae8d16477bb059e97883a3 (diff)
Fix crash due to consecutive weak spacing (#5562)
-rw-r--r--crates/typst-layout/src/inline/collect.rs37
-rw-r--r--crates/typst-layout/src/inline/linebreak.rs2
-rw-r--r--tests/ref/issue-5244-consecutive-weak-space-heading.pngbin0 -> 346 bytes
-rw-r--r--tests/ref/issue-5244-consecutive-weak-space.pngbin0 -> 194 bytes
-rw-r--r--tests/ref/issue-5253-consecutive-weak-space-math.pngbin0 -> 138 bytes
-rw-r--r--tests/suite/layout/spacing.typ18
6 files changed, 38 insertions, 19 deletions
diff --git a/crates/typst-layout/src/inline/collect.rs b/crates/typst-layout/src/inline/collect.rs
index fbcddee5..23e82c41 100644
--- a/crates/typst-layout/src/inline/collect.rs
+++ b/crates/typst-layout/src/inline/collect.rs
@@ -256,8 +256,7 @@ impl<'a> Collector<'a> {
}
fn push_text(&mut self, text: &str, styles: StyleChain<'a>) {
- self.full.push_str(text);
- self.push_segment(Segment::Text(text.len(), styles));
+ self.build_text(styles, |full| full.push_str(text));
}
fn build_text<F>(&mut self, styles: StyleChain<'a>, f: F)
@@ -266,33 +265,33 @@ impl<'a> Collector<'a> {
{
let prev = self.full.len();
f(&mut self.full);
- let len = self.full.len() - prev;
- self.push_segment(Segment::Text(len, styles));
- }
+ let segment_len = self.full.len() - prev;
- fn push_item(&mut self, item: Item<'a>) {
- self.full.push_str(item.textual());
- self.push_segment(Segment::Item(item));
- }
-
- fn push_segment(&mut self, segment: Segment<'a>) {
- match (self.segments.last_mut(), &segment) {
- // Merge adjacent text segments with the same styles.
- (Some(Segment::Text(last_len, last_styles)), Segment::Text(len, styles))
- if *last_styles == *styles =>
- {
- *last_len += *len;
+ // Merge adjacent text segments with the same styles.
+ if let Some(Segment::Text(last_len, last_styles)) = self.segments.last_mut() {
+ if *last_styles == styles {
+ *last_len += segment_len;
+ return;
}
+ }
+ self.segments.push(Segment::Text(segment_len, styles));
+ }
+
+ fn push_item(&mut self, item: Item<'a>) {
+ match (self.segments.last_mut(), &item) {
// Merge adjacent weak spacing by taking the maximum.
(
Some(Segment::Item(Item::Absolute(prev_amount, true))),
- Segment::Item(Item::Absolute(amount, true)),
+ Item::Absolute(amount, true),
) => {
*prev_amount = (*prev_amount).max(*amount);
}
- _ => self.segments.push(segment),
+ _ => {
+ self.full.push_str(item.textual());
+ self.segments.push(Segment::Item(item));
+ }
}
}
}
diff --git a/crates/typst-layout/src/inline/linebreak.rs b/crates/typst-layout/src/inline/linebreak.rs
index 236d6892..7b66fcdb 100644
--- a/crates/typst-layout/src/inline/linebreak.rs
+++ b/crates/typst-layout/src/inline/linebreak.rs
@@ -971,11 +971,13 @@ where
}
/// Estimates the metrics for the line spanned by the range.
+ #[track_caller]
fn estimate(&self, range: Range) -> T {
self.get(range.end) - self.get(range.start)
}
/// Get the metric at the given byte position.
+ #[track_caller]
fn get(&self, index: usize) -> T {
match index.checked_sub(1) {
None => T::default(),
diff --git a/tests/ref/issue-5244-consecutive-weak-space-heading.png b/tests/ref/issue-5244-consecutive-weak-space-heading.png
new file mode 100644
index 00000000..c1ef7924
--- /dev/null
+++ b/tests/ref/issue-5244-consecutive-weak-space-heading.png
Binary files differ
diff --git a/tests/ref/issue-5244-consecutive-weak-space.png b/tests/ref/issue-5244-consecutive-weak-space.png
new file mode 100644
index 00000000..7a102ddf
--- /dev/null
+++ b/tests/ref/issue-5244-consecutive-weak-space.png
Binary files differ
diff --git a/tests/ref/issue-5253-consecutive-weak-space-math.png b/tests/ref/issue-5253-consecutive-weak-space-math.png
new file mode 100644
index 00000000..a15646ca
--- /dev/null
+++ b/tests/ref/issue-5253-consecutive-weak-space-math.png
Binary files differ
diff --git a/tests/suite/layout/spacing.typ b/tests/suite/layout/spacing.typ
index f5938995..d5cd122c 100644
--- a/tests/suite/layout/spacing.typ
+++ b/tests/suite/layout/spacing.typ
@@ -58,3 +58,21 @@ This is the first line \ #h(2cm, weak: true) A new line
// Non-weak-spacing, on the other hand, is not removed.
This is the first line \ #h(2cm, weak: false) A new line
+
+--- issue-5244-consecutive-weak-space ---
+#set par(linebreaks: "optimized")
+#{
+ [A]
+ h(0.3em, weak: true)
+ h(0.3em, weak: true)
+ [B]
+}
+
+--- issue-5244-consecutive-weak-space-heading ---
+#set par(justify: true)
+#set heading(numbering: "I.")
+
+= #h(0.3em, weak: true) test
+
+--- issue-5253-consecutive-weak-space-math ---
+$= thin thin$ a