Page MenuHome

Toolbar icon theming support
Closed, ResolvedPublicTO DO


Currently, the toolbar icons work well on dark backgrounds:

But on light backgrounds they become hard to read:

Since the toolbar icons are vectors, stored as meshes with materials, we could actually make the colors themable.

Each color is stored as a separate material, such as theme.general.base (white), theme.mesh.add (green), theme.mesh.modify (purple), theme.mesh.remove (Red) etc.

We could simply let the theme set these colors, so that bright themes can set the base color to be dark.

Event Timeline

Not sure if the outlines will be supported for these. Also I think it would look rather strange. It's cleaner to just use contrasting colors, rather than outlines

@William Reynish (billreynish) I think this was addressed in this revision.

Though for learning more, can I revert these changes and try the direction you hinted? I found the function def_internal_icon in interface_icons.c Line 181. But I couldn't find where the mesh colors are. If they are found, theme_color could be changed and this function could be called(alongside the one which currently changes all the colors.) whenever themes are changed. This would, however, redraw all the icons too.

Turns out my interpretation of the issue and the said commit was wrong. So questions now:

Which file is open the third screenshot (with the icons and colour settings) ?

Where are the icons stored ? as I came to know, they're in a blend file, but couldn't find which one.

source file:

utility to generate geometry icons:

these icons are stored in the ../datafiles/icons/ directory

BKE_icon_geom_from_memory - reading .dat files
BKE_icon_geom_rasterize - icon rasterization

See if this workflow can be used: Since the mesh material is stored in icon_geom.blend file, and it is accessible using some APIs (todo for me), they can be put in the datafiles in /datafiles/icons/ in the form of strings or hashes if required. This can be done if not done yet in the utility file Yevgeny mentioned.

Those values can be read in BKE_icon_geom_from_memory where now geom->colors is being updated. According to the theme, new colors can be assigned there, and then the Icon_Geom can be sent for rasterization.

Part two of the task will be to run this process again, or only the "assigning the color" part when the user changes the theme in Preferences.

Do comment about mistakes or starting points.

The ability colorize icons at runtime is available under Preferences/Themes: Icon Colors.
There doesn't appear to be categories for the toolbar icons, but this would be the best approach. Some of the Toolbar icons already appear to be colorized from their default white foreground.
It may be a matter of some interface hooks, or there may be another reason why these icons can't be colorized at this stage. In any case it may be the best option to start with how it's approached colorizing other icons I mentioned.
There may be some technical insights a developer can give, since there must be some reasoning behind the ability to colorize the toolbar icons not being available.

@JPG (joules) They are already dynamically displayed, and each color is a separate material, so that it's easy to set up for theming. All that needs to be added is the necessary hooks to the theming system.

Okay, was talking to @William Reynish (billreynish) and the following might be a nice and easy solution that would do all we need and would not require any extra theme settings:

The only real issue right now is that we are wanting the ability to select a light color for the background of the icons. That is now set in Themes / User Interface / Toolbar Item / Inner. Currently the value needs to be dark in order to give enough contrast with the colors of the icons.

But we could allow that background color to dictate the color of the icons themselves.

interface_icons.c icon_draw_size() has a btheme var. Use that to get the toolbar item inner color. Pass that along to BKE_icon_geom_rasterize(). Inside that function check to see whether that color is darkish or lightish. The best way to do that is to send the color to rgb_to_grayscale() and if over 0.5f then it is lightish. If darkish leave the icon colors as is. If light then convert the icon colors to HSV, using rgb_to_hsv(), invert the V (so 1 becomes 0 and 0 becomes 1) then convert back to rgb and use that. This way white portions of the icon will be black, black will be white, and light green will be dark green, dark blue will become light blue, etc.

I wrote the required for color inversion and it darkens the color when "inner" is light (>0.5f). This is the result of the diff I have attached:

The color(say in last icon) is black even when it is expected to be a darker shade (of say green) because the original color had the maximum component out of RGBA over 200, which translates to over V >= 80 in HSV. 1-V should be edited to 1-V + 0.35 or close to see better color at the expense of darkness.

Some comments I anticipate are:

  • not respecting const nature of const uint col.
  • whether the for loop used for separating RGB and A is endian-safe or not.
  • General formatting and code style guidelines.

Work to do: Making the icons change colour when in preferences, "inner" slider is changed.

@Ankit (ankitm) Thanks for this! Could you post your patch via the patch tracker: ?

Then add the User Interface group as a reviewer. Thanks!

Brecht Van Lommel (brecht) reopened this task as Confirmed.Feb 3 2020, 6:47 PM

With the colors auto inverting at least the icons are readable, I'll leave this task open if we want to make it possible to pick the specific colors.

@Brecht Van Lommel (brecht) IMO I think it’s fine to close this task now. The main issue was addressed. I would no longer push for any changes in this area for now.

Brecht Van Lommel (brecht) closed this task as Resolved.Feb 3 2020, 7:07 PM

@Brecht Van Lommel (brecht) - AFAIK we wouldn't have a way of selecting specific colors since all we are getting at the point we read them is rgb values, so there is nothing that can be used to group them.

One big "to do: though, is caching. These items take a while to rasterize and we are only caching one copy. So the cached copies are invalidated if we ask for a different size or (with this patch) if we require a reversed one. So the cache should be fairly useless right now in many circumstances as it is quite easy to get a workspace where we see multiple sizes.

Another "to do" would be to support multiple differing tool areas. So a set of tools that are light on dark background in one editor, while reversed in another.