Open abey79 opened 1 year ago
Comment from @emilk:
We should create a proper issue about how to do icons. Some quick, random thoughts:
There are at least three things to consider:
- Ease of changing out icons (e.g just drop a .png or .svg in folder)
- Low code bloat (don't increase .wasm size too much)
- Visual quality (icons shouldn't be blurry, no matter what dpi scaling the user has)
There are two major ways to go.
Imagers (e.g. .png)
- very easy to create and use
but one imager will never be optimal for all resolution scalings.
- we could export one high-res .png and dynamically rescale it to fit the users resolution. Pretty easy to implement, and low code bloat.
Vector graphics
Using
epaint
vector rendering (like this PR) works great (proper anti-aliasing for all resolutions), but only for convex polygons.Dor concave polygons we either need to implement something new in epaint, or use some 3rd party rendering tool (more code bloat)
egui_extras
uses a lot of dependencies for this, see https://docs.rs/egui_extras/latest/egui_extras/image/struct.RetainedImage.html#method.from_svg_bytes
.svg
is a horribly complex format. tinyvg is an interesting new alternative, but still requires us to ship code for parsing and rasterizing, increasing .wasm size.Conclusions?
I'm leaning towards using a single high-res .png for each icon, then resize it using some high-quality algo (e.g. Lanczos filtering) to create a crisp icon for the current resolution scaling.
Easy to use, easy to implement, high-quality, low code bloat.
My two three cents:
1) On code bloat: we currently have 29kB worth of PNGs pulled into the binary. Assuming a doubling of resolution (48x48), that would scale to about 120kB. A vector representation would arguably reduce this significantly (10x?). Does that represent a significant budget for some (acceptable) code bloat?
2) I'd stay away from SVG: too complex and not mature enough. An alternative could be the SVG path
format (e.g. L10,10 Q20,20 30,30 Z
). kurbo has a parser for that and seems like a very lightweight dependency (by default, no sub-dependency that we dont already have). This would require building a render with support for concave shapes and even-odd fill rules.
3) Developing said renderer might be simpler if we cache bitmaps at the desired resolution (as opposed to including it in epaint
and the egui render loop), even CPU based. That approach could further limit code bloat at the expense of a little memory and CPU time at start-up (or upon first displaying a given icon).
did we already consider creating a font at build time from input vector data and use that? Egui already handles font rendering, meaning that a vector graphics library is already dragged in
did we already consider creating a font at build time from input vector data and use that? Egui already handles font rendering, meaning that a vector graphics library is already dragged in
We'd end up pulling a font-building library I guess, but I like this idea :)
Example of putting icons in a font for egui: https://github.com/amPerl/egui-phosphor
It appears to be just using pre-packaged fonts.
Which leads to the idea of storing our icons in a font file, and just editing/adding icon with e.g. FontForge (or some scripts). Then we just need a bunch of constants to map icon names to unicode characters.
Online tool to build font from SVG: https://www.glyphter.com
It should be relatively straightforward to have a script converting a bunch of SVGs into a TTF font and generate the corresponding re_ui
constants.
One downside of the font approach is that it will only support monochrome icons (epaint doesn't support color emojis)
Whatever we chose should be compatible with:
(forked from discussion in #2920)
We currently use 24x24px png exported from Figma.
This approach has two shortcomings:
Moving forward, our strategy for icons should enable:
cc @martenbjork @emilk