Zero fontsize panic workaround (#15371)

# Objective

- Fix https://github.com/bevyengine/bevy/issues/15366. `cosmic-text`
buffers refuse to function if the `Metrics` font size is zero.

## Solution

- Trick `cosmic-text` into clearing its internal buffer when the largest
font size of segments is zero by sending it no spans and a tiny
`Metrics::font_size` and `Metrics::line_height`.

## Testing

- [x] Fixes @brandon-reinhart 's bug.
This commit is contained in:
UkoeHB 2024-09-23 12:31:50 -05:00 committed by GitHub
parent 8e3db957c5
commit 21da0b72ae
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -90,7 +90,12 @@ impl TextPipeline {
.ok_or(TextError::NoSuchFont)?; .ok_or(TextError::NoSuchFont)?;
} }
let line_height = font_size * 1.2; let line_height = font_size * 1.2;
let metrics = Metrics::new(font_size, line_height).scale(scale_factor as f32); let mut metrics = Metrics::new(font_size, line_height).scale(scale_factor as f32);
// Metrics of 0.0 cause `Buffer::set_metrics` to panic. We hack around this by 'falling
// through' to call `Buffer::set_rich_text` with zero spans so any cached text will be cleared without
// deallocating the buffer.
metrics.font_size = metrics.font_size.max(0.000001);
metrics.line_height = metrics.line_height.max(0.000001);
// Load Bevy fonts into cosmic-text's font system. // Load Bevy fonts into cosmic-text's font system.
// This is done as as separate pre-pass to avoid borrow checker issues // This is done as as separate pre-pass to avoid borrow checker issues
@ -108,24 +113,27 @@ impl TextPipeline {
.into_iter() .into_iter()
.map(|_| -> (&str, Attrs) { unreachable!() }) .map(|_| -> (&str, Attrs) { unreachable!() })
.collect(); .collect();
spans.extend( // `metrics.font_size` hack continued: ignore all spans when scale_factor is zero.
sections if scale_factor > 0.0 {
.iter() spans.extend(
.enumerate() sections
.filter(|(_section_index, section)| section.style.font_size > 0.0) .iter()
.map(|(section_index, section)| { .enumerate()
( .filter(|(_section_index, section)| section.style.font_size > 0.0)
&section.value[..], .map(|(section_index, section)| {
get_attrs( (
section, &section.value[..],
section_index, get_attrs(
font_system, section,
&self.map_handle_to_font_id, section_index,
scale_factor, font_system,
), &self.map_handle_to_font_id,
) scale_factor,
}), ),
); )
}),
);
}
let spans_iter = spans.iter().copied(); let spans_iter = spans.iter().copied();
buffer.set_metrics(font_system, metrics); buffer.set_metrics(font_system, metrics);