mirror of
https://github.com/emilk/egui.git
synced 2026-09-02 14:50:03 -04:00
Move ends_with_newline back into Row
This commit is contained in:
@@ -739,7 +739,9 @@ impl GalleyCache {
|
|||||||
let mut text_left = job.text.as_str();
|
let mut text_left = job.text.as_str();
|
||||||
let mut first_row_min_height = job.first_row_min_height;
|
let mut first_row_min_height = job.first_row_min_height;
|
||||||
loop {
|
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 start = current;
|
||||||
|
|
||||||
let mut line_job = LayoutJob {
|
let mut line_job = LayoutJob {
|
||||||
@@ -749,8 +751,7 @@ impl GalleyCache {
|
|||||||
..job.wrap
|
..job.wrap
|
||||||
},
|
},
|
||||||
sections: Vec::new(),
|
sections: Vec::new(),
|
||||||
// Prevent an infinite recursion
|
break_on_newline: true,
|
||||||
break_on_newline: false,
|
|
||||||
halign: job.halign,
|
halign: job.halign,
|
||||||
justify: job.justify,
|
justify: job.justify,
|
||||||
first_row_min_height,
|
first_row_min_height,
|
||||||
@@ -782,28 +783,14 @@ impl GalleyCache {
|
|||||||
current = section_end;
|
current = section_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the current line is empty, add an extra offset to make sure it's not omitted
|
let galley = self.layout_component_line(fonts, line_job);
|
||||||
// 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);
|
|
||||||
// This will prevent us from invalidating cache entries unnecessarily
|
// This will prevent us from invalidating cache entries unnecessarily
|
||||||
if left_max_rows != usize::MAX {
|
if left_max_rows != usize::MAX {
|
||||||
left_max_rows -= galley.rows.len();
|
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() {
|
if current >= job.text.len() {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
@@ -822,29 +809,30 @@ impl GalleyCache {
|
|||||||
pixels_per_point: fonts.pixels_per_point,
|
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());
|
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 {
|
let mut rows = galley.rows.iter();
|
||||||
row: placed_row.row.clone(),
|
if i != galleys.len() - 1 && !galley.elided {
|
||||||
pos: round_to_pixel(new_pos),
|
let popped = rows.next_back();
|
||||||
ends_with_newline: placed_row.ends_with_newline,
|
debug_assert_eq!(popped.unwrap().row.glyphs.len(), 0);
|
||||||
}
|
|
||||||
}));
|
|
||||||
if let Some(last) = merged_galley.rows.last_mut() {
|
|
||||||
last.ends_with_newline = true;
|
|
||||||
}
|
}
|
||||||
merged_galley.rect = merged_galley
|
|
||||||
.rect
|
merged_galley.rows.extend(rows.map(|placed_row| {
|
||||||
.union(galley.rect.translate(current_offset));
|
let new_pos = round_to_pixel(placed_row.pos + current_offset);
|
||||||
merged_galley.rect.max.y += extra_y_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_vertices += galley.num_vertices;
|
||||||
merged_galley.num_indices += galley.num_indices;
|
merged_galley.num_indices += galley.num_indices;
|
||||||
if galley.elided {
|
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
|
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> {
|
fn layout(&mut self, fonts: &mut FontsImpl, mut job: LayoutJob) -> Arc<Galley> {
|
||||||
if job.wrap.max_width.is_finite() {
|
if job.wrap.max_width.is_finite() {
|
||||||
// Protect against rounding errors in egui layout code.
|
// Protect against rounding errors in egui layout code.
|
||||||
|
|||||||
@@ -220,9 +220,9 @@ fn rows_from_paragraphs(
|
|||||||
glyphs: vec![],
|
glyphs: vec![],
|
||||||
visuals: Default::default(),
|
visuals: Default::default(),
|
||||||
size: vec2(0.0, paragraph.empty_paragraph_height),
|
size: vec2(0.0, paragraph.empty_paragraph_height),
|
||||||
|
ends_with_newline: !is_last_paragraph,
|
||||||
}),
|
}),
|
||||||
pos: pos2(paragraph.cursor_x, 0.0),
|
pos: pos2(paragraph.cursor_x, 0.0),
|
||||||
ends_with_newline: !is_last_paragraph,
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
let paragraph_max_x = paragraph.glyphs.last().unwrap().max_x();
|
let paragraph_max_x = paragraph.glyphs.last().unwrap().max_x();
|
||||||
@@ -236,13 +236,15 @@ fn rows_from_paragraphs(
|
|||||||
glyphs: paragraph.glyphs,
|
glyphs: paragraph.glyphs,
|
||||||
visuals: Default::default(),
|
visuals: Default::default(),
|
||||||
size: rect.size(),
|
size: rect.size(),
|
||||||
|
ends_with_newline: !is_last_paragraph,
|
||||||
}),
|
}),
|
||||||
pos: rect.min,
|
pos: rect.min,
|
||||||
ends_with_newline: !is_last_paragraph,
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
line_break(¶graph, job, &mut rows, elided);
|
line_break(¶graph, 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![],
|
glyphs: vec![],
|
||||||
visuals: Default::default(),
|
visuals: Default::default(),
|
||||||
size: rect.size(),
|
size: rect.size(),
|
||||||
|
ends_with_newline: false,
|
||||||
}),
|
}),
|
||||||
pos: rect.min,
|
pos: rect.min,
|
||||||
ends_with_newline: false,
|
|
||||||
});
|
});
|
||||||
row_start_x += first_row_indentation;
|
row_start_x += first_row_indentation;
|
||||||
first_row_indentation = 0.0;
|
first_row_indentation = 0.0;
|
||||||
@@ -316,9 +318,9 @@ fn line_break(
|
|||||||
glyphs,
|
glyphs,
|
||||||
visuals: Default::default(),
|
visuals: Default::default(),
|
||||||
size: rect.size(),
|
size: rect.size(),
|
||||||
|
ends_with_newline: false,
|
||||||
}),
|
}),
|
||||||
pos: rect.min,
|
pos: rect.min,
|
||||||
ends_with_newline: false,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Start a new row:
|
// Start a new row:
|
||||||
@@ -359,9 +361,9 @@ fn line_break(
|
|||||||
glyphs,
|
glyphs,
|
||||||
visuals: Default::default(),
|
visuals: Default::default(),
|
||||||
size: rect.size(),
|
size: rect.size(),
|
||||||
|
ends_with_newline: false,
|
||||||
}),
|
}),
|
||||||
pos: rect.min,
|
pos: rect.min,
|
||||||
ends_with_newline: false,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -546,13 +546,6 @@ pub struct PlacedRow {
|
|||||||
|
|
||||||
/// The position of this [`Row`] relative to the galley.
|
/// The position of this [`Row`] relative to the galley.
|
||||||
pub pos: Pos2,
|
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 {
|
impl PlacedRow {
|
||||||
@@ -586,6 +579,13 @@ pub struct Row {
|
|||||||
|
|
||||||
/// The mesh, ready to be rendered.
|
/// The mesh, ready to be rendered.
|
||||||
pub visuals: RowVisuals,
|
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.
|
/// The tessellated output of a row.
|
||||||
|
|||||||
Reference in New Issue
Block a user