Animated icons for GTK

I have been working for a while on GTK support for stateful, animated, symbolic icons. This post is meant to provide an introduction to the format, and encourage experimentation with it. The code will land very soon in GTK 4.21.

Features

At its core, an icon is a an array of paths, which get stroked or filled to render the icon. We allow symbolic as well as fixed colors.

An icon can provide a number of states, and each path can be present in a subset of states.
Thus changing the state an icon can cause paths to appear and disappear. We allow animating
these transitions in various ways (blur, fade, animate).

It is also possible to animate a path continuously in a given state, in various ways.

Examples for transitions and animations can be seen here.

The provided transition and animation styles are very much up for discussion and extension.

The format has some other features and parameters that are best explored while playing
with examples.

Tools

While working on this, I’ve written an icon editor. Currently, it lives as a demo in the GTK repository, but it might end up as a standalone tool eventually.

The application will be available as org.gtk.Shaper in the gnome-nightly flatpak remote very soon.

Documentation

The documentation for the format can be found here, and the documentation for the new paintable implementation can be found here.

Answers to some questions

  1. Why use an SVG-based format, instead of something more compact and binary, such as OpenType fonts ?

Experience (e.g. the ‘symbolic png’ format) has shown that our designers are unwilling to use formats other than SVG. Inkscape is the tool of choice, and anything that is not interoperable with that tool is going to fail.

  1. Why not just use SVG ? It does animation, doesn’t it ?

SVG animation is different in style from what we are interested in here (dynamic strokes and state transitions). We don’t have a SVG library that handles animation. And even if we did, it would require tight integration with our CSS machinery, which it is not set up for.

  1. Why use a handrolled parser instead of librsvg ?

For these icons to fully integrate with the GTK renderer, we need the SVG scene graph to be translated into render nodes. At this time, librsvg only offers a cairo-based API for delivering its results, which can’t do that.

  1. Why is this not an XDG standard ?

It is much too early to think about setting this format in stone. At this point, it needs adoption and experimentation, to see what works, what doesn’t, and what is missing.

11 Likes

One recommendation:

What is called “Blur” here is actually “Morph” or “Interpolated Path” or “Tweened”. If you call it “Blur” you will confuse both users of Inkscape where Blur is a non-animated feature of the filters available i the fill and stroke dialog. And graphics artists who might expect the Blur-out / Blur-in animation feature instead.

1 Like

There is no morphing here.

The effect is implemented as a combination of blur + component transfer.
I am certainly open to calling it something else.
I’m not privy to digital artist lingo.
I think Jakub was asking for ‘blobbing’.

There was some reference to ‘liquid charcoal’ too, but maybe that was a joke :slight_smile:

1 Like

Now I look more carefully, I can see how it’s “blobbing” and the use of component transfer to produce a harsh cut off for an ever more amorphous shape is kinda genius. I hope that’s you invention so I can praise you directly :smile:

I think blur-in/out is exactly what you have minus the component transfer. The effect is quite liquid like, so there’s a bunch of water type words like might work for it. Droplet, bead, dew, drip, ooze, splash, and some onomatopoeias like “blop”, “bloob” etc

My partner suggests “morph”

1 Like

I will call it blob, I think.

Jakub suggested to use alpha thresholding to get the effect. I implemented component transfer filters in our rendering machinery to use for this. Teamwork :slight_smile:

Thanks!

I’m currently rewriting Inkscape’s filters code and was doing the component transfer work a few days ago. I’d like to compare your implementation, would that be possible? Can you point me to the right codebase/files?

Sure. It lives here:

This is the cairo implementation:

And this is the GL/Vulkan one:

I ended up going with ‘morph’ for the name of the effect after all, btw.

1 Like

Ah interesting. My poll wasn’t complete: Martin Owens :inkscape:: "Post your alts as replies if you have better word…" - FLOSS.social but shows this to be the strongest option by opinion.

Oh, very nice. Thanks for doing that poll

Thanks for posting the code, we’ll probably end up moving to something on the gpu eventually, but for now we’re moving away from ARGB32 cairo, and towards at least RGBA128F to do more complex color work. The new system is entirely floating point so we’re moving away from bit shifting calculations for example.

Or at least, that’s the plan. Nothing useful for your current direction I think.

Tangentially related, here is my tracker for how much of the svg filters we currently support in our renderer:

Hi,
I’ve an icon that should be horizontally flipped when using a RTL locale. Currently, for this usecase, we have to provide 2 icons files.

In this new format, would it make sense to add a kind of auto-flip flag that, when set, automatically renders the icon flipped in RTL?

You can do that with CSS, such flag feels out of scope for this.

e.g.

.my-icon:dir(rtl) {
 transform: rotateY(180deg);
}
1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.