fix non-exact text h-alignment (#13846)

# Objective

when a parent container is auto-sized, text alignments `Center` and
`Right` don't align to the center and right properly. fix it

## Solution

ab_glyph positions return +/- values from an anchor point. we currently
transform them to positive values from the min-x of the glyphs, and then
offset from the left of the bounds. instead, we can keep the negative
values as ab_glyph intended and offset from the left/middle/right of the
bounds as appropriate.

## Testing

texts with align left, center, right, all contained in the purple boxes:
before (0.14.0-rc.2):
![Screenshot 2024-06-14
165456](https://github.com/bevyengine/bevy/assets/50659922/90fb73b0-d8bd-4ae8-abf3-7106eafc93ba)

after:

![Screenshot 2024-06-14
164449](https://github.com/bevyengine/bevy/assets/50659922/0a75ff09-b51d-4fbe-a491-b655a145c08b)

code:
```rs
use bevy::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .run();
}

fn setup(mut commands: Commands) {
    commands.spawn(Camera2dBundle::default());

    for (left, justify) in [
        (100.0, JustifyText::Left),
        (500.0, JustifyText::Center),
        (900.0, JustifyText::Right),
    ] {
        commands
        // container
        .spawn(NodeBundle {
            style: Style {
                flex_direction: FlexDirection::Column,
                position_type: PositionType::Absolute,
                left: Val::Px(left),
                top: Val::Px(100.0),
                width: Val::Px(300.0),
                ..Default::default()
            },
            ..Default::default()
        })
        .with_children(|commands| {
            commands.spawn(NodeBundle{
                style: Style {
                    flex_direction: FlexDirection::Row,
                    height: Val::Px(75.0),
                    ..Default::default()
                },
                background_color: Color::srgb(1.0, 0.0, 1.0).into(),
                ..Default::default()
            }).with_children(|commands| {
                // a div that reduces the available size
                commands.spawn(NodeBundle {
                    style: Style {
                        width: Val::Px(75.0),
                        ..Default::default()
                    },
                    background_color: Color::srgb(0.0, 1.0, 0.0).into(),
                    ..Default::default()
                });

                // text with width=auto, but actual size will not be what it expcets due to the sibling div above
                commands.spawn(TextBundle {
                    text: Text::from_section("Some text that wraps onto a second line", Default::default()).with_justify(justify),
                    style: Style {
                        align_self: AlignSelf::Center,
                        ..Default::default()
                    },
                    ..Default::default()
                });
            });
        });
    }
}
```
This commit is contained in:
robtfm 2024-06-14 20:14:42 +01:00 committed by GitHub
parent 117346d8b7
commit 01971f210e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 10 additions and 1 deletions

View file

@ -64,6 +64,7 @@ impl GlyphBrush {
textures: &mut Assets<Image>,
text_settings: &TextSettings,
y_axis_orientation: YAxisOrientation,
h_anchor: f32,
) -> Result<Vec<PositionedGlyph>, TextError> {
if glyphs.is_empty() {
return Ok(Vec::new());
@ -126,7 +127,7 @@ impl GlyphBrush {
let glyph_rect = texture_atlas.textures[atlas_info.glyph_index];
let size = glyph_rect.size().as_vec2();
let x = bounds.min.x + size.x / 2.0 - text_bounds.min.x;
let x = bounds.min.x + size.x / 2.0 + h_anchor;
let y = match y_axis_orientation {
YAxisOrientation::BottomToTop => {

View file

@ -87,6 +87,13 @@ impl TextPipeline {
let size = compute_text_bounds(&section_glyphs, |index| scaled_fonts[index]).size();
let h_anchor = match text_alignment {
JustifyText::Left => 0.0,
JustifyText::Center => bounds.x * 0.5,
JustifyText::Right => bounds.x * 1.0,
}
.floor();
let glyphs = self.brush.process_glyphs(
section_glyphs,
&sections,
@ -96,6 +103,7 @@ impl TextPipeline {
textures,
text_settings,
y_axis_orientation,
h_anchor,
)?;
Ok(TextLayoutInfo {