在 GTK4 中,我们一直在尝试为图像数据寻找更好的解决方案。在 GTK3 中,我们用于此目的的对象是 pixbufs 和 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 像素数组,如果您愿意,可以下载像素。它也保证是不可变的,因此像素永远不会改变。存在许多构造函数,可以从文件、资源、数据或 pixbufs 创建纹理。
但是纹理和 pixbufs 之间最大的区别在于,它们不公开用于存储像素的内存。事实上,在调用 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 的动画的可绘制对象的信息放在一起,您也许可以 看到它的发展方向…
这似乎非常适合 retro-gtk 的需求,谢谢!
为什么 gdk_paintable_get_intrinsic_aspect_ratio() 返回一个整数?它使用的是定点数吗?
那么 GIcon 抽象呢?这两个对象是否继承 GIcon 以便能够对其进行哈希/序列化?
复制粘贴错误;这已经修复了。
下次请提交问题。 :-)