With GTK4, we’ve been trying to find better solution for image data. In GTK3 the objects we used for this were pixbufs and Cairo surfaces. But they don’t fit the bill anymore, so now we have
GdkTexture is the replacement for
GdkPixbuf. Why is it better?
For a start, it is a lot simpler. The API looks like this:
int gdk_texture_get_width (GdkTexture *texture); int gdk_texture_get_height (GdkTexture *texture); void gdk_texture_download (GdkTexture *texture, guchar *data, gsize stride);
So it is a 2D pixel array and if you want to, you can download the pixels. It is also guaranteed immutable, so the pixels will never change. Lots of constructors exist to create textures from files, resources, data or pixbufs.
But the biggest difference between textures and pixbufs is that they don’t expose the memory that they use to store the pixels. In fact, before
gdk_texture_download() is called, that data doesn’t even need to exist.
And this is used in the GL texture. The GtkGLArea widget for example uses this method to pass data around. GStreamer is expected to pass video in the form of GL textures, too.
But sometimes, you have something more complex than an immutable bunch of pixels. For example you could have an animated GIF or a scalable SVG. That’s where
GdkPaintable comes in.
In abstract terms,
GdkPaintable is an interface for objects that know how to render themselves at any size. Inspired by CSS images, they can optionally provide intrinsic sizing information that GTK widgets can use to place them.
So the core of the GdkPaintable interface are the function make the paintable render itself and the 3 functions that provide sizing information:
void gdk_paintable_snapshot (GdkPaintable *paintable, GdkSnapshot *snapshot, double width, double height); int gdk_paintable_get_intrinsic_width (GdkPaintable *paintable); int gdk_paintable_get_intrinsic_height (GdkPaintable *paintable); double gdk_paintable_get_intrinsic_aspect_ratio (GdkPaintable *paintable);
On top of that, the paintable can emit the “invalidate-contents” and “invalidate-size” signals when its contents or size changes.
To make this more concrete, let’s take a scalable SVG as an example: The paintable implementation would return no intrinsic size (the return value 0 for those sizing function achieves that) and whenever it is drawn, it would draw itself pixel-exact at the given size.
Or take the example of the animated GIF: It would provide its pixel size as its intrinsic size and draw the current frame of the animation scaled to the given size. And whenever the next frame of the animation should be displayed, it would emit the “invalidate-size” signal.
And last but not least,
GdkTexture implements this interface.
We’re currently in the process of changing all the code that in GTK3 accepted
GdkPixbuf to now accept
GtkImage widget of course has been changed already, as have the drag’n’drop icons or
GtkAboutDialog. Experimental patches exist to let applications provide paintables to the GTK CSS engine.
And if you now put all this information together about GStreamer potentially providing textures backed by GL images and creating paintables that do animations that can then be uploaded to CSS, you can maybe see where this is going…
5 thoughts on “textures and paintables”
This seems to be perfectly fitted for the needs of retro-gtk, thanks!
Why is gdk_paintable_get_intrinsic_aspect_ratio() returning an int? Is it using fixed point?
What about the GIcon abstraction? Are those two objects inheriting GIcon to be able to hash/serialize them?
Copy and paste thinko; this was already fixed.
Please, file an issue the next time. :-)
Comments are closed.