emilk / egui

egui: an easy-to-use immediate mode GUI in Rust that runs on both web and native
https://www.egui.rs/
Apache License 2.0
22.06k stars 1.59k forks source link

Proposal: SVGImage API that is separate from RetainedImage #2219

Open bluskript opened 1 year ago

bluskript commented 1 year ago

Is your feature request related to a problem? Please describe. Currently, there is a problem with the current way SVGs are rendered: it is rasterized once, using the scale that the SVG file itself provides, and is reused regardless of render size.

This introduces various artifacts depending on resolution:

On low resolutions, ferris looks crunchy and not very smooth! image

On high resolutions however, ferris looks low-detailed and pixelated. image

Describe the solution you'd like I think a separate SVGImage struct, alongside RetainedImage, would be appropriate. This would store an initial pixmap for the size the SVG specifies, but would rasterize a new pixmap and cache it whenever one is requested for a resolution that does not yet exist. This may need some optimization / laziness however, because it might not be worth re-rasterizing SVGs if the size difference is only by a few pixels.

Describe alternatives you've considered Rasterizing a series of difference resolution pixmaps of SVGs and changing them as needed. This has the potential downside of more memory usage, but would be more performant.

bluskript commented 1 year ago

Update: Seems like there's better ways to approach this, most likely to proceed by implementing mipmapping as well as providing a way for users to select a custom size to pre-render SVGs at.

LoganDark commented 1 year ago

I would like to see SVGs rendered as vectors rather than cached as bitmaps imho

GreatGodOfFire commented 1 year ago

Another problem with the current SVG implementation is that it is slow. Rasterizing 12 SVGs with a resolution of 100x100 pixels takes my computer around 2 seconds in debug mode and around 700ms in release mode. Maybe tessellating the SVGs with lyon and rendering them as a mesh yields better performance?

barries commented 1 week ago

Adding some more examples, because I happen to be comparing egui to two other GUI frameworks and tripped over this today. So, for reference, some magnified screen caps for an .svg file that was drawn w/ height 30px and is being displayed with height 64px:

Very old Electron.js + Ubuntu 18.04: image

Recent WebKit on Tauri + Windows 11 Pro: image

egui 0.28.1 on Windows 11 Pro: image

This was a surprise because both our shipping app (Electron.js) and a proof-of-concept Tauri prototype handled this smoothly (lol)--I wasn't even aware of that the image was "smaller" until I saw it rendered in egui. My goal, FWIW, is to switch to egui--I think there are significant advantages for our app. the Tauri step allowed us to keep our view in HTML+CSS and port the app logic to Rust, now I'm trying to "thin down" from a web front-end to native, pure Rust.