mirror of
https://github.com/bevyengine/bevy
synced 2024-11-21 20:23:28 +00:00
Avoid reallocating spans buffer in TextPipeline (#15012)
# Objective - Don't reallocate the spans vector every time TextPipeline updates a buffer. ## Solution - Cache the spans buffer in `TextPipeline`. This is possible through some [rust magic](https://users.rust-lang.org/t/how-to-cache-a-vectors-capacity/94478/10).
This commit is contained in:
parent
3227c3de36
commit
49a06e9c76
1 changed files with 34 additions and 17 deletions
|
@ -51,6 +51,10 @@ pub struct TextPipeline {
|
|||
///
|
||||
/// See [`cosmic_text::SwashCache`] for more information.
|
||||
swash_cache: SwashCache,
|
||||
/// Buffered vec for collecting spans.
|
||||
///
|
||||
/// See [this dark magic](https://users.rust-lang.org/t/how-to-cache-a-vectors-capacity/94478/10).
|
||||
spans_buffer: Vec<(&'static str, Attrs<'static>)>,
|
||||
}
|
||||
|
||||
impl TextPipeline {
|
||||
|
@ -95,23 +99,29 @@ impl TextPipeline {
|
|||
// The section index is stored in the metadata of the spans, and could be used
|
||||
// to look up the section the span came from and is not used internally
|
||||
// in cosmic-text.
|
||||
let spans: Vec<(&str, Attrs)> = sections
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(_section_index, section)| section.style.font_size > 0.0)
|
||||
.map(|(section_index, section)| {
|
||||
(
|
||||
§ion.value[..],
|
||||
get_attrs(
|
||||
section,
|
||||
section_index,
|
||||
font_system,
|
||||
&self.map_handle_to_font_id,
|
||||
scale_factor,
|
||||
),
|
||||
)
|
||||
})
|
||||
let mut spans: Vec<(&str, Attrs)> = std::mem::take(&mut self.spans_buffer)
|
||||
.into_iter()
|
||||
.map(|_| -> (&str, Attrs) { unreachable!() })
|
||||
.collect();
|
||||
spans.extend(
|
||||
sections
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(_section_index, section)| section.style.font_size > 0.0)
|
||||
.map(|(section_index, section)| {
|
||||
(
|
||||
§ion.value[..],
|
||||
get_attrs(
|
||||
section,
|
||||
section_index,
|
||||
font_system,
|
||||
&self.map_handle_to_font_id,
|
||||
scale_factor,
|
||||
),
|
||||
)
|
||||
}),
|
||||
);
|
||||
let spans_iter = spans.iter().copied();
|
||||
|
||||
buffer.set_metrics(font_system, metrics);
|
||||
buffer.set_size(font_system, bounds.width, bounds.height);
|
||||
|
@ -126,7 +136,7 @@ impl TextPipeline {
|
|||
},
|
||||
);
|
||||
|
||||
buffer.set_rich_text(font_system, spans, Attrs::new(), Shaping::Advanced);
|
||||
buffer.set_rich_text(font_system, spans_iter, Attrs::new(), Shaping::Advanced);
|
||||
|
||||
// PERF: https://github.com/pop-os/cosmic-text/issues/166:
|
||||
// Setting alignment afterwards appears to invalidate some layouting performed by `set_text` which is presumably not free?
|
||||
|
@ -135,6 +145,13 @@ impl TextPipeline {
|
|||
}
|
||||
buffer.shape_until_scroll(font_system, false);
|
||||
|
||||
// Recover the spans buffer.
|
||||
spans.clear();
|
||||
self.spans_buffer = spans
|
||||
.into_iter()
|
||||
.map(|_| -> (&'static str, Attrs<'static>) { unreachable!() })
|
||||
.collect();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue