diff --git a/crates/doc/src/tests.rs b/crates/doc/src/tests.rs index 928dca55..41e233c4 100644 --- a/crates/doc/src/tests.rs +++ b/crates/doc/src/tests.rs @@ -560,6 +560,16 @@ fn is_ancestor_holds_for_very_deep_chains() { assert!(matches!(d.reparent(root, leaf, None), Err(DocError::Cycle(..)))); } +#[test] +fn text_insert_at_run_boundary_keeps_runs_disjoint() { + let mut t = TextData::new("0123456789"); + t.restyle(0, 5, |s| s.font_size = 20.0); + t.restyle(5, 10, |s| s.font_size = 30.0); + t.replace_range(5, 5, "xx"); + let runs: Vec<(usize, usize)> = t.runs.iter().map(|r| (r.start, r.end)).collect(); + assert_eq!(runs, vec![(0, 7), (7, 12)]); +} + #[test] fn many_small_vector_subpaths_build_and_stroke_without_rescans() { // Many closed subpaths whose last point repeats the start (#F-332), a long open chain (#F-334) diff --git a/crates/doc/src/text.rs b/crates/doc/src/text.rs index 458426ad..d2abfed9 100644 --- a/crates/doc/src/text.rs +++ b/crates/doc/src/text.rs @@ -579,7 +579,14 @@ impl TextData { } self.runs.sort_by_key(|r| r.start); let mut merged: Vec = Vec::with_capacity(self.runs.len()); - for r in std::mem::take(&mut self.runs) { + for mut r in std::mem::take(&mut self.runs) { + // Runs never overlap: a later run starts where the previous one ends at the earliest. + if let Some(prev) = merged.last() { + r.start = r.start.max(prev.end); + if r.start >= r.end { + continue; + } + } match merged.last_mut() { Some(prev) if prev.end == r.start && prev.style == r.style => prev.end = r.end, _ => merged.push(r),