Skip to content

Commit 486eb53

Browse files
committed
Implement yielding when height is exceeded
Signed-off-by: Nico Burns <[email protected]>
1 parent f44d4d6 commit 486eb53

File tree

1 file changed

+31
-8
lines changed

1 file changed

+31
-8
lines changed

parley/src/layout/line_break.rs

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ struct LineState {
4242
/// Of the line currently being built, the maximum line height seen so far.
4343
/// This represents a lower-bound on the eventual line height of the line.
4444
running_line_height: f32,
45+
max_height_exceeded: bool,
4546

4647
/// We lag the text-wrap-mode by one cluster due to line-breaking boundaries only
4748
/// being triggered on the cluster after the linebreak.
@@ -184,6 +185,7 @@ impl BreakerState {
184185
#[inline(always)]
185186
fn add_line_height(&mut self, height: f32) {
186187
self.line.running_line_height = self.line.running_line_height.max(height);
188+
self.line.max_height_exceeded = self.line.running_line_height > self.line_max_height;
187189
}
188190

189191
pub fn set_layout_max_advance(&mut self, advance: f32) {
@@ -259,6 +261,13 @@ impl<'a, B: Brush> BreakLines<'a, B> {
259261
}
260262
}
261263

264+
fn max_height_break_data(&self, line_height: f32) -> Option<YieldData> {
265+
Some(YieldData::MaxHeightExceeded(MaxHeightBreakData {
266+
advance: self.state.line.x,
267+
line_height,
268+
}))
269+
}
270+
262271
pub fn state(&self) -> &BreakerState {
263272
&self.state
264273
}
@@ -374,6 +383,11 @@ impl<'a, B: Brush> BreakLines<'a, B> {
374383

375384
// println!("BOX next_x: {}", next_x);
376385

386+
let box_will_be_appended = next_x <= max_advance || self.state.line.x == 0.0;
387+
if height_contribution > self.state.line_max_height && box_will_be_appended {
388+
return self.max_height_break_data(height_contribution);
389+
}
390+
377391
// If the box fits on the current line (or we are at the start of the current line)
378392
// then simply move on to the next item
379393
if next_x <= max_advance || self.state.line.text_wrap_mode != TextWrapMode::Wrap
@@ -425,6 +439,8 @@ impl<'a, B: Brush> BreakLines<'a, B> {
425439
let is_newline = whitespace == Whitespace::Newline;
426440
let is_space = whitespace.is_space_or_nbsp();
427441
let boundary = cluster.info().boundary();
442+
let line_height = run.metrics().line_height;
443+
let max_height_exceeded = self.state.line.max_height_exceeded;
428444
let style = &self.layout.data.styles[cluster.data.style_index as usize];
429445

430446
// Lag text_wrap_mode style by one cluster
@@ -441,10 +457,11 @@ impl<'a, B: Brush> BreakLines<'a, B> {
441457
// break_opportunity = true;
442458
}
443459
} else if is_newline {
444-
self.state.append_cluster_to_line(
445-
self.state.line.x,
446-
run.metrics().line_height,
447-
);
460+
if max_height_exceeded {
461+
return self.max_height_break_data(line_height);
462+
}
463+
self.state
464+
.append_cluster_to_line(self.state.line.x, line_height);
448465
if try_commit_line!(BreakReason::Explicit) {
449466
// TODO: can this be hoisted out of the conditional?
450467
self.state.cluster_idx += 1;
@@ -483,7 +500,9 @@ impl<'a, B: Brush> BreakLines<'a, B> {
483500
//
484501
// We simply append the cluster(s) to the current line
485502
if next_x <= max_advance {
486-
let line_height = run.metrics().line_height;
503+
if max_height_exceeded {
504+
return self.max_height_break_data(line_height);
505+
}
487506
self.state.append_cluster_to_line(next_x, line_height);
488507
self.state.cluster_idx += 1;
489508
if is_space {
@@ -500,7 +519,9 @@ impl<'a, B: Brush> BreakLines<'a, B> {
500519
//
501520
// We hang any overflowing whitespace and then line-break.
502521
if is_space && text_wrap_mode == TextWrapMode::Wrap {
503-
let line_height = run.metrics().line_height;
522+
if max_height_exceeded {
523+
return self.max_height_break_data(line_height);
524+
}
504525
self.state.append_cluster_to_line(next_x, line_height);
505526
if try_commit_line!(BreakReason::Regular) {
506527
// TODO: can this be hoisted out of the conditional?
@@ -551,7 +572,9 @@ impl<'a, B: Brush> BreakLines<'a, B> {
551572
//
552573
// We fall back to appending the content to the line.
553574
else {
554-
let line_height = run.metrics().line_height;
575+
if max_height_exceeded {
576+
return self.max_height_break_data(line_height);
577+
}
555578
self.state.append_cluster_to_line(next_x, line_height);
556579
self.state.cluster_idx += 1;
557580
}
@@ -597,7 +620,7 @@ impl<'a, B: Brush> BreakLines<'a, B> {
597620
self.state.line_y += line_break_data.line_height as f64;
598621
continue;
599622
}
600-
YieldData::MaxHeightExceeded(_) => continue,
623+
YieldData::MaxHeightExceeded(_) => continue, // unreachable because max_height is set to f32::MAX
601624
YieldData::InlineBoxBreak(_) => continue,
602625
}
603626
}

0 commit comments

Comments
 (0)