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

Center Text #54

Open
DasLixou opened this issue Oct 4, 2023 · 18 comments
Open

Center Text #54

DasLixou opened this issue Oct 4, 2023 · 18 comments
Labels
question Further information is requested

Comments

@DasLixou
Copy link
Contributor

DasLixou commented Oct 4, 2023

How would I center the text in for example the middle of my window?

I currently do

let x = self.size.width / 2;
        let y = self.size.height / 2;

        self.text_renderer
            .prepare(
                &self.device,
                &self.queue,
                &mut self.font_system,
                &mut self.atlas,
                Resolution {
                    width: self.size.width,
                    height: self.size.height,
                },
                [TextArea {
                    buffer: &self.buffer,
                    left: x as f32,
                    top: y as f32,
                    scale: 1.0,
                    bounds: TextBounds {
                        left: x as i32,
                        top: y as i32,
                        right: self.size.width as i32,
                        bottom: self.size.height as i32,
                    },
                    default_color: glyphon::Color::rgb(0, 0, 0),
                }],
                &mut self.cache,
            )
            .unwrap();

But that does it with a offset. Now i would need something like the worlds famous translate(-50%) css trick...
But I can't seem to find any API to get the size of the text. Also the TextBounds API is kinda weird because provides extra left and top values which are absolute so I need to pass the left and top in there as well...

@grovesNL
Copy link
Owner

grovesNL commented Oct 4, 2023

The plan was to let cosmic-text handle all alignment, e.g., through https://docs.rs/cosmic-text/latest/cosmic_text/struct.BufferLine.html#method.set_align or any other APIs they add upstream. So the idea is that you could let the buffer be sized to the full width of the window and center it horizontally that way.

The extra left/top are useful if you want to render a region of the text area, so in those cases the left/top might not be the same (area left/top are about shifting, while bounds left/top are about clipping/culling). We might be able to make this a little easier though.

@grovesNL grovesNL added the question Further information is requested label Oct 4, 2023
@DasLixou
Copy link
Contributor Author

DasLixou commented Oct 4, 2023

@grovesNL yeah from my perspective a more intuitive API would be to handle the left and top completely from the "align" sector and let the bounds be relative to the text and also provide a const Bounds::FULL

@DasLixou
Copy link
Contributor Author

DasLixou commented Oct 4, 2023

@grovesNL Is there already a way to use the alignment or is it like from a PR?

@DasLixou
Copy link
Contributor Author

DasLixou commented Oct 4, 2023

Do I see this correctly? https://docs.rs/cosmic-text/latest/cosmic_text/struct.BufferLine.html#method.set_align only provides basic left, middle, right alignment? No top, middle, down and no translating?

@grovesNL
Copy link
Owner

grovesNL commented Oct 4, 2023

Is there already a way to use the alignment or is it like from a PR?

I think you should already be able to call this function on your Buffers.

only provides basic left, middle, right alignment? No top, middle, down and no translating?

Vertical alignment was requested in pop-os/cosmic-text#79 but hasn't been implemented yet as far as I know. I guess you can handle middle by approximating it if you have a maximum number of lines/can approximate the line heights. Translating is handled by the left/top in the text area.

@DasLixou
Copy link
Contributor Author

DasLixou commented Oct 4, 2023

But then I would at least need an api to get the used size of the buffer
And that shouldn't be that easy because it gets processed in the prepare function (because of wrapping etc.)
So I would need to get a result of prepare in prepare

@grovesNL
Copy link
Owner

grovesNL commented Oct 4, 2023

Yeah it's not very convenient right now, you could do something as described in pop-os/cosmic-text#70 to get the visible lines

@DasLixou
Copy link
Contributor Author

DasLixou commented Oct 5, 2023

So in my dreams 💅 a more intuitive API would look like this:

self.text_renderer
    .prepare(
        &self.device,
        &self.queue,
        &mut self.font_system,
        &mut self.atlas,
        Resolution {
            width: self.size.width,
            height: self.size.height,
        },
        // note that this is now a slice, which enables us to store the info in a vec and just give a slice to it
        &[BufferAttachment {
            buffer: &self.buffer,
            horizontal_offset: x as f32,
            horizontal_alignment: Alignment::Center,
            horizontal_bounds: Bounds::Unbound, // replaces TextBounds
            vertical_offset: y as f32,
            vertical_alignment: Alignment::Center,
            vertical_bounds: Bounds::Unbound, // replaces TextBounds
            base_color: glyphon::Color::rgb(0, 0, 0), // base_color sounds better than default_color i think
            ..Default::default() // hide scale, or scissor & rotation when they're added
        }],
        &mut self.cache,
    )
    .unwrap();

The associated enums would look like this:

enum Alignment {
    Start,
    Center,
    End,
}
enum Bounds {
    Fixed(/* wait what type?..*/),
    /// The Text will go on without any limit
    Unbound,
    // maybe we can also have an option to automatically stop at resolution end?
}

Thoughts?

@grovesNL
Copy link
Owner

grovesNL commented Oct 6, 2023

  • I think buffer attachment sounds a bit too vague
  • horizontal_alignment and vertical_alignment would be set on buffer itself, so we don't control that in glyphon and it can't be specified at this level
  • I don't think I'd recommend using something like Bounds::Unbound because you almost always want to clip to some region (at least the window border) to avoid sending extra text to the GPU
  • base_color sounds like we're using it to mix colors but it's more like a default vs. custom color for part of the text

@DasLixou
Copy link
Contributor Author

DasLixou commented Oct 6, 2023

  • I think buffer attachment sounds a bit too vague

    • horizontal_alignment and vertical_alignment would be set on buffer itself, so we don't control that in glyphon and it can't be specified at this level

    • I don't think I'd recommend using something like Bounds::Unbound because you almost always want to clip to some region (at least the window border) to avoid sending extra text to the GPU

    • base_color sounds like we're using it to mix colors but it's more like a default vs. custom color for part of the text

  • I just was confused with all the Text... things so I named it that way, but when you think TextArea is more suitable, it's fine.
  • So that would be something that happens at cosmic_text?
  • Wait did I understand TextBounds wrong? I thought its at which point it does a linebreak, like a box in which the text is laid out. Bounds::Unbound should say: 'I never need a linebreak, just ignore when you are outside of the window'
  • Oh yeah, base_color really is a bad choice with this in mind 😅

@grovesNL
Copy link
Owner

So that would be something that happens at cosmic_text?

Exactly, most text styling, alignment, etc. all happen in cosmic-text itself instead of glyphon

Wait did I understand TextBounds wrong? I thought its at which point it does a linebreak, like a box in which the text is laid out.

Text bounds is about clipping/culling to a visible area, the size of the buffer (the one you give to cosmic-text when you create a buffer) controls where line breaks happen

@DasLixou
Copy link
Contributor Author

Wait... so when that's cosmic_texts stuff.. can we then not have the sizes of the text on render and use that to center it?

@grovesNL
Copy link
Owner

At least for vertically centering you'd have to query the height based on the visible lines which is pop-os/cosmic-text#70

@DasLixou
Copy link
Contributor Author

Why is this closed?

@grovesNL
Copy link
Owner

Sorry we can reopen it if there's anything remaining - I thought there wasn't anything else required from glyphon's side to center text. Is there anything missing?

@grovesNL grovesNL reopened this Jan 15, 2024
@DasLixou
Copy link
Contributor Author

Well it's nothing on glyphons side but still it's not possible yet... so i think as a sort of tracking issue this will do it

@madmaxio
Copy link

Has someone tried implement cursor functionality with on top of cosmic-text/glyphon? Any recommendations what approach to use (cosmic-text alignment probably)?

@BillyDM
Copy link

BillyDM commented May 28, 2024

Has someone tried implement cursor functionality with on top of cosmic-text/glyphon? Any recommendations what approach to use (cosmic-text alignment probably)?

In the GUI lib I'm creating, I'm using the align inside of the text properties for horizontal alignment, and my own custom method for vertical alignment:

pub fn layout_text_bounds(
    bounds_size: Size,
    unclipped_text_size: Size,
    padding: Padding,
    min_clipped_size: Size,
    vertical_align: Align,
    font_size: f32,
) -> Rect {
    if unclipped_text_size.is_empty() {
        return Rect::default();
    }

    let content_rect = crate::layout::layout_inner_rect_with_min_size(
        padding,
        Rect::from_size(bounds_size),
        min_clipped_size,
    );

    // We need to vertically align the text ourselves as rootvg/glyphon does not do this.
    let text_bounds_y = match vertical_align {
        Align::Start => content_rect.min_y(),
        Align::Center => content_rect.min_y() + ((content_rect.height() - font_size) / 2.0) + 1.0,
        Align::End => content_rect.max_y() - unclipped_text_size.height,
    };

    Rect::new(
        Point::new(content_rect.min_x(), text_bounds_y),
        Size::new(content_rect.width(), unclipped_text_size.height),
    )
}

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

No branches or pull requests

4 participants