Skip to content

Alignment doesn't work when the buffer is unbounded #343

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

Open
rparrett opened this issue Jan 6, 2025 · 1 comment
Open

Alignment doesn't work when the buffer is unbounded #343

rparrett opened this issue Jan 6, 2025 · 1 comment

Comments

@rparrett
Copy link
Contributor

rparrett commented Jan 6, 2025

I'm debugging bevyengine/bevy#16783 and it seems like it might be an issue here with cosmic-text.

We've worked around this on our end by doing a re-layout with bounds determined from the first pass, but it's not ideal performance-wise.

Testing against 1ab7fc2, but Bevy is using cosmic-text 0.12.

Expand Code
use cosmic_text::{Align, Attrs, Buffer, FontSystem, Metrics, Shaping};

fn main() {
    let metrics = Metrics::relative(20.0, 1.5);
    let mut buffer = Buffer::new_empty(metrics);
    let mut font_system = FontSystem::new();

    let attrs = Attrs::new();
    let spans: [(&str, Attrs); 3] = [("x\n", attrs), ("yyy\n", attrs), ("z", attrs)];

    let align = Some(Align::Center);

    buffer.set_rich_text(&mut font_system, spans, attrs, Shaping::Advanced, align);

    for buffer_line in buffer.lines.iter_mut() {
        buffer_line.set_align(align);
    }

    buffer.shape_until_scroll(&mut font_system, false);

    println!("unbounded");
    print_glyphs(&buffer);

    println!("\nbounded");
    buffer.set_size(&mut font_system, Some(100.0), None);
    buffer.shape_until_scroll(&mut font_system, false);

    print_glyphs(&buffer);
}

fn print_glyphs(buffer: &Buffer) {
    println!("{:^3}{:^10}{:^10}", "id", "x", "y");

    for (glyph, line_y) in buffer.layout_runs().flat_map(|run| {
        run.glyphs
            .iter()
            .map(move |layout_glyph| (layout_glyph, run.line_y))
    }) {
        println!("{:3}{:10}{:10}", glyph.glyph_id, glyph.x, glyph.y + line_y);
    }
}

What went wrong

When the buffer is unbounded, text is always left aligned.

The code above lays out the following text:

x
yyy
z

With Align::Center set with either set_rich_text or on each line with set_align.

Things seem to work as expected when there are bounds.

bounded
id     x         y     
713     45.15      21.7
714 35.239998      51.7
714 45.079998      51.7
714     54.92      51.7
726     45.63      81.7

But when the buffer is unbounded, the text is left-aligned.

unbounded
id     x         y     
713         0      21.7
714         0      51.7
714      9.84      51.7
714     19.68      51.7
726         0      81.7
@tigregalis
Copy link
Contributor

tigregalis commented Jan 9, 2025

Is this the intended behaviour @jackpot51 ?

Each BufferLine/ShapeLine determines its own width, then it is "centred" within its own line.

But when it's unbounded, the text's width is of course the line's width (there is no line breaking), so there's no alignment correction at all.

The intention is a little unclear. When you first set up the Buffer, it requires providing an alignment (Buffer-level alignment), but currently, cosmic-text supports mixed alignment within one Buffer, since each BufferLine has a set_align method.

That is, currently cosmic-text supports this display in a single Buffer:

left align                |
               right align|
      center align        |

Ideally the alignment would be Buffer-level, and apply after the shaping (after you know the width of the whole buffer) but that wouldn't support mixed alignment.

But an application could instead support mixed alignment through stacking multiple Buffers:

left align                |
               right align|
      center align        |

I'm not sure how well the post-shaping alignment works with the incremental approach.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants