-
Notifications
You must be signed in to change notification settings - Fork 2k
Exclude \n when splitting Galleys
#7316
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
516a3b7
4e50c17
3af339f
022d342
b279216
9352dbe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -204,20 +204,12 @@ fn calculate_intrinsic_size( | |||
| ) -> Vec2 { | ||||
| let mut intrinsic_size = Vec2::ZERO; | ||||
| for (idx, paragraph) in paragraphs.iter().enumerate() { | ||||
| if paragraph.glyphs.is_empty() { | ||||
| if idx == 0 { | ||||
| intrinsic_size.y += point_scale.round_to_pixel(paragraph.empty_paragraph_height); | ||||
| } | ||||
| continue; | ||||
| } | ||||
| intrinsic_size.x = f32::max( | ||||
| paragraph | ||||
| .glyphs | ||||
| .last() | ||||
| .map(|l| l.max_x()) | ||||
| .unwrap_or_default(), | ||||
| intrinsic_size.x, | ||||
| ); | ||||
| let width = paragraph | ||||
| .glyphs | ||||
| .last() | ||||
| .map(|l| l.max_x()) | ||||
| .unwrap_or_default(); | ||||
| intrinsic_size.x = f32::max(intrinsic_size.x, width); | ||||
|
|
||||
| let mut height = paragraph | ||||
| .glyphs | ||||
|
|
@@ -253,7 +245,7 @@ fn rows_from_paragraphs( | |||
|
|
||||
| if paragraph.glyphs.is_empty() { | ||||
| rows.push(PlacedRow { | ||||
| pos: Pos2::ZERO, | ||||
| pos: pos2(0.0, f32::NAN), | ||||
| row: Arc::new(Row { | ||||
| section_index_at_start: paragraph.section_index_at_start, | ||||
| glyphs: vec![], | ||||
|
|
@@ -659,12 +651,12 @@ fn galley_from_rows( | |||
| let mut cursor_y = 0.0; | ||||
|
|
||||
| for placed_row in &mut rows { | ||||
| let mut max_row_height = first_row_min_height.max(placed_row.rect().height()); | ||||
| let mut max_row_height = first_row_min_height.at_least(placed_row.height()); | ||||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This really got me, changing the position here to NaN: egui/crates/epaint/src/text/text_layout.rs Line 250 in 4e50c17
Would cause the max_row_height here to change to 0. Took me a bit to see that this was due to getting the height from the rect instead of looking at the size directly. |
||||
| let row = Arc::make_mut(&mut placed_row.row); | ||||
|
|
||||
| first_row_min_height = 0.0; | ||||
| for glyph in &row.glyphs { | ||||
| max_row_height = max_row_height.max(glyph.line_height); | ||||
| max_row_height = max_row_height.at_least(glyph.line_height); | ||||
| } | ||||
| max_row_height = point_scale.round_to_pixel(max_row_height); | ||||
|
|
||||
|
|
@@ -1212,4 +1204,72 @@ mod tests { | |||
| assert_eq!(row.pos, Pos2::ZERO); | ||||
| assert_eq!(row.rect().max.x, row.glyphs.last().unwrap().max_x()); | ||||
| } | ||||
|
|
||||
| #[test] | ||||
| fn test_empty_row() { | ||||
| let mut fonts = FontsImpl::new( | ||||
| 1.0, | ||||
| 1024, | ||||
| AlphaFromCoverage::default(), | ||||
| FontDefinitions::default(), | ||||
| ); | ||||
|
|
||||
| let font_id = FontId::default(); | ||||
| let font_height = fonts.font(&font_id).row_height(); | ||||
|
|
||||
| let job = LayoutJob::simple(String::new(), font_id, Color32::WHITE, f32::INFINITY); | ||||
|
|
||||
| let galley = layout(&mut fonts, job.into()); | ||||
|
|
||||
| assert_eq!(galley.rows.len(), 1, "Expected one row"); | ||||
| assert_eq!( | ||||
| galley.rows[0].row.glyphs.len(), | ||||
| 0, | ||||
| "Expected no glyphs in the empty row" | ||||
| ); | ||||
| assert_eq!( | ||||
| galley.size(), | ||||
| Vec2::new(0.0, font_height.round()), | ||||
| "Unexpected galley size" | ||||
| ); | ||||
| assert_eq!( | ||||
| galley.intrinsic_size(), | ||||
| Vec2::new(0.0, font_height.round()), | ||||
| "Unexpected intrinsic size" | ||||
| ); | ||||
| } | ||||
|
|
||||
| #[test] | ||||
| fn test_end_with_newline() { | ||||
| let mut fonts = FontsImpl::new( | ||||
| 1.0, | ||||
| 1024, | ||||
| AlphaFromCoverage::default(), | ||||
| FontDefinitions::default(), | ||||
| ); | ||||
|
|
||||
| let font_id = FontId::default(); | ||||
| let font_height = fonts.font(&font_id).row_height(); | ||||
|
|
||||
| let job = LayoutJob::simple("Hi!\n".to_owned(), font_id, Color32::WHITE, f32::INFINITY); | ||||
|
|
||||
| let galley = layout(&mut fonts, job.into()); | ||||
|
|
||||
| assert_eq!(galley.rows.len(), 2, "Expected two rows"); | ||||
| assert_eq!( | ||||
| galley.rows[1].row.glyphs.len(), | ||||
| 0, | ||||
| "Expected no glyphs in the empty row" | ||||
| ); | ||||
| assert_eq!( | ||||
| galley.size().round(), | ||||
| Vec2::new(17.0, font_height.round() * 2.0), | ||||
| "Unexpected galley size" | ||||
| ); | ||||
| assert_eq!( | ||||
| galley.intrinsic_size().round(), | ||||
| Vec2::new(17.0, font_height.round() * 2.0), | ||||
| "Unexpected intrinsic size" | ||||
| ); | ||||
| } | ||||
| } | ||||
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -561,11 +561,7 @@ pub struct Galley { | |||||||||||
| /// tessellation. | ||||||||||||
| pub pixels_per_point: f32, | ||||||||||||
|
|
||||||||||||
| /// This is the size that a non-wrapped, non-truncated, non-justified version of the text | ||||||||||||
| /// would have. | ||||||||||||
| /// | ||||||||||||
| /// Useful for advanced layouting. | ||||||||||||
| pub intrinsic_size: Vec2, | ||||||||||||
| pub(crate) intrinsic_size: Vec2, | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| #[derive(Clone, Debug, PartialEq)] | ||||||||||||
|
|
@@ -801,6 +797,21 @@ impl Galley { | |||||||||||
| self.rect.size() | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| /// This is the size that a non-wrapped, non-truncated, non-justified version of the text | ||||||||||||
| /// would have. | ||||||||||||
| /// | ||||||||||||
| /// Useful for advanced layouting. | ||||||||||||
| #[inline] | ||||||||||||
| pub fn intrinsic_size(&self) -> Vec2 { | ||||||||||||
| // We do the rounding here instead of in `round_output_to_gui` so that rounding | ||||||||||||
| // errors don't accumulate when concatenating multiple galleys. | ||||||||||||
| if self.job.round_output_to_gui { | ||||||||||||
| self.intrinsic_size.round_ui() | ||||||||||||
| } else { | ||||||||||||
| self.intrinsic_size | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| pub(crate) fn round_output_to_gui(&mut self) { | ||||||||||||
| for placed_row in &mut self.rows { | ||||||||||||
| // Optimization: only call `make_mut` if necessary (can cause a deep clone) | ||||||||||||
|
|
@@ -827,8 +838,6 @@ impl Galley { | |||||||||||
| .at_most(rect.min.x + self.job.wrap.max_width) | ||||||||||||
| .floor_ui(); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| self.intrinsic_size = self.intrinsic_size.round_ui(); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| /// Append each galley under the previous one. | ||||||||||||
|
|
@@ -849,32 +858,28 @@ impl Galley { | |||||||||||
|
|
||||||||||||
| for (i, galley) in galleys.iter().enumerate() { | ||||||||||||
| let current_y_offset = merged_galley.rect.height(); | ||||||||||||
|
|
||||||||||||
| let mut rows = galley.rows.iter(); | ||||||||||||
| // As documented in `Row::ends_with_newline`, a '\n' will always create a | ||||||||||||
| // new `Row` immediately below the current one. Here it doesn't make sense | ||||||||||||
| // for us to append this new row so we just ignore it. | ||||||||||||
| let is_last_row = i + 1 == galleys.len(); | ||||||||||||
| if !is_last_row && !galley.elided { | ||||||||||||
| let popped = rows.next_back(); | ||||||||||||
| debug_assert_eq!(popped.unwrap().row.glyphs.len(), 0, "Bug in Galley::concat"); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| merged_galley.rows.extend(rows.map(|placed_row| { | ||||||||||||
| let new_pos = placed_row.pos + current_y_offset * Vec2::Y; | ||||||||||||
| let new_pos = new_pos.round_to_pixels(pixels_per_point); | ||||||||||||
| merged_galley.mesh_bounds = merged_galley | ||||||||||||
| .mesh_bounds | ||||||||||||
| .union(placed_row.visuals.mesh_bounds.translate(new_pos.to_vec2())); | ||||||||||||
| merged_galley.rect = merged_galley | ||||||||||||
| .rect | ||||||||||||
| .union(Rect::from_min_size(new_pos, placed_row.size)); | ||||||||||||
|
|
||||||||||||
| super::PlacedRow { | ||||||||||||
| pos: new_pos, | ||||||||||||
| row: placed_row.row.clone(), | ||||||||||||
| } | ||||||||||||
| })); | ||||||||||||
| let is_last_galley = i + 1 == galleys.len(); | ||||||||||||
|
|
||||||||||||
| merged_galley | ||||||||||||
| .rows | ||||||||||||
| .extend(galley.rows.iter().enumerate().map(|(row_idx, placed_row)| { | ||||||||||||
| let new_pos = placed_row.pos + current_y_offset * Vec2::Y; | ||||||||||||
| let new_pos = new_pos.round_to_pixels(pixels_per_point); | ||||||||||||
| merged_galley.mesh_bounds = merged_galley | ||||||||||||
| .mesh_bounds | ||||||||||||
| .union(placed_row.visuals.mesh_bounds.translate(new_pos.to_vec2())); | ||||||||||||
|
Comment on lines
+868
to
+870
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you think about adding a
Suggested change
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That'd be neat! |
||||||||||||
| merged_galley.rect = merged_galley | ||||||||||||
| .rect | ||||||||||||
| .union(Rect::from_min_size(new_pos, placed_row.size)); | ||||||||||||
|
|
||||||||||||
| let mut row = placed_row.row.clone(); | ||||||||||||
| let is_last_row_in_galley = row_idx + 1 == galley.rows.len(); | ||||||||||||
| if !is_last_galley && is_last_row_in_galley { | ||||||||||||
| // Since we remove the `\n` when splitting rows, we need to add it back here | ||||||||||||
| Arc::make_mut(&mut row).ends_with_newline = true; | ||||||||||||
| } | ||||||||||||
| super::PlacedRow { pos: new_pos, row } | ||||||||||||
| })); | ||||||||||||
|
|
||||||||||||
| merged_galley.num_vertices += galley.num_vertices; | ||||||||||||
| merged_galley.num_indices += galley.num_indices; | ||||||||||||
|
|
||||||||||||
Uh oh!
There was an error while loading. Please reload this page.