1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-29 21:00:03 -04:00

Move ends_with_newline back into Row

This commit is contained in:
Fishhh
2024-11-30 15:38:58 +01:00
parent 6147ff3668
commit 66c83c31ce
3 changed files with 64 additions and 57 deletions

View File

@@ -739,7 +739,9 @@ impl GalleyCache {
let mut text_left = job.text.as_str();
let mut first_row_min_height = job.first_row_min_height;
loop {
let end = text_left.find('\n').map_or(job.text.len(), |i| i + current);
let end = text_left
.find('\n')
.map_or(job.text.len(), |i| i + current + 1);
let start = current;
let mut line_job = LayoutJob {
@@ -749,8 +751,7 @@ impl GalleyCache {
..job.wrap
},
sections: Vec::new(),
// Prevent an infinite recursion
break_on_newline: false,
break_on_newline: true,
halign: job.halign,
justify: job.justify,
first_row_min_height,
@@ -782,28 +783,14 @@ impl GalleyCache {
current = section_end;
}
// If the current line is empty, add an extra offset to make sure it's not omitted
// because the resulting galley will have a height of zero.
let extra_y_offset = if start == end && end != job.text.len() {
while job.sections[current_section].byte_range.end == end {
current_section += 1;
}
let format = &job.sections[current_section].format;
format
.line_height
.unwrap_or(fonts.row_height(&format.font_id))
} else {
0.0
};
let galley = self.layout(fonts, line_job);
let galley = self.layout_component_line(fonts, line_job);
// This will prevent us from invalidating cache entries unnecessarily
if left_max_rows != usize::MAX {
left_max_rows -= galley.rows.len();
}
galleys.push((galley, extra_y_offset));
galleys.push(galley);
current = end + 1;
current = end;
if current >= job.text.len() {
break;
} else {
@@ -822,29 +809,30 @@ impl GalleyCache {
pixels_per_point: fonts.pixels_per_point,
};
for (galley, extra_y_offset) in galleys {
for (i, galley) in galleys.iter().enumerate() {
let current_offset = emath::vec2(0.0, merged_galley.rect.height());
merged_galley
.rows
.extend(galley.rows.iter().map(|placed_row| {
let new_pos = placed_row.pos + current_offset;
merged_galley.mesh_bounds = merged_galley
.mesh_bounds
.union(placed_row.visuals.mesh_bounds.translate(new_pos.to_vec2()));
super::PlacedRow {
row: placed_row.row.clone(),
pos: round_to_pixel(new_pos),
ends_with_newline: placed_row.ends_with_newline,
}
}));
if let Some(last) = merged_galley.rows.last_mut() {
last.ends_with_newline = true;
let mut rows = galley.rows.iter();
if i != galleys.len() - 1 && !galley.elided {
let popped = rows.next_back();
debug_assert_eq!(popped.unwrap().row.glyphs.len(), 0);
}
merged_galley.rect = merged_galley
.rect
.union(galley.rect.translate(current_offset));
merged_galley.rect.max.y += extra_y_offset;
merged_galley.rows.extend(rows.map(|placed_row| {
let new_pos = round_to_pixel(placed_row.pos + current_offset);
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(emath::Rect::from_min_size(new_pos, placed_row.size));
super::PlacedRow {
row: placed_row.row.clone(),
pos: new_pos,
}
}));
merged_galley.num_vertices += galley.num_vertices;
merged_galley.num_indices += galley.num_indices;
if galley.elided {
@@ -853,13 +841,30 @@ impl GalleyCache {
}
}
if let Some(last) = merged_galley.rows.last_mut() {
last.ends_with_newline = false;
}
merged_galley
}
fn layout_component_line(&mut self, fonts: &mut FontsImpl, job: LayoutJob) -> Arc<Galley> {
let hash = crate::util::hash(&job);
match self.cache.entry(hash) {
std::collections::hash_map::Entry::Occupied(entry) => {
let cached = entry.into_mut();
cached.last_used = self.generation;
cached.galley.clone()
}
std::collections::hash_map::Entry::Vacant(entry) => {
let galley = super::layout(fonts, job.into());
let galley = Arc::new(galley);
entry.insert(CachedGalley {
last_used: self.generation,
galley: galley.clone(),
});
galley
}
}
}
fn layout(&mut self, fonts: &mut FontsImpl, mut job: LayoutJob) -> Arc<Galley> {
if job.wrap.max_width.is_finite() {
// Protect against rounding errors in egui layout code.

View File

@@ -220,9 +220,9 @@ fn rows_from_paragraphs(
glyphs: vec![],
visuals: Default::default(),
size: vec2(0.0, paragraph.empty_paragraph_height),
ends_with_newline: !is_last_paragraph,
}),
pos: pos2(paragraph.cursor_x, 0.0),
ends_with_newline: !is_last_paragraph,
});
} else {
let paragraph_max_x = paragraph.glyphs.last().unwrap().max_x();
@@ -236,13 +236,15 @@ fn rows_from_paragraphs(
glyphs: paragraph.glyphs,
visuals: Default::default(),
size: rect.size(),
ends_with_newline: !is_last_paragraph,
}),
pos: rect.min,
ends_with_newline: !is_last_paragraph,
});
} else {
line_break(&paragraph, job, &mut rows, elided);
rows.last_mut().unwrap().ends_with_newline = !is_last_paragraph;
let placed_row = rows.last_mut().unwrap();
let row = Arc::get_mut(&mut placed_row.row).unwrap();
row.ends_with_newline = !is_last_paragraph;
}
}
}
@@ -288,9 +290,9 @@ fn line_break(
glyphs: vec![],
visuals: Default::default(),
size: rect.size(),
ends_with_newline: false,
}),
pos: rect.min,
ends_with_newline: false,
});
row_start_x += first_row_indentation;
first_row_indentation = 0.0;
@@ -316,9 +318,9 @@ fn line_break(
glyphs,
visuals: Default::default(),
size: rect.size(),
ends_with_newline: false,
}),
pos: rect.min,
ends_with_newline: false,
});
// Start a new row:
@@ -359,9 +361,9 @@ fn line_break(
glyphs,
visuals: Default::default(),
size: rect.size(),
ends_with_newline: false,
}),
pos: rect.min,
ends_with_newline: false,
});
}
}

View File

@@ -546,13 +546,6 @@ pub struct PlacedRow {
/// The position of this [`Row`] relative to the galley.
pub pos: Pos2,
/// If true, this [`PlacedRow`] came from a paragraph ending with a `\n`.
/// The `\n` itself is omitted from [`Row::glyphs`].
/// A `\n` in the input text always creates a new [`PlacedRow`] below it,
/// so that text that ends with `\n` has an empty [`PlacedRow`] last.
/// This also implies that the last [`PlacedRow`] in a [`Galley`] always has `ends_with_newline == false`.
pub ends_with_newline: bool,
}
impl PlacedRow {
@@ -586,6 +579,13 @@ pub struct Row {
/// The mesh, ready to be rendered.
pub visuals: RowVisuals,
/// If true, this [`Row`] came from a paragraph ending with a `\n`.
/// The `\n` itself is omitted from [`glyphs`].
/// A `\n` in the input text always creates a new [`Row`] below it,
/// so that text that ends with `\n` has an empty [`Row`] last.
/// This also implies that the last [`Row`] in a [`Galley`] always has `ends_with_newline == false`.
pub ends_with_newline: bool,
}
/// The tessellated output of a row.