RFC: Provide library to handle icon themes
Bilal and I have been talking about making a library to handle (symbolic) icon themes directly in librsvg. Some goals:
- Take a complete
icon-theme.svg
and be able to enumerate icons, render them individually, recolor them, etc. Basically, remove the need for splitting SVGs into individual icons just for the sake of consuming them from GTK — generally, make the workflow easier for artists. - Make GTK use this library directly for loading/rendering icons, instead of loading individual images indirectly via GdkPixbufLoader.
This comment has some related discussion on things GTK needs to change about recoloring icons.
RFC from artists
I'd love to have some input from the artists, because I don't know their whole workflow. Librsvg will soon have support for providing custom stylesheets and maybe CSS variables.
What sort of functionality would you like in a to manage/preview icons? I'm aware of symbolic-preview, but haven't read the whole source code to see what it wants to support
Would the same tool manage symbolic icon themes and application icons? I'm not very familiar with the design workflow for app icons.
What sort of recoloring would you like to do at rendering time, or any other kind of CSS paraphernalia? Are there CSS features that you need that librsvg doesn't support yet?
Have you had the need to sanitize icon theme SVGs, something like ensuring that all <g>
have a <title>
, that the icon names inside the <title>
are not duplicated, things like that?
RFC from coders
Right now the librsvg source tree is organized like this:
-
librsvg
- provides the C API around... -
rsvg_internals
- the actual implementation of librsvg -
librsvg_crate
- provides a Rust API around the former
We can have another module in there, a libicontheme
or whatever we want to call it. A sketch of the API:
pub struct IconTheme { ... };
impl IconTheme {
pub fn load(stream: &gio::InputStream) -> Result<Self>;
pub fn iter(&self) -> Icons;
pub fn get_icon(&self, name: &str) -> Result<Icon>;
}
pub struct Icons { ... };
impl Iterator for Icons {
type Item = Icon;
fn next(&mut self) -> Option<Self::Item>;
}
pub struct Icon { ... };
impl Icon {
pub fn get_name(&self) -> String;
pub fn get_layer(&self) -> String;
// this could even provide a gtk::Snapshot or whatever GTK4 likes to do
pub fn render(&self, cr: &cairo::Context, recoloring: RecoloringParams) -> Result<()>;
}
We can iterate on the Rust API quickly, and later wrap it with a C API for GTK's consumption.
AFAICT from the icon theme files, icons have a name in the <title>
of their corresponding group, and may live inside an Inkscape layer. I think the API should preserve this information so the tool can do things like only show icons corresponding to a layer.
Implementing the library
Feel free to change rsvg_internals
to make things pub
as necessary. This sub-library is never exported, so there is no need to maintain a stable API for it (the wrapper c_api and librsvg_crate are the stable ones).
There are the beginnings of internals documentation here. I'm still filling those in; if you need some docs urgently, ping me and I'll write them.
Some useful things to get this new library started:
The Document
struct represents a loaded SVG. It has a tree
field with the root of the element tree; each element is an RsvgNode
, which is a type alias for rctree::Node<rsvg_internals::NodeData>
.
The thing that actually loads the Document
and lets you render sub-elements is a Handle
. This is somewhat lower-level than the librsvg::SvgHandle
from the public API, but is very similar in principle. I think the new library's IconTheme::load
would use this directly.
NodeData
NodeData
is the data for each element. Its node_type
field is where you would ask, "is this element a <g>
(a NodeType::Group
", for example.
The tree of nodes
rctree::Node
has the tree-walking methods like first_child
, next_sibling
, etc.
To get a NodeData
from a Node
, you do node.borrow()
.
Open questions
What's the overhead of 1) GTK loading each icon.svg
individually (i.e. lots of I/O on scattered files) versus 2) GTK loading a single icon-theme.svg
once (probably more memory consumption since unused icons are also loaded; less I/O)?
For memory consumption see #528 (closed) - there are some easy wins we can get to reduce the per-element memory usage.