RazrFalcon / resvg

An SVG rendering library.
Mozilla Public License 2.0
2.74k stars 220 forks source link

Feature request: render Tree as Mask #624

Closed Pr0methean closed 1 year ago

Pr0methean commented 1 year ago

For an app of mine, I often need only the opacity mask of a rasterized SVG file and not the colors. Being able to render the Tree directly into a Mask would probably be faster than rendering to a Pixmap and passing it to Mask::from_pixmap, because the color channels wouldn't need to be calculated and discarded.

RazrFalcon commented 1 year ago

You cannot render SVG to a mask. It's a fundamentally a RGBA format. We would have to disable filters and raster images. Also, tiny-skia is RGBA-only as well. It doesn't have a grayscale mode.

This feature would require significant changes with close to zero benefits. Out of scope.

Pr0methean commented 1 year ago

Is there any format you can suggest using instead for paths that contain diagonals and curves that need to be rasterized, but only for their anti-aliased opacity? My app works mostly by using SVGs to define layers, then using DSL code to define which layers are stacked to create which texture and what color each layer is painted. Most of the layers are used in more than one texture, and a lot of the app's code serves to de-duplicate reusable layers while still keeping the memory footprint under control. A few SVGs contain colors (and usually gradients) and are rendered out without being repainted, but they're the exception rather than the rule. The app is at https://github.com/Pr0methean/OcHd-RustBuild.

RazrFalcon commented 1 year ago

There are only two open-ish vector formats out there: SVG and PDF. And both are a nightmare to use. PDF does support grayscale mode, but I don't think there are any good PDF rendering libraries for rust. So you would need to use C/C++ one.

I would suggest parsing SVG manually, using something like roxmltree or even usvg if you have no control over input SVG. Then writing your own renderer, which should take like 20 LOC to render lines for tiny-skia::Mask (remember that tiny-skia::Mask is still using the RGBA pipeline as of now).

You need a very niche solution and the Rust ecosystem is too young for that.

PS: to be honest, judging by your app, your would never hit a performance bottleneck. Don't even bother.