Fix text alignment for unbounded text (#17270)

# Objective

Fixes #16783

## Solution

Works around a `cosmic-text` bug or limitation by triggering a re-layout
with the calculated width from the first layout run. See linked issue.

Credit to @ickshonpe for the clever solution.

## Performance

This has a significant performance impact only on unbounded text that
are not `JustifyText::Left`, which is still a bit of a bummer because
text2d performance in 0.15.1 is already not great. But this seems better
than alignment not working.

||many_text2d nfc re|many_text2d nfc re center|
|-|-|-|
|unbounded-layout-no-fix|3.06|3.10|
|unbounded-layout-fix|3.05  -0.2%|2.71 🟥 -12.5%|

## Testing

I added a centered text to the `text2d` example.

`cargo run --example text2d`

We should look at other text examples and stress tests. I haven't tested
as thoroughly as I would like, so help testing that this doesn't break
something in UI would be appreciated.
This commit is contained in:
Rob Parrett 2025-01-10 21:45:32 -08:00 committed by GitHub
parent 51c3bf24b7
commit 5c0e13f29b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 19 additions and 1 deletions

View File

@ -191,6 +191,14 @@ impl TextPipeline {
}
buffer.shape_until_scroll(font_system, false);
// Workaround for alignment not working for unbounded text.
// See https://github.com/pop-os/cosmic-text/issues/343
if bounds.width.is_none() && justify != JustifyText::Left {
let dimensions = buffer_dimensions(buffer);
// `set_size` causes a re-layout to occur.
buffer.set_size(font_system, Some(dimensions.x), bounds.height);
}
// Recover the spans buffer.
spans.clear();
self.spans_buffer = spans

View File

@ -111,10 +111,11 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
// Demonstrate font smoothing off
commands.spawn((
Text2d::new("FontSmoothing::None"),
Text2d::new("This text has\nFontSmoothing::None\nAnd JustifyText::Center"),
slightly_smaller_text_font
.clone()
.with_font_smoothing(FontSmoothing::None),
TextLayout::new_with_justify(JustifyText::Center),
Transform::from_translation(Vec3::new(-400.0, -250.0, 0.0)),
));

View File

@ -42,6 +42,10 @@ struct Args {
/// whether to disable all frustum culling.
#[argh(switch)]
no_frustum_culling: bool,
/// whether the text should use `JustifyText::Center`.
#[argh(switch)]
center: bool,
}
#[derive(Resource)]
@ -123,6 +127,11 @@ fn setup(mut commands: Commands, font: Res<FontHandle>, args: Res<Args>) {
Text2d(random_text(&mut rng, &args)),
random_text_font(&mut rng, &args, font.0.clone()),
TextColor(color.into()),
TextLayout::new_with_justify(if args.center {
JustifyText::Center
} else {
JustifyText::Left
}),
Transform {
translation,
rotation,