Fix text wrapping when a child of a v_stack() (#3362)

Previously text that was rendered in a flex-column would reserve the
correct
amount of space during layout, and then paint itself incorrectly.

Release Notes:

- N/A
This commit is contained in:
Conrad Irwin
2023-11-19 11:37:31 -07:00
committed by GitHub
6 changed files with 129 additions and 41 deletions
+25 -5
View File
@@ -64,19 +64,34 @@ impl<V: 'static> Element<V> for Text {
let layout_id = cx.request_measured_layout(Default::default(), rem_size, {
let element_state = element_state.clone();
move |known_dimensions, _| {
move |known_dimensions, available_space| {
let wrap_width = known_dimensions.width.or(match available_space.width {
crate::AvailableSpace::Definite(x) => Some(x),
_ => None,
});
if let Some(text_state) = element_state.0.lock().as_ref() {
if text_state.size.is_some()
&& (wrap_width.is_none() || wrap_width == text_state.wrap_width)
{
return text_state.size.unwrap();
}
}
let Some(lines) = text_system
.shape_text(
&text,
font_size,
&runs[..],
known_dimensions.width, // Wrap if we know the width.
wrap_width, // Wrap if we know the width.
)
.log_err()
else {
element_state.lock().replace(TextStateInner {
lines: Default::default(),
line_height,
wrap_width,
size: Some(Size::default()),
});
return Size::default();
};
@@ -88,9 +103,12 @@ impl<V: 'static> Element<V> for Text {
size.width = size.width.max(line_size.width);
}
element_state
.lock()
.replace(TextStateInner { lines, line_height });
element_state.lock().replace(TextStateInner {
lines,
line_height,
wrap_width,
size: Some(size),
});
size
}
@@ -133,6 +151,8 @@ impl TextState {
struct TextStateInner {
lines: SmallVec<[WrappedLine; 1]>,
line_height: Pixels,
wrap_width: Option<Pixels>,
size: Option<Size<Pixels>>,
}
struct InteractiveText {