slint-ui / slint

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

[RFC] Text stroke/outline support #4981

Closed nununoisy closed 6 months ago

nununoisy commented 7 months ago

Text strokes are super useful for boosting text contrast in certain situations, especially when drawing on dynamic content. It doesn't seem like it would be that hard to add them since some of the rendering backends already support them:

The only difficulty here would be the software renderer:

For those reasons, I think it makes sense to just leave text stroking unsupported in the software renderer for now.

As for the markup, we could borrow the syntax from the stroke properties for Rectangle:

In addition, by varying the draw order, we could also allow the selection of outline styles/insets:

Example image

If this syntax is acceptable, I'd be happy to author a PR to get this support in.

tronical commented 7 months ago

Yes, I think that makes sense. I'd start with stroke and stroke-width first, and leave out stroke-style for a second step.

Implementation wise, it might be worth adding a TextWithOutline or TextWithStroke in builtins.slint so that regular Text elements don't pay the price of the additional properties.

Regarding the software renderer, yeah, I think swash is the way to go. Perhaps this could also be done separately, i.e. stroke first for the other renderers, then we worry about swash, and then implement it for the software renderer - i.e. separate PRs.

Olivier, what do yo think?

nununoisy commented 7 months ago

Right. I've already begun implementing this according to the earlier spec and I have functioning implementations with support for stroke styles working on FemtoVG, Skia, and Qt. Besides an extra if statement, they don't incur any additional overhead if stroking is disabled. Right now I'm checking the stroke width to see if it's non-zero, but it might make more sense to instead check the stroke brush to see if it's transparent so that a zero stroke width can correspond to a hairline stroke.

Is there any particular reason you want to push out stroke-style to a next step? It's not complicated at all to implement, but I could see the syntax being undesirable. Perhaps it could make more sense to generalize the TextStrokeStyle struct so we can extend the syntax to Rectangles and Paths also by implementing outside strokes for those elements. In fact, it would be nice also to be able to control other aspects of the stroke, like the cap, bevels, miter limit, etc.; that's probably in the territory of a separate issue.

Along those lines, in the meantime, should it be a center or outside stroke? Center strokes are the default in most illustration programs, but outside strokes are much more popular in UI design because they don't mess up the proportions of the font. In fact, there are CSS properties for center text strokes, but most web designers prefer to use box-shadows in a hacky way because it's the only way to get outside strokes.

tronical commented 7 months ago

Is there any particular reason you want to push out stroke-style to a next step?

I was just thinking in terms of complexity, but if you’re confident about it then no problem.

I would also lean to outside stroke as default for text.