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.
This commit is contained in:
Benjamin Otte 2018-03-14 04:45:25 +01:00
parent c9557c207f
commit 7844320f10
9 changed files with 234 additions and 21 deletions

View File

@ -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;

View File

@ -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));

View File

@ -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

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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);

173
gtk/gtkscaler.c Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#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);
}

36
gtk/gtkscalerprivate.h Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#ifndef __GTK_SCALER_H__
#define __GTK_SCALER_H__
#include <gdk/gdk.h>
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__ */

View File

@ -123,6 +123,7 @@ gtk_private_sources = files([
'gtkprivate.c',
'gtkprogresstracker.c',
'gtkquery.c',
'gtkscaler.c',
'gtksearchengine.c',
'gtksearchenginemodel.c',
'gtksearchenginesimple.c',