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

TextComponents - Position changes with length of text #401

Closed
CleanCut opened this issue Aug 31, 2020 · 7 comments
Closed

TextComponents - Position changes with length of text #401

CleanCut opened this issue Aug 31, 2020 · 7 comments
Labels
A-UI Graphical user interfaces, styles, layouts, and widgets C-Bug An unexpected or incorrect behavior

Comments

@CleanCut
Copy link
Member

On macOS, just altering this string slice causes the vertical position of the text to change!

rising-text

@CleanCut
Copy link
Member Author

The first shot is the normal "Text Example". The second alters it to be "Text Example -- notice anything?". The third is "Text Example -- notice anything? Even more text 1234567890"

@CleanCut
Copy link
Member Author

Suggested labels: bug | ui

@GabCampbell GabCampbell added C-Bug An unexpected or incorrect behavior A-UI Graphical user interfaces, styles, layouts, and widgets labels Aug 31, 2020
@GabCampbell
Copy link
Contributor

I agree with you this is definitely a bug thanks for letting us know :) If anyone is reading this can you confirm the bug repros on other platforms too 😊

@TheNeikos
Copy link
Contributor

I'm on Archlinux , here's the same texts:

"Text Example"
image

"Text Example -- notice anything?"
image

"Text Example -- notice anything? Even more text 1234567890"
image

Same issue here

@TheNeikos
Copy link
Contributor

This happens due to how the flexbox engine interacts with fixed size elements:

  • First a fixed size is computed here:
    let width = font_atlases.add_glyphs_to_atlas(
    &fonts,
    &mut texture_atlases,
    &mut textures,
    text.style.font_size,
    &text.value,
    );
    calculated_size.size = Size::new(width, text.style.font_size);
  • This size is then used during layout here:
    pub fn upsert_leaf(&mut self, entity: Entity, style: &Style, calculated_size: CalculatedSize) {
    let stretch = &mut self.stretch;
    let stretch_style = style.into();
    let measure = Box::new(move |constraints: stretch::geometry::Size<Number>| {
    let mut size = stretch::geometry::Size {
    width: calculated_size.size.width,
    height: calculated_size.size.height,
    };
    match (constraints.width, constraints.height) {
    (Number::Undefined, Number::Undefined) => {}
    (Number::Defined(width), Number::Undefined) => {
    size.height = width * size.height / size.width;
    size.width = width;
    }
    (Number::Undefined, Number::Defined(height)) => {
    size.width = height * size.width / size.height;
    size.height = height;
    }
    (Number::Defined(width), Number::Defined(height)) => {
    size.width = width;
    size.height = height;
    }
    }
    Ok(size)
    });
  • For example if we calculate a text with (w: 100px, h: 20px). The layout engine then says we only have 80px of actual width or we overflow. This is then handled in the measure closure. Right now, we simply keep the aspect ratio which then reduces the height. In this case 20 * 80/100 = 16. So, our Node now has a size of (w: 80, h: 20px). This is different to the calculated size!
  • When rendered, we simply divide the node.size by 2 to get the center and offset that with is transform. But then go on to draw with the original size:
    let position =
    Vec3::from(transform.value.w_axis().truncate()) - (node.size / 2.0).extend(0.0);
    let mut drawable_text = DrawableText {
    font: fonts.get(&text.font).unwrap(),
    font_atlas_set: font_atlas_sets
    .get(&text.font.as_handle::<FontAtlasSet>())
    .unwrap(),
    texture_atlases: &texture_atlases,
    render_resource_bindings: &mut render_resource_bindings,
    asset_render_resource_bindings: &mut asset_render_resource_bindings,
    position,
    msaa: &msaa,
    style: &text.style,
    text: &text.value,
    container_size: node.size,
    };
    drawable_text.draw(&mut draw, &mut draw_context).unwrap();

This then results in the behavior we see now: A smaller height divided by two makes for an 'upwards' growing text, when in actuality it should be shrinking to fit the available width.

I am not sure what the ideal solution is here. Either the text overflows, or it gets smaller and smaller. Another option is to have it break into a new line (if there is space?)

@CleanCut
Copy link
Member Author

CleanCut commented Sep 1, 2020

In my use-case I would like to wrap. From my naive standpoint of never having had to implement a text layout system, it seems like wrap vs. shrink vs. overflow should all be supported via some configurable option. I don't know how hard that is to do.

@mockersf
Copy link
Member

I have this issue, my "fix" to have the expected placement is to set the Style component of the TextComponents, with the height equal to the font size:

TextComponents {
    style: Style {
        size: Size {
            height: Val::Px(40.),
            ..Default::default()
        },
        ..Default::default()
    },
    text: Text {
        value: "Text example",
        font,
        style: TextStyle {
            color: Color::WHITE,
            font_size: 40.,
        },
    },
    ..Default::default()
}

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

No branches or pull requests

4 participants