Skip to content

Commit 29e479e

Browse files
committed
Hang trailing whitespace before explicit newline
1 parent f435705 commit 29e479e

6 files changed

+73
-17
lines changed

parley/src/layout/line/greedy.rs

+22-7
Original file line numberDiff line numberDiff line change
@@ -535,14 +535,29 @@ impl<'a, B: Brush> BreakLines<'a, B> {
535535
line.metrics.trailing_whitespace = run
536536
.filter(|item| item.is_text_run())
537537
.and_then(|run| {
538-
let cluster = if self.layout.is_rtl() {
539-
self.layout.data.clusters[run.cluster_range.clone()].first()
538+
if self.layout.is_rtl() {
539+
// An RTL layout that has a line that ends with a space followed by a
540+
// forced line break will always have a separate run that looks like:
541+
// [" ", "\n"]. This means that the first cluster of a run with trailing
542+
// white space is always a space, regardless of whether the forced line
543+
// break follows, so we don't have to check for forced line breaks
544+
// explicitly.
545+
self.layout.data.clusters[run.cluster_range.clone()]
546+
.first()
547+
.filter(|cluster| cluster.info.whitespace().is_space_or_nbsp())
548+
.map(|cluster| cluster.advance)
540549
} else {
541-
self.layout.data.clusters[run.cluster_range.clone()].last()
542-
};
543-
cluster
544-
.filter(|cluster| cluster.info.whitespace().is_space_or_nbsp())
545-
.map(|cluster| cluster.advance)
550+
match &self.layout.data.clusters[run.cluster_range.clone()] {
551+
[.., a, b]
552+
if a.info.whitespace().is_space_or_nbsp()
553+
&& b.info.whitespace() == Whitespace::Newline =>
554+
{
555+
Some(a.advance + b.advance)
556+
}
557+
[.., a] if a.info.whitespace().is_space_or_nbsp() => Some(a.advance),
558+
_ => None,
559+
}
560+
}
546561
})
547562
.unwrap_or(0.0);
548563

parley/src/tests/test_basic.rs

+42-10
Original file line numberDiff line numberDiff line change
@@ -116,18 +116,50 @@ fn full_width_inbox() {
116116
fn trailing_whitespace() {
117117
let mut env = testenv!();
118118

119-
let text = "AAA BBB";
120-
let mut builder = env.ranged_builder(text);
121-
let mut layout = builder.build(text);
122-
layout.break_all_lines(Some(45.));
123-
layout.align(None, Alignment::Start, false);
119+
{
120+
let text = "AAA BBB";
121+
let mut builder = env.ranged_builder(text);
122+
let mut layout = builder.build(text);
123+
layout.break_all_lines(Some(45.));
124+
layout.align(None, Alignment::Start, false);
124125

125-
assert!(
126-
layout.width() < layout.full_width(),
127-
"Trailing whitespace should cause a difference between width and full_width"
128-
);
126+
env.with_name("soft_wrap").check_layout_snapshot(&layout);
127+
}
129128

130-
env.check_layout_snapshot(&layout);
129+
{
130+
let text = "AAA \nBBB";
131+
let mut builder = env.ranged_builder(text);
132+
let mut layout = builder.build(text);
133+
layout.break_all_lines(None);
134+
layout.align(None, Alignment::Start, false);
135+
136+
env.with_name("hard_wrap").check_layout_snapshot(&layout);
137+
}
138+
}
139+
140+
#[test]
141+
fn trailing_whitespace_rtl() {
142+
let mut env = testenv!();
143+
144+
{
145+
let text = "بببب ااااا";
146+
let mut builder = env.ranged_builder(text);
147+
let mut layout = builder.build(text);
148+
layout.break_all_lines(Some(45.));
149+
layout.align(None, Alignment::Start, false);
150+
151+
env.with_name("soft_wrap").check_layout_snapshot(&layout);
152+
}
153+
154+
{
155+
let text = "بببب \nااااا";
156+
let mut builder = env.ranged_builder(text);
157+
let mut layout = builder.build(text);
158+
layout.break_all_lines(None);
159+
layout.align(None, Alignment::Start, false);
160+
161+
env.with_name("hard_wrap").check_layout_snapshot(&layout);
162+
}
131163
}
132164

133165
#[test]
Loading
Loading
Loading

0 commit comments

Comments
 (0)