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

Support separate background and foreground color on UI text #5935

Open
Weibye opened this issue Sep 10, 2022 · 12 comments
Open

Support separate background and foreground color on UI text #5935

Weibye opened this issue Sep 10, 2022 · 12 comments
Labels
A-Text Rendering and layout for characters A-UI Graphical user interfaces, styles, layouts, and widgets C-Enhancement A new feature

Comments

@Weibye
Copy link
Contributor

Weibye commented Sep 10, 2022

What problem does this solve or what need does it fill?

We would like to be able to support things like text-highlighting, text-selection and generally improve what we can do with text in our UI. These require that we can color foreground and background of the text independently.

At the moment we have support for foreground color of text in the text sections, but we have no background color support.

What solution would you like?

Not completely sure which approach is correct. Either add a background-color field to TextBundle or add background color to the TextSection.

We probably need the latter if we want to want to support highlighting of arbitrary sections of text, but this is going to be very interesting how it would work with things like "user marks arbitrary text that gets highlighted". Maybe these need to be multiple but separated features?

What alternative(s) have you considered?

  • Not supporting it.
  • Other approaches for text highlighting that is not connected to the TextBundle / TextSection.
@Weibye Weibye added C-Enhancement A new feature A-UI Graphical user interfaces, styles, layouts, and widgets labels Sep 10, 2022
@afonsolage
Copy link
Contributor

I don't know the implementation details, but I feel this should be added to TextSection, since it already has a TextStyle property.

@djeedai
Copy link
Contributor

djeedai commented Sep 17, 2022

Can you please describe precisely what a "text background color" is here?

  • the color of the rect of each glyph separately (probably not, but including to show the confusion)
  • the color of a rect extending from the ascent to the descent lines vertically (typically used for text highlight)
  • the color of the bounding rect of the text taken as a UI element (node), including any potential padding

You can achieve 3. by wrapping the text into a parent Node; that's typically how I do "text background" when I need it, but I consider that different from text highlighting.

I think the request is about 2., in which case this is related to another issue about the fact we discard the position of the glyphs relative to the baseline in the text pipeline and instead always position text based on the bounding box of the glyphs, which is wrong.

@Weibye
Copy link
Contributor Author

Weibye commented Sep 17, 2022

Yeah, don't really know enough about this to know exactly how this should be done, but from your description I think that 2. is what users really want.

@djeedai
Copy link
Contributor

djeedai commented Sep 17, 2022

Item 2. is when you highlight a text by selecting it. The selection needs to be of constant height whatever the text so the height is based on the font metrics, not the actual text content (glyphs used). "ace" and "pub" would have the same background rectangle height despite the "p" and "b". Most likely this is what we want to implement with this issue indeed.

Item 3. is when you place a single-word text inside a rect as e.g. a button and you want it aligned in some particular way, possibly with borders and padding, and you want visually the same spacing around all sides, so depends on the text content(*).

(*) Actually typography purists would probably argue that even for a button you want to align from the baseline and font metrics so it's a bad example. But it's good enough to understand I think. 😊

@ghost
Copy link

ghost commented Sep 18, 2022

Can you please describe precisely what a "text background color" is here?

  • the color of the rect of each glyph separately (probably not, but including to show the confusion)
  • the color of a rect extending from the ascent to the descent lines vertically (typically used for text highlight)
  • the color of the bounding rect of the text taken as a UI element (node), including any potential padding

You can achieve 3. by wrapping the text into a parent Node; that's typically how I do "text background" when I need it, but I consider that different from text highlighting.

I think the request is about 2., in which case this is related to another issue about the fact we discard the position of the glyphs relative to the baseline in the text pipeline and instead always position text based on the bounding box of the glyphs, which is wrong.

After reading alexheretic/glyph-brush#153, it looks like we're stuck with only the glyph bounds with their section and index. When drawing backgrounds, we need to:

  1. Add text_background_color and text_highlight_color to TextStyle and highlight_index and highlight_length to the Text component.
  2. Split the glyphs into lines and calculate the max ascent and minimum descent for each line.
  3. Calculate the rects of all backgrounds with an alpha greater than 0 and add them to TextLayoutInfo.
  4. Render these rects behind glyphs for text2d and bevy_ui.

@djeedai
Copy link
Contributor

djeedai commented Sep 18, 2022

Split the glyphs into lines and calculate the max ascent and minimum descent for each line.

If you try to implement text highlighting (option 2.) with this, you will end up with line backgrounds of varying heights and that will look ugly.

@ghost
Copy link

ghost commented Sep 18, 2022

Split the glyphs into lines and calculate the max ascent and minimum descent for each line.

If you try to implement text highlighting (option 2.) with this, you will end up with line backgrounds of varying heights and that will look ugly.

I don't understand what you mean. Google Docs does something similar to this:
Screenshot from 2022-09-18 11-59-07

@ghost
Copy link

ghost commented Sep 18, 2022

It may be useful to store information about each line with lines: Vec<{glyph_count: u32, max_ascent: f64, min_descent: f64}> in TextLayoutInfo. This will reduce redundant computation for a TextArea widget in the future because of input handling.

@djeedai
Copy link
Contributor

djeedai commented Sep 18, 2022

If you try to implement text highlighting (option 2.) with this, you will end up with line backgrounds of varying heights and that will look ugly.

I don't understand what you mean. Google Docs does something similar to this: Screenshot from 2022-09-18 11-59-07

Google Docs seems to do exactly what I describe based on font metrics, with the extra complication of using multiple font sizes per line: take the max of all ascents and descents of all fonts used in the line, so based on font metrics alone and not on the actual glyphs used in the line. Your statement "we're stuck with only the glyph bounds" seems to imply you want to calculate the max ascent and descent of each glyph actually used in the line, which will cause a line with "pub" to have an highlight a lot taller than a line with "ace", for a same font and font size.

@djeedai
Copy link
Contributor

djeedai commented Sep 18, 2022

Actually the ascent and descent are per font and not per glyph so I'm not sure what you were talking about referencing the glyph bounds (which have no typographic meaning). Maybe we're talking about the same thing?

@djeedai
Copy link
Contributor

djeedai commented Sep 18, 2022

It may be useful to store information about each line with lines: Vec<{glyph_count: u32, max_ascent: f64, min_descent: f64}> in TextLayoutInfo. This will reduce redundant computation for a TextArea widget in the future because of input handling.

Ascent and descent are font properties unrelated to what glyphs are used in the line. There's no need to store nor calculate anything because if I remember correctly we cannot use multiple fonts nor font sizes per section.

bors bot pushed a commit that referenced this issue Feb 20, 2023
# Objective

`TextBundle` should have a `BackgroundColor` component.

Apart from adding emphasis etc to text, adding a background color to text nodes can be extremely useful for understanding how Bevy aligns, sizes and positions text, and identifying and debugging problems.

It's easy for users to insert the `BackgroundColor` component themselves but not immediately obvious or discoverable that it's possible. A `BackgroundColor` component allows us to add a `with_background_color` helper function to `TextBundle`.

related issue: #5935

## Solution

Add a `BackgroundColor` component to `TextBundle`.

---

## Changelog

* Added a `BackgroundColor` component to `TextBundle`.
* Added a helper method `with_background_color` to `TextBundle`.

## Migration Guide
`TextBundle` now has a `BackgroundColor` component. 

Use `TextBundle`'s `background_color` field or the `with_background_color` method to set a background color for text when spawning a text node, in place of manual insertion of a `BackgroundColor` component.
@JMS55
Copy link
Contributor

JMS55 commented Dec 19, 2023

Is this completed by #7596 ?

@viridia viridia added the A-Text Rendering and layout for characters label Apr 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Text Rendering and layout for characters A-UI Graphical user interfaces, styles, layouts, and widgets C-Enhancement A new feature
Projects
None yet
Development

No branches or pull requests

5 participants