From: Benjamin Otte Date: Wed, 14 Mar 2018 03:45:25 +0000 (+0100) Subject: image: Load resources and files into textures X-Git-Tag: archive/raspbian/4.4.1+ds1-2+rpi1^2~18^2~22^2~939 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=7844320f1031cf83f69b3c15e19c7e49d038d0bb;p=gtk4.git image: Load resources and files into textures Instead of loading them into surfaces (which we want to get rid of), we load into textures. In fact, we introduce a new paintable subclass called a GtkScaler that takes care of tracking scaling. This also ideally gets rid of an extra conversion once renderers learn to render textures directly. --- diff --git a/demos/gtk-demo/main.c b/demos/gtk-demo/main.c index a5e7388888..95798c7c2f 100644 --- a/demos/gtk-demo/main.c +++ b/demos/gtk-demo/main.c @@ -555,7 +555,7 @@ add_data_tab (const gchar *demoname) resource_name = g_strconcat (resource_dir, "/", resources[i], NULL); widget = gtk_image_new_from_resource (resource_name); - if (gtk_image_get_surface (GTK_IMAGE (widget)) == NULL) + if (gtk_image_get_texture (GTK_IMAGE (widget)) == NULL) { GBytes *bytes; diff --git a/gtk/gtkcellrendererpixbuf.c b/gtk/gtkcellrendererpixbuf.c index 1c043a3a46..a217634f94 100644 --- a/gtk/gtkcellrendererpixbuf.c +++ b/gtk/gtkcellrendererpixbuf.c @@ -381,7 +381,7 @@ gtk_cell_renderer_pixbuf_set_property (GObject *object, take_image_definition (cellpixbuf, gtk_image_definition_new_surface (g_value_get_boxed (value))); break; case PROP_TEXTURE: - take_image_definition (cellpixbuf, gtk_image_definition_new_texture (g_value_get_object (value), 1)); + take_image_definition (cellpixbuf, gtk_image_definition_new_texture (g_value_get_object (value))); break; case PROP_ICON_SIZE: gtk_cell_renderer_pixbuf_set_icon_size (cellpixbuf, g_value_get_enum (value)); diff --git a/gtk/gtkiconhelper.c b/gtk/gtkiconhelper.c index 26c1b2ca4a..e5acea210c 100644 --- a/gtk/gtkiconhelper.c +++ b/gtk/gtkiconhelper.c @@ -626,7 +626,7 @@ void _gtk_icon_helper_set_texture (GtkIconHelper *self, GdkTexture *texture) { - gtk_icon_helper_take_definition (self, gtk_image_definition_new_texture (texture, 1)); + gtk_icon_helper_take_definition (self, gtk_image_definition_new_texture (texture)); } void diff --git a/gtk/gtkimage.c b/gtk/gtkimage.c index 3013a93a29..fbddabd930 100644 --- a/gtk/gtkimage.c +++ b/gtk/gtkimage.c @@ -31,6 +31,7 @@ #include "gtkicontheme.h" #include "gtkintl.h" #include "gtkprivate.h" +#include "gtkscalerprivate.h" #include "gtksnapshot.h" #include "gtktypebuiltins.h" #include "gtkwidgetprivate.h" @@ -729,7 +730,8 @@ gtk_image_set_from_file (GtkImage *image, GtkImagePrivate *priv = gtk_image_get_instance_private (image); GdkPixbufAnimation *anim; gint scale_factor; - cairo_surface_t *surface; + GdkTexture *texture; + GdkPaintable *scaler; g_return_if_fail (GTK_IS_IMAGE (image)); @@ -753,11 +755,13 @@ gtk_image_set_from_file (GtkImage *image, return; } - surface = gdk_cairo_surface_create_from_pixbuf (gdk_pixbuf_animation_get_static_image (anim), - scale_factor, _gtk_widget_get_window (GTK_WIDGET (image))); - gtk_image_set_from_surface (image, surface); - cairo_surface_destroy (surface); + texture = gdk_texture_new_for_pixbuf (gdk_pixbuf_animation_get_static_image (anim)); + scaler = gtk_scaler_new (GDK_PAINTABLE (texture), scale_factor); + gtk_image_set_from_paintable (image, scaler); + + g_object_unref (scaler); + g_object_unref (texture); g_object_unref (anim); priv->filename = g_strdup (filename); @@ -809,7 +813,8 @@ gtk_image_set_from_resource (GtkImage *image, GtkImagePrivate *priv = gtk_image_get_instance_private (image); GdkPixbufAnimation *animation; gint scale_factor = 1; - cairo_surface_t *surface; + GdkTexture *texture; + GdkPaintable *scaler; g_return_if_fail (GTK_IS_IMAGE (image)); @@ -840,10 +845,13 @@ gtk_image_set_from_resource (GtkImage *image, return; } - surface = gdk_cairo_surface_create_from_pixbuf (gdk_pixbuf_animation_get_static_image (animation), - scale_factor, _gtk_widget_get_window (GTK_WIDGET (image))); - gtk_image_set_from_surface (image, surface); - cairo_surface_destroy (surface); + texture = gdk_texture_new_for_pixbuf (gdk_pixbuf_animation_get_static_image (animation)); + scaler = gtk_scaler_new (GDK_PAINTABLE (texture), scale_factor); + + gtk_image_set_from_paintable (image, scaler); + + g_object_unref (scaler); + g_object_unref (texture); priv->resource_path = g_strdup (resource_path); diff --git a/gtk/gtkimagedefinition.c b/gtk/gtkimagedefinition.c index c3b8a456da..f663f12365 100644 --- a/gtk/gtkimagedefinition.c +++ b/gtk/gtkimagedefinition.c @@ -57,7 +57,6 @@ struct _GtkImageDefinitionTexture { gint ref_count; GdkTexture *texture; - int scale; }; struct _GtkImageDefinitionPaintable { @@ -151,8 +150,7 @@ gtk_image_definition_new_surface (cairo_surface_t *surface) } GtkImageDefinition * -gtk_image_definition_new_texture (GdkTexture *texture, - gint scale) +gtk_image_definition_new_texture (GdkTexture *texture) { GtkImageDefinition *def; @@ -161,7 +159,6 @@ gtk_image_definition_new_texture (GdkTexture *texture, def = gtk_image_definition_alloc (GTK_IMAGE_TEXTURE); def->texture.texture = g_object_ref (texture); - def->texture.scale = scale; return def; } @@ -238,11 +235,10 @@ gtk_image_definition_get_scale (const GtkImageDefinition *def) case GTK_IMAGE_EMPTY: case GTK_IMAGE_SURFACE: case GTK_IMAGE_PAINTABLE: + case GTK_IMAGE_TEXTURE: case GTK_IMAGE_ICON_NAME: case GTK_IMAGE_GICON: return 1; - case GTK_IMAGE_TEXTURE: - return def->texture.scale; } } diff --git a/gtk/gtkimagedefinitionprivate.h b/gtk/gtkimagedefinitionprivate.h index 66ccae8be5..8cdb26c9e6 100644 --- a/gtk/gtkimagedefinitionprivate.h +++ b/gtk/gtkimagedefinitionprivate.h @@ -29,8 +29,7 @@ GtkImageDefinition * gtk_image_definition_new_empty (void); GtkImageDefinition * gtk_image_definition_new_icon_name (const char *icon_name); GtkImageDefinition * gtk_image_definition_new_gicon (GIcon *gicon); GtkImageDefinition * gtk_image_definition_new_surface (cairo_surface_t *surface); -GtkImageDefinition * gtk_image_definition_new_texture (GdkTexture *texture, - int scale); +GtkImageDefinition * gtk_image_definition_new_texture (GdkTexture *texture); GtkImageDefinition * gtk_image_definition_new_paintable (GdkPaintable *paintable); GtkImageDefinition * gtk_image_definition_ref (GtkImageDefinition *def); diff --git a/gtk/gtkscaler.c b/gtk/gtkscaler.c new file mode 100644 index 0000000000..2d9caa718f --- /dev/null +++ b/gtk/gtkscaler.c @@ -0,0 +1,173 @@ +/* + * Copyright © 2018 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: Benjamin Otte + */ + +#include "config.h" + +#include "gtkscalerprivate.h" + +#include "gtksnapshot.h" + +struct _GtkScaler +{ + GObject parent_instance; + + GdkPaintable *paintable; + double scale_factor; +}; + +struct _GtkScalerClass +{ + GObjectClass parent_class; +}; + +static void +gtk_scaler_paintable_snapshot (GdkPaintable *paintable, + GdkSnapshot *snapshot, + double width, + double height) +{ + GtkScaler *self = GTK_SCALER (paintable); + + if (self->scale_factor == 1.0) + { + gdk_paintable_snapshot (self->paintable, snapshot, width, height); + } + else + { + graphene_matrix_t scale_matrix; + + graphene_matrix_init_scale (&scale_matrix, 1.0 / self->scale_factor, 1.0 / self->scale_factor, 1.0); + gtk_snapshot_push_transform (snapshot, + &scale_matrix, + "GtkScaler<%g>", + self->scale_factor); + gdk_paintable_snapshot (self->paintable, + snapshot, + width * self->scale_factor, + height * self->scale_factor); + gtk_snapshot_pop (snapshot); + } +} + +static GdkPaintable * +gtk_scaler_paintable_get_current_image (GdkPaintable *paintable) +{ + GtkScaler *self = GTK_SCALER (paintable); + GdkPaintable *current_paintable, *current_self; + + current_paintable = gdk_paintable_get_current_image (self->paintable); + current_self = gtk_scaler_new (current_paintable, self->scale_factor); + g_object_unref (current_paintable); + + return current_self; +} + +static GdkPaintableFlags +gtk_scaler_paintable_get_flags (GdkPaintable *paintable) +{ + GtkScaler *self = GTK_SCALER (paintable); + + return gdk_paintable_get_flags (self->paintable); +} + +static int +gtk_scaler_paintable_get_intrinsic_width (GdkPaintable *paintable) +{ + GtkScaler *self = GTK_SCALER (paintable); + + return gdk_paintable_get_intrinsic_width (self->paintable) / self->scale_factor; +} + +static int +gtk_scaler_paintable_get_intrinsic_height (GdkPaintable *paintable) +{ + GtkScaler *self = GTK_SCALER (paintable); + + return gdk_paintable_get_intrinsic_height (self->paintable) / self->scale_factor; +} + +static double gtk_scaler_paintable_get_intrinsic_aspect_ratio (GdkPaintable *paintable) +{ + GtkScaler *self = GTK_SCALER (paintable); + + return gdk_paintable_get_intrinsic_aspect_ratio (self->paintable); +}; + +static void +gtk_scaler_paintable_init (GdkPaintableInterface *iface) +{ + iface->snapshot = gtk_scaler_paintable_snapshot; + iface->get_current_image = gtk_scaler_paintable_get_current_image; + iface->get_flags = gtk_scaler_paintable_get_flags; + iface->get_intrinsic_width = gtk_scaler_paintable_get_intrinsic_width; + iface->get_intrinsic_height = gtk_scaler_paintable_get_intrinsic_height; + iface->get_intrinsic_aspect_ratio = gtk_scaler_paintable_get_intrinsic_aspect_ratio; +} + +G_DEFINE_TYPE_EXTENDED (GtkScaler, gtk_scaler, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE, + gtk_scaler_paintable_init)) + +static void +gtk_scaler_dispose (GObject *object) +{ + GtkScaler *self = GTK_SCALER (object); + + if (self->paintable) + { + g_signal_handlers_disconnect_by_func (self->paintable, gdk_paintable_invalidate_contents, self); + g_signal_handlers_disconnect_by_func (self->paintable, gdk_paintable_invalidate_size, self); + g_clear_object (&self->paintable); + } + + G_OBJECT_CLASS (gtk_scaler_parent_class)->dispose (object); +} + +static void +gtk_scaler_class_init (GtkScalerClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->dispose = gtk_scaler_dispose; +} + +static void +gtk_scaler_init (GtkScaler *self) +{ + self->scale_factor = 1.0; +} + +GdkPaintable * +gtk_scaler_new (GdkPaintable *paintable, + double scale_factor) +{ + GtkScaler *self; + + g_return_val_if_fail (GDK_IS_PAINTABLE (paintable), NULL); + g_return_val_if_fail (scale_factor > 0.0, NULL); + + self = g_object_new (GTK_TYPE_SCALER, NULL); + + self->paintable = g_object_ref (paintable); + g_signal_connect_swapped (paintable, "invalidate-contents", G_CALLBACK (gdk_paintable_invalidate_contents), self); + g_signal_connect_swapped (paintable, "invalidate-size", G_CALLBACK (gdk_paintable_invalidate_size), self); + self->scale_factor = scale_factor; + + return GDK_PAINTABLE (self); +} diff --git a/gtk/gtkscalerprivate.h b/gtk/gtkscalerprivate.h new file mode 100644 index 0000000000..b48bc10cd9 --- /dev/null +++ b/gtk/gtkscalerprivate.h @@ -0,0 +1,36 @@ +/* + * Copyright © 2018 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: Benjamin Otte + */ + +#ifndef __GTK_SCALER_H__ +#define __GTK_SCALER_H__ + +#include + +G_BEGIN_DECLS + +#define GTK_TYPE_SCALER (gtk_scaler_get_type ()) + +G_DECLARE_FINAL_TYPE (GtkScaler, gtk_scaler, GTK, SCALER, GObject) + +GdkPaintable * gtk_scaler_new (GdkPaintable *paintable, + double scale_factor); + +G_END_DECLS + +#endif /* __GTK_SCALER_H__ */ diff --git a/gtk/meson.build b/gtk/meson.build index 63b374c848..619b709b1b 100644 --- a/gtk/meson.build +++ b/gtk/meson.build @@ -123,6 +123,7 @@ gtk_private_sources = files([ 'gtkprivate.c', 'gtkprogresstracker.c', 'gtkquery.c', + 'gtkscaler.c', 'gtksearchengine.c', 'gtksearchenginemodel.c', 'gtksearchenginesimple.c',