Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Text wraps incorrectly for a frame after a change to its font size #9874

Closed
ickshonpe opened this issue Sep 20, 2023 · 4 comments · Fixed by #9923
Closed

Text wraps incorrectly for a frame after a change to its font size #9874

ickshonpe opened this issue Sep 20, 2023 · 4 comments · Fixed by #9923
Labels
A-UI Graphical user interfaces, styles, layouts, and widgets C-Bug An unexpected or incorrect behavior

Comments

@ickshonpe
Copy link
Contributor

ickshonpe commented Sep 20, 2023

Bevy version

main 038d113

What you did

use bevy::prelude::*;

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

fn setup(
    mut commands: Commands,
) {
    commands.spawn(Camera2dBundle::default());
    commands.spawn(TextBundle::from("Hello, world!"));
}

fn update(
    mut text_query: Query<&mut Text>,
) {
    for mut text in text_query.iter_mut() {
        text.sections[0].style.font_size *= 1.001;
    }
}

What went wrong

As the text increases in size it flickers between being displayed on one line and wrapped across two lines
It should always be on one line.

Additional Information

Could just be a system ordering issue

@ickshonpe ickshonpe added C-Bug An unexpected or incorrect behavior S-Needs-Triage This issue needs to be labelled labels Sep 20, 2023
@alice-i-cecile alice-i-cecile added A-UI Graphical user interfaces, styles, layouts, and widgets and removed S-Needs-Triage This issue needs to be labelled labels Sep 20, 2023
@rparrett
Copy link
Contributor

rparrett commented Sep 21, 2023

I think that this is scale-factor dependent. I am able reproduce on every run with e.g.

app.add_plugins(DefaultPlugins.set(WindowPlugin {
    primary_window: Some(Window {
        resolution: WindowResolution::default().with_scale_factor_override(7. / 3.),
        ..default()
    }),
    ..default()
}))

But not 2.0 or 1.0.

@ickshonpe
Copy link
Contributor Author

ickshonpe commented Sep 22, 2023

I think that this is scale-factor dependent. I am able reproduce on every run with e.g.

app.add_plugins(DefaultPlugins.set(WindowPlugin {
    primary_window: Some(Window {
        resolution: WindowResolution::default().with_scale_factor_override(7. / 3.),
        ..default()
    }),
    ..default()
}))

But not 2.0 or 1.0.

Probably not a system ordering issue then, most likely the bounds calculated by the measure func and the text system are different at certain scale factors. The text systems badly need more tests I think.

@rparrett
Copy link
Contributor

Simplified the repro slightly, although maybe there's more going on than just this.

use bevy::{prelude::*, window::WindowResolution};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins.set(WindowPlugin {
            primary_window: Some(Window {
                resolution: WindowResolution::default().with_scale_factor_override(7. / 3.),
                ..default()
            }),
            ..default()
        }))
        .add_systems(Startup, setup)
        .run();
}

fn setup(mut commands: Commands) {
    commands.spawn(Camera2dBundle::default());
    commands.spawn(TextBundle::from_section(
        "Hello, world!",
        TextStyle {
            font_size: 12.02,
            ..default()
        },
    ));
}
Screenshot 2023-09-22 at 11 19 37 AM

@rparrett
Copy link
Contributor

rparrett commented Sep 25, 2023

Bisected the modified repro just above:

After #9784, text appears on two lines instead of one, but both lines are rendered.
After #9637, second line disappears

github-merge-queue bot pushed a commit that referenced this issue Sep 28, 2023
# Objective

Text bounds are computed by the layout algorithm using the text's
measurefunc so that text will only wrap after it's used the maximum
amount of available horizontal space.

When the layout size is returned the layout coordinates are rounded and
this sometimes results in the final size of the Node not matching the
size computed with the measurefunc. This means that the text may no
longer fit the horizontal available space and instead wrap onto a new
line. However, no glyphs will be generated for this new line because no
vertical space for the extra line was allocated.

fixes #9874

## Solution

Store both the rounded and unrounded node sizes in `Node`.

Rounding is used to eliminate pixel-wide gaps between nodes that should
be touching edge to edge, but this isn't necessary for text nodes as
they don't have solid edges.

## Changelog

* Added the `rounded_size: Vec2` field to `Node`.
* `text_system` uses the unrounded node size when computing a text
layout.

---------

Co-authored-by: Rob Parrett <robparrett@gmail.com>
rdrpenguin04 pushed a commit to rdrpenguin04/bevy that referenced this issue Jan 9, 2024
# Objective

Text bounds are computed by the layout algorithm using the text's
measurefunc so that text will only wrap after it's used the maximum
amount of available horizontal space.

When the layout size is returned the layout coordinates are rounded and
this sometimes results in the final size of the Node not matching the
size computed with the measurefunc. This means that the text may no
longer fit the horizontal available space and instead wrap onto a new
line. However, no glyphs will be generated for this new line because no
vertical space for the extra line was allocated.

fixes bevyengine#9874

## Solution

Store both the rounded and unrounded node sizes in `Node`.

Rounding is used to eliminate pixel-wide gaps between nodes that should
be touching edge to edge, but this isn't necessary for text nodes as
they don't have solid edges.

## Changelog

* Added the `rounded_size: Vec2` field to `Node`.
* `text_system` uses the unrounded node size when computing a text
layout.

---------

Co-authored-by: Rob Parrett <robparrett@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-UI Graphical user interfaces, styles, layouts, and widgets C-Bug An unexpected or incorrect behavior
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants