slint-ui / slint

Slint is a declarative GUI toolkit to build native user interfaces for Rust, C++, or JavaScript apps.
https://slint.dev
Other
16.85k stars 556 forks source link

FemtoVG renderer: Text disappears if its font-size is too large compared to the height of its parent #2029

Open jturcotte opened 1 year ago

jturcotte commented 1 year ago

What I'm trying to do is to have text take the full height of its parent.

Demo := Window {
    width: 600px;
    height: 200px;
    Rectangle {
        background: blue;
        Rectangle {
            height: 50%;
            y: parent.height / 2 - height / 2;
            background: yellow;
            Text {
                text: "Hello World!";
                height: 100%;

                // This works
                // font-size: 86px;

                // This doesn't work (but it does if you increase height: 50% of the parent Rectangle)
                // font-size: 87px;

                // This also doesn't work with the winit-femtovg nor winit-software backends,
                // but it does work with the Qt backend
                // (at least in the code I had with slint-lsp before I tried to reproduce it here).
                font-size: height;
            }
        }
    }
}

Online editor

tronical commented 1 year ago

I see two issues here:

  1. The old question what the text element should do if the glyphs don't fit. Right now it skips the glyphs entirely, but it could also clip, or just draw out of the bounds. I recall discussing this with Olivier before and I think we concluded that clipping was "best", but I'm growing uncertain of it. As this issue shows, sometimes it's necessary to work around font sizes and then the disappearing behavior is hard to use.

  2. The font-size property really just describes how to scale the metrics the font provides to the screen. The font remains in control of the individual glyph metrics relative to that. This is also a frequent source of headaches for web designers, and among the many articles out there, this one by Microsoft design stands out with a beautiful description and offers a solution: https://medium.com/microsoft-design/leading-trim-the-future-of-digital-typesetting-d082d84b202 . The two CSS properties described might be an elegant solution. It's just not clear yet if they'll advance in CSS.

As a third option, I think QML also had a font size mode that basically tried to fit the font size to automatically change so that everything fits into the given height.

What do you think?

jturcotte commented 1 year ago

About (1.), I don't understand why you can't just let the text overflow its own constrained bounds, is this a limitation of the renderer? Otherwise, even if it wouldn't fit, the worst case that I see is that the text could overlap with neighbor text. I generally also wouldn't expect clipping to happen either, unless clip is set to true.

About (2.), I think that slint is already doing a pretty good job and, for example, font_size: min(width, height) / 2; on a laid out Text is doing pretty much what I would expect it to do. Even if it might not be an exact sizing mechanism, it still allows me to tweak it up/down for a given font on a given backend.

So the issue that brought me here is that I don't have control to fill a (small) screen with a table full of text, unless I start laying out the text elements to have their bounds overlapping just so that I can end up with the actual glyphs superposed with only 1 or 2 px in-between. If possible, I'd rather have the option to grow the font_size almost past the Text's bounds so that I can have the option of tweaking it back down to do what I want.

For reference, this is the 240x160 mock-up I had with slint-lsp using the Qt backend: image

and this is how I discovered the issue, when I tried to make it use the GL backend and was wondering where the text went: image