Fix text measurement algorithm (#8425)

# Objective

Followup to #7779 which tweaks the actual text measurement algorithm to
be more robust.

Before:

<img width="822" alt="Screenshot 2023-04-17 at 18 12 05"
src="https://user-images.githubusercontent.com/1007307/232566858-3d3f0fd5-f3d4-400a-8371-3c2a3f541e56.png">

After:

<img width="810" alt="Screenshot 2023-04-17 at 18 41 40"
src="https://user-images.githubusercontent.com/1007307/232566919-4254cbfa-1cc3-4ea7-91ed-8ca1b759bacf.png">

(note extra space taken up in header in before example)

## Solution

- Text layout of horizontal text (currently the only kind of text we
support) is now based solely on the layout constraints in the horizontal
axis. It ignores constraints in the vertical axis and computes vertical
size based on wrapping subject to the horizontal axis constraints.
- I've also added a paragraph to the `grid` example for testing / demo
purposes.
This commit is contained in:
Nico Burns 2023-04-17 20:59:42 +01:00 committed by GitHub
parent 7604464438
commit 919919c998
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 14 deletions

View file

@ -30,7 +30,7 @@ impl Measure for TextMeasure {
width: Option<f32>,
height: Option<f32>,
available_width: AvailableSpace,
available_height: AvailableSpace,
_available_height: AvailableSpace,
) -> Vec2 {
let x = width.unwrap_or_else(|| match available_width {
AvailableSpace::Definite(x) => x.clamp(
@ -43,16 +43,10 @@ impl Measure for TextMeasure {
height
.map_or_else(
|| match available_height {
AvailableSpace::Definite(y) => {
let y = y.clamp(
self.info.max_width_content_size.y,
self.info.min_width_content_size.y,
);
self.info.compute_size(Vec2::new(x, y))
}
AvailableSpace::MinContent => Vec2::new(x, self.info.max_width_content_size.y),
AvailableSpace::MaxContent => Vec2::new(x, self.info.min_width_content_size.y),
|| match available_width {
AvailableSpace::Definite(_) => self.info.compute_size(Vec2::new(x, f32::MAX)),
AvailableSpace::MinContent => Vec2::new(x, self.info.min_width_content_size.y),
AvailableSpace::MaxContent => Vec2::new(x, self.info.max_width_content_size.y),
},
|y| Vec2::new(x, y),
)

View file

@ -124,8 +124,13 @@ fn spawn_layout(mut commands: Commands, asset_server: Res<AssetServer>) {
align_items: AlignItems::Start,
// Align content towards the center in the horizontal axis
justify_items: JustifyItems::Center,
// Add 20px padding to the top
padding: UiRect::top(Val::Px(20.)),
// Add 10px padding
padding: UiRect::all(Val::Px(10.)),
// Add an fr track to take up all the available space at the bottom of the column so that the text nodes
// can be top-aligned. Normally you'd use flexbox for this, but this is the CSS Grid example so we're using grid.
grid_template_rows: vec![GridTrack::auto(), GridTrack::auto(), GridTrack::fr(1.0)],
// Add a 10px gap between rows
gap: Size::height(Val::Px(10.)),
..default()
},
background_color: BackgroundColor(Color::BLACK),
@ -135,11 +140,20 @@ fn spawn_layout(mut commands: Commands, asset_server: Res<AssetServer>) {
builder.spawn(TextBundle::from_section(
"Sidebar",
TextStyle {
font,
font: font.clone(),
font_size: 24.0,
color: Color::WHITE,
},
));
builder.spawn(TextBundle::from_section(
"A paragraph of text which ought to wrap nicely. A paragraph of text which ought to wrap nicely. A paragraph of text which ought to wrap nicely. A paragraph of text which ought to wrap nicely. A paragraph of text which ought to wrap nicely. A paragraph of text which ought to wrap nicely. A paragraph of text which ought to wrap nicely.",
TextStyle {
font: font.clone(),
font_size: 16.0,
color: Color::WHITE,
},
));
builder.spawn(NodeBundle::default());
});
// Footer / status bar