在 GTK4 中,我们一直在尝试寻找更好的图像数据解决方案。在 GTK3 中,我们为此使用的对象是 pixbuf 和 Cairo surfaces。但是它们不再符合要求,所以现在我们有了 GdkTexture
和 GdkPaintable
。
GdkTexture
GdkTexture
是 GdkPixbuf
的替代品。为什么它更好?
首先,它简单得多。API 如下所示:
int gdk_texture_get_width (GdkTexture *texture); int gdk_texture_get_height (GdkTexture *texture); void gdk_texture_download (GdkTexture *texture, guchar *data, gsize stride);
因此,它是一个 2D 像素数组,如果需要,您可以下载像素。它也被保证是不可变的,所以像素永远不会改变。存在许多构造函数可以从文件、资源、数据或 pixbuf 创建纹理。
但是纹理和 pixbuf 之间最大的区别在于它们不暴露用于存储像素的内存。事实上,在调用 gdk_texture_download()
之前,这些数据甚至不需要存在。
这在 GL 纹理中使用。例如,GtkGLArea 小部件 使用此方法来传递数据。GStreamer 也期望以 GL 纹理的形式传递视频。
GdkPaintable
但有时,您会拥有比不可变的一堆像素更复杂的东西。例如,您可能有一个动画 GIF 或一个可缩放的 SVG。这就是 GdkPaintable
的用武之地。
抽象地说,GdkPaintable
是一个接口,用于知道如何在任何大小下渲染自身的对象。受 CSS 图像 的启发,它们可以选择性地提供 GTK 小部件可用于放置它们的固有尺寸信息。
因此,GdkPaintable 接口的核心是使可绘制对象渲染自身的函数,以及提供尺寸信息的 3 个函数
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);
最重要的是,当可绘制对象的内容或大小更改时,它可以发出“invalidate-contents”和“invalidate-size”信号。
为了使其更加具体,让我们以一个可缩放的 SVG 为例:可绘制对象的实现将返回没有固有大小(这些尺寸函数的返回值 0 即可实现),并且每次绘制时,它都会以给定大小绘制自身像素精确。
或者以动画 GIF 为例:它会提供其像素大小作为其固有大小,并将动画的当前帧缩放到给定大小。并且每当应该显示动画的下一帧时,它都会发出“invalidate-size”信号。
最后但并非最不重要的一点是,GdkTexture
实现了此接口。
我们目前正在更改 GTK3 中接受 GdkPixbuf
的所有代码,现在接受 GdkPaintable
。当然,GtkImage
小部件已经更改,拖放图标或 GtkAboutDialog
也已更改。存在实验性补丁,允许应用程序向 GTK CSS 引擎提供可绘制对象。
如果您现在将所有关于 GStreamer 可能提供由 GL 图像支持的纹理,并创建可以上传到 CSS 的动画的可绘制对象的信息放在一起,您也许可以 看到它的发展方向……