diff --git a/crates/epaint/src/text/text_layout.rs b/crates/epaint/src/text/text_layout.rs index b3e6953015d..4fa3ba49427 100644 --- a/crates/epaint/src/text/text_layout.rs +++ b/crates/epaint/src/text/text_layout.rs @@ -220,7 +220,7 @@ fn rows_from_paragraphs( }); } else { let paragraph_max_x = paragraph.glyphs.last().unwrap().max_x(); - if paragraph_max_x <= job.wrap.max_width { + if paragraph_max_x <= job.effective_wrap_width() { // Early-out optimization: the whole paragraph fits on one row. let paragraph_min_x = paragraph.glyphs[0].pos.x; rows.push(Row { @@ -241,11 +241,7 @@ fn rows_from_paragraphs( } fn line_break(paragraph: &Paragraph, job: &LayoutJob, out_rows: &mut Vec, elided: &mut bool) { - let wrap_width_margin = if job.round_output_size_to_nearest_ui_point { - 0.5 - } else { - 0.0 - }; + let wrap_width = job.effective_wrap_width(); // Keeps track of good places to insert row break if we exceed `wrap_width`. let mut row_break_candidates = RowBreakCandidates::default(); @@ -262,7 +258,7 @@ fn line_break(paragraph: &Paragraph, job: &LayoutJob, out_rows: &mut Vec, e let potential_row_width = paragraph.glyphs[i].max_x() - row_start_x; - if job.wrap.max_width + wrap_width_margin < potential_row_width { + if wrap_width < potential_row_width { // Row break: if first_row_indentation > 0.0 @@ -420,7 +416,7 @@ fn replace_last_glyph_with_overflow_character( }); } - if row_width(row) <= job.wrap.max_width || row.glyphs.len() == 1 { + if row_width(row) <= job.effective_wrap_width() || row.glyphs.len() == 1 { return; // we are done } @@ -467,7 +463,7 @@ fn replace_last_glyph_with_overflow_character( } // Check if we're within width budget: - if row_width(row) <= job.wrap.max_width || row.glyphs.len() == 1 { + if row_width(row) <= job.effective_wrap_width() || row.glyphs.len() == 1 { return; // We are done } @@ -653,8 +649,8 @@ fn galley_from_rows( // If the user picked a too aggressive wrap width (e.g. more narrow than any individual glyph), // we should let the user know. } else { - // Make sure we don't over the max wrap width the user picked: - rect.max.x = rect.max.x.at_most(rect.min.x + job.wrap.max_width); + // Make sure we don't go over the max wrap width the user picked: + rect.max.x = rect.max.x.at_most(rect.min.x + job.wrap.max_width).floor(); } } diff --git a/crates/epaint/src/text/text_layout_types.rs b/crates/epaint/src/text/text_layout_types.rs index c754061b5f2..df20c63c31d 100644 --- a/crates/epaint/src/text/text_layout_types.rs +++ b/crates/epaint/src/text/text_layout_types.rs @@ -175,6 +175,18 @@ impl LayoutJob { } max_height } + + /// The wrap with, with a small margin in some cases. + pub fn effective_wrap_width(&self) -> f32 { + if self.round_output_size_to_nearest_ui_point { + // On a previous pass we may have rounded down by at most 0.5 and reported that as a width. + // egui may then set that width as the max width for subsequent frames, and it is important + // that we then don't wrap earlier. + self.wrap.max_width + 0.5 + } else { + self.wrap.max_width + } + } } impl std::hash::Hash for LayoutJob {