mirror of
https://github.com/emilk/egui.git
synced 2026-09-01 06:10:06 -04:00
Fix section_index
This commit is contained in:
@@ -4,7 +4,7 @@ use crate::{
|
|||||||
mutex::{Mutex, MutexGuard},
|
mutex::{Mutex, MutexGuard},
|
||||||
text::{
|
text::{
|
||||||
font::{Font, FontImpl},
|
font::{Font, FontImpl},
|
||||||
Galley, LayoutJob,
|
Galley, LayoutJob, LayoutSection,
|
||||||
},
|
},
|
||||||
TextureAtlas,
|
TextureAtlas,
|
||||||
};
|
};
|
||||||
@@ -809,7 +809,8 @@ impl GalleyCache {
|
|||||||
fonts: &mut FontsImpl,
|
fonts: &mut FontsImpl,
|
||||||
job: Arc<LayoutJob>,
|
job: Arc<LayoutJob>,
|
||||||
) -> Galley {
|
) -> Galley {
|
||||||
let mut current_section = 0;
|
profiling::function_scope!();
|
||||||
|
|
||||||
let mut current = 0;
|
let mut current = 0;
|
||||||
let mut max_rows_remaining = job.wrap.max_rows;
|
let mut max_rows_remaining = job.wrap.max_rows;
|
||||||
let mut galleys = Vec::new();
|
let mut galleys = Vec::new();
|
||||||
@@ -839,29 +840,35 @@ impl GalleyCache {
|
|||||||
round_output_to_gui: job.round_output_to_gui,
|
round_output_to_gui: job.round_output_to_gui,
|
||||||
};
|
};
|
||||||
|
|
||||||
while current < end {
|
// Keep all (previous) sections (so the correct `section_index` is outputted),
|
||||||
let mut s = &job.sections[current_section];
|
// but shift their byte ranges:
|
||||||
while s.byte_range.end <= current {
|
paragraph_job.sections = job
|
||||||
current_section += 1;
|
.sections
|
||||||
s = &job.sections[current_section];
|
.iter()
|
||||||
}
|
.cloned()
|
||||||
|
.filter_map(|section| {
|
||||||
debug_assert!(s.byte_range.contains(¤t), "Bug in LayoutJob splitter");
|
let LayoutSection {
|
||||||
let section_end = s.byte_range.end.min(end);
|
leading_space,
|
||||||
paragraph_job.sections.push(crate::text::LayoutSection {
|
byte_range,
|
||||||
// Leading space should only be added to the first section
|
format,
|
||||||
// if the there are multiple sections that will be created
|
} = section;
|
||||||
// from splitting the current section.
|
if end <= byte_range.start {
|
||||||
leading_space: if current == s.byte_range.start {
|
None
|
||||||
s.leading_space
|
|
||||||
} else {
|
} else {
|
||||||
0.0
|
let byte_range = byte_range.start.saturating_sub(start)
|
||||||
},
|
..byte_range.end.saturating_sub(start).min(end - start);
|
||||||
byte_range: current - start..section_end - start,
|
Some(LayoutSection {
|
||||||
format: s.format.clone(),
|
leading_space: if byte_range.end == 0 {
|
||||||
});
|
0.0 // this sections is behind us (unused in this paragraph)
|
||||||
current = section_end;
|
} else {
|
||||||
}
|
leading_space
|
||||||
|
},
|
||||||
|
byte_range,
|
||||||
|
format,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
let galley = self.layout(fonts, paragraph_job, false);
|
let galley = self.layout(fonts, paragraph_job, false);
|
||||||
|
|
||||||
@@ -1005,8 +1012,7 @@ mod tests {
|
|||||||
f32::INFINITY,
|
f32::INFINITY,
|
||||||
),
|
),
|
||||||
LayoutJob::simple(
|
LayoutJob::simple(
|
||||||
"The is some text that may be long.\nDet kanske också finns lite ÅÄÖ här."
|
"This some text that may be long.\nDet kanske också finns lite ÅÄÖ här.".to_owned(),
|
||||||
.to_owned(),
|
|
||||||
FontId::new(14.0, FontFamily::Proportional),
|
FontId::new(14.0, FontFamily::Proportional),
|
||||||
Color32::WHITE,
|
Color32::WHITE,
|
||||||
50.0,
|
50.0,
|
||||||
@@ -1018,7 +1024,7 @@ mod tests {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
job.append(
|
job.append(
|
||||||
"The first paragraph has some leading space.\n",
|
"1st paragraph has some leading space.\n",
|
||||||
16.0,
|
16.0,
|
||||||
TextFormat {
|
TextFormat {
|
||||||
font_id: FontId::new(14.0, FontFamily::Proportional),
|
font_id: FontId::new(14.0, FontFamily::Proportional),
|
||||||
@@ -1026,7 +1032,7 @@ mod tests {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
job.append(
|
job.append(
|
||||||
"The second paragraph has underline and strikthrough, and has some non-ASCII characters:\n ÅÄÖ.",
|
"2nd paragraph has underline and strikthrough, and has some non-ASCII characters:\n ÅÄÖ.",
|
||||||
0.0,
|
0.0,
|
||||||
TextFormat {
|
TextFormat {
|
||||||
font_id: FontId::new(15.0, FontFamily::Monospace),
|
font_id: FontId::new(15.0, FontFamily::Monospace),
|
||||||
@@ -1036,7 +1042,7 @@ mod tests {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
job.append(
|
job.append(
|
||||||
"The last paragraph is kind of boring, but has italics.\nAnd a newline",
|
"3rd paragraph is kind of boring, but has italics.\nAnd a newline",
|
||||||
0.0,
|
0.0,
|
||||||
TextFormat {
|
TextFormat {
|
||||||
font_id: FontId::new(10.0, FontFamily::Proportional),
|
font_id: FontId::new(10.0, FontFamily::Proportional),
|
||||||
@@ -1061,11 +1067,34 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
for job in jobs() {
|
for job in jobs() {
|
||||||
let as_whole = GalleyCache::default().layout(&mut fonts, job.clone(), false);
|
let whole = GalleyCache::default().layout(&mut fonts, job.clone(), false);
|
||||||
|
|
||||||
let split = GalleyCache::default().layout(&mut fonts, job.clone(), true);
|
let split = GalleyCache::default().layout(&mut fonts, job.clone(), true);
|
||||||
|
|
||||||
similar_asserts::assert_eq!(split, as_whole, "Input text: '{}'", job.text);
|
dbg!(whole.rect, whole.mesh_bounds);
|
||||||
|
dbg!(split.rect, split.mesh_bounds);
|
||||||
|
|
||||||
|
for (i, row) in whole.rows.iter().enumerate() {
|
||||||
|
println!(
|
||||||
|
"Whole row {i}: section_index_at_start={}, first glyph section_index: {:?}",
|
||||||
|
row.row.section_index_at_start,
|
||||||
|
row.row.glyphs.first().map(|g| g.section_index)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
for (i, row) in split.rows.iter().enumerate() {
|
||||||
|
println!(
|
||||||
|
"Split row {i}: section_index_at_start={}, first glyph section_index: {:?}",
|
||||||
|
row.row.section_index_at_start,
|
||||||
|
row.row.glyphs.first().map(|g| g.section_index)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
similar_asserts::assert_eq!(
|
||||||
|
split,
|
||||||
|
whole,
|
||||||
|
"pixels_per_point: {pixels_per_point:.2}, input text: '{}'",
|
||||||
|
job.text
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -661,6 +661,14 @@ fn galley_from_rows(
|
|||||||
num_indices += row.visuals.mesh.indices.len();
|
num_indices += row.visuals.mesh.indices.len();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fill in correct section_index_at_start for each row:
|
||||||
|
for placed in &mut rows {
|
||||||
|
let row = Arc::make_mut(&mut placed.row);
|
||||||
|
if let Some(first_glyph) = row.glyphs.first_mut() {
|
||||||
|
row.section_index_at_start = first_glyph.section_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut rect = Rect::from_min_max(pos2(min_x, 0.0), pos2(max_x, cursor_y));
|
let mut rect = Rect::from_min_max(pos2(min_x, 0.0), pos2(max_x, cursor_y));
|
||||||
|
|
||||||
if job.round_output_to_gui {
|
if job.round_output_to_gui {
|
||||||
|
|||||||
@@ -914,6 +914,13 @@ impl Galley {
|
|||||||
merged_galley.elided |= galley.elided;
|
merged_galley.elided |= galley.elided;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for placed in &mut merged_galley.rows {
|
||||||
|
let row = Arc::make_mut(&mut placed.row);
|
||||||
|
if let Some(first_glyph) = row.glyphs.first_mut() {
|
||||||
|
row.section_index_at_start = first_glyph.section_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if merged_galley.job.round_output_to_gui {
|
if merged_galley.job.round_output_to_gui {
|
||||||
super::round_output_to_gui(&mut merged_galley.rect, &merged_galley.job);
|
super::round_output_to_gui(&mut merged_galley.rect, &merged_galley.job);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user