diff --git a/parley/src/layout/line/greedy.rs b/parley/src/layout/line/greedy.rs index fd08b04b..410a87d0 100644 --- a/parley/src/layout/line/greedy.rs +++ b/parley/src/layout/line/greedy.rs @@ -535,14 +535,29 @@ impl<'a, B: Brush> BreakLines<'a, B> { line.metrics.trailing_whitespace = run .filter(|item| item.is_text_run()) .and_then(|run| { - let cluster = if self.layout.is_rtl() { - self.layout.data.clusters[run.cluster_range.clone()].first() + if self.layout.is_rtl() { + // An RTL layout that has a line that ends with a space followed by a + // forced line break will always have a separate run that looks like: + // [" ", "\n"]. This means that the first cluster of a run with trailing + // white space is always a space, regardless of whether the forced line + // break follows, so we don't have to check for forced line breaks + // explicitly. + self.layout.data.clusters[run.cluster_range.clone()] + .first() + .filter(|cluster| cluster.info.whitespace().is_space_or_nbsp()) + .map(|cluster| cluster.advance) } else { - self.layout.data.clusters[run.cluster_range.clone()].last() - }; - cluster - .filter(|cluster| cluster.info.whitespace().is_space_or_nbsp()) - .map(|cluster| cluster.advance) + match &self.layout.data.clusters[run.cluster_range.clone()] { + [.., a, b] + if a.info.whitespace().is_space_or_nbsp() + && b.info.whitespace() == Whitespace::Newline => + { + Some(a.advance + b.advance) + } + [.., a] if a.info.whitespace().is_space_or_nbsp() => Some(a.advance), + _ => None, + } + } }) .unwrap_or(0.0); diff --git a/parley/src/tests/test_basic.rs b/parley/src/tests/test_basic.rs index 28fc0a8c..a59341b4 100644 --- a/parley/src/tests/test_basic.rs +++ b/parley/src/tests/test_basic.rs @@ -116,18 +116,50 @@ fn full_width_inbox() { fn trailing_whitespace() { let mut env = testenv!(); - let text = "AAA BBB"; - let mut builder = env.ranged_builder(text); - let mut layout = builder.build(text); - layout.break_all_lines(Some(45.)); - layout.align(None, Alignment::Start, false); + { + let text = "AAA BBB"; + let mut builder = env.ranged_builder(text); + let mut layout = builder.build(text); + layout.break_all_lines(Some(45.)); + layout.align(None, Alignment::Start, false); - assert!( - layout.width() < layout.full_width(), - "Trailing whitespace should cause a difference between width and full_width" - ); + env.with_name("soft_wrap").check_layout_snapshot(&layout); + } - env.check_layout_snapshot(&layout); + { + let text = "AAA \nBBB"; + let mut builder = env.ranged_builder(text); + let mut layout = builder.build(text); + layout.break_all_lines(None); + layout.align(None, Alignment::Start, false); + + env.with_name("hard_wrap").check_layout_snapshot(&layout); + } +} + +#[test] +fn trailing_whitespace_rtl() { + let mut env = testenv!(); + + { + let text = "بببب ااااا"; + let mut builder = env.ranged_builder(text); + let mut layout = builder.build(text); + layout.break_all_lines(Some(45.)); + layout.align(None, Alignment::Start, false); + + env.with_name("soft_wrap").check_layout_snapshot(&layout); + } + + { + let text = "بببب \nااااا"; + let mut builder = env.ranged_builder(text); + let mut layout = builder.build(text); + layout.break_all_lines(None); + layout.align(None, Alignment::Start, false); + + env.with_name("hard_wrap").check_layout_snapshot(&layout); + } } #[test] diff --git a/parley/tests/snapshots/trailing_whitespace-0.png b/parley/tests/snapshots/trailing_whitespace-hard_wrap.png similarity index 100% rename from parley/tests/snapshots/trailing_whitespace-0.png rename to parley/tests/snapshots/trailing_whitespace-hard_wrap.png diff --git a/parley/tests/snapshots/trailing_whitespace-soft_wrap.png b/parley/tests/snapshots/trailing_whitespace-soft_wrap.png new file mode 100644 index 00000000..47108d1d --- /dev/null +++ b/parley/tests/snapshots/trailing_whitespace-soft_wrap.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2c74ef51f92b44fd0e365f3a8cbc405a79e1e39a960ab9207608fe110e9e866f +size 3038 diff --git a/parley/tests/snapshots/trailing_whitespace_rtl-hard_wrap.png b/parley/tests/snapshots/trailing_whitespace_rtl-hard_wrap.png new file mode 100644 index 00000000..e0cbe2dc --- /dev/null +++ b/parley/tests/snapshots/trailing_whitespace_rtl-hard_wrap.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6a5ce4cfcb92948523da41a2c780867dc6ea11ce42548a4b36ee8b27aa2f561a +size 2606 diff --git a/parley/tests/snapshots/trailing_whitespace_rtl-soft_wrap.png b/parley/tests/snapshots/trailing_whitespace_rtl-soft_wrap.png new file mode 100644 index 00000000..e0cbe2dc --- /dev/null +++ b/parley/tests/snapshots/trailing_whitespace_rtl-soft_wrap.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6a5ce4cfcb92948523da41a2c780867dc6ea11ce42548a4b36ee8b27aa2f561a +size 2606