summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk/gtkcellrendererpixbuf.c3
-rw-r--r--gtk/gtkentry.c1
-rw-r--r--gtk/gtkiconhelper.c85
-rw-r--r--gtk/gtkiconhelperprivate.h3
-rw-r--r--gtk/gtkimage.c137
-rw-r--r--gtk/gtkimage.h12
-rw-r--r--gtk/gtkimagedefinition.c40
-rw-r--r--gtk/gtkimagedefinitionprivate.h2
8 files changed, 270 insertions, 13 deletions
diff --git a/gtk/gtkcellrendererpixbuf.c b/gtk/gtkcellrendererpixbuf.c
index 3d0efa9054..cd042c9a70 100644
--- a/gtk/gtkcellrendererpixbuf.c
+++ b/gtk/gtkcellrendererpixbuf.c
@@ -297,6 +297,9 @@ notify_storage_type (GtkCellRendererPixbuf *cellpixbuf,
case GTK_IMAGE_TEXTURE:
g_object_notify (G_OBJECT (cellpixbuf), "texture");
break;
+ case GTK_IMAGE_PAINTABLE:
+ g_object_notify (G_OBJECT (cellpixbuf), "paintable");
+ break;
case GTK_IMAGE_ICON_NAME:
g_object_notify (G_OBJECT (cellpixbuf), "icon-name");
break;
diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c
index d038aeaf6e..1275820484 100644
--- a/gtk/gtkentry.c
+++ b/gtk/gtkentry.c
@@ -6556,6 +6556,7 @@ gtk_entry_clear_icon (GtkEntry *entry,
break;
case GTK_IMAGE_SURFACE:
+ case GTK_IMAGE_PAINTABLE:
case GTK_IMAGE_EMPTY:
default:
g_assert_not_reached ();
diff --git a/gtk/gtkiconhelper.c b/gtk/gtkiconhelper.c
index ddc58e803b..3f9eee4454 100644
--- a/gtk/gtkiconhelper.c
+++ b/gtk/gtkiconhelper.c
@@ -269,6 +269,16 @@ ensure_paintable_from_texture (GtkIconHelper *self,
}
static GdkPaintable *
+ensure_paintable_from_paintable (GtkIconHelper *self,
+ GdkPaintable *paintable,
+ int *scale)
+{
+ *scale = 1;
+
+ return g_object_ref (paintable);
+}
+
+static GdkPaintable *
ensure_paintable_for_gicon (GtkIconHelper *self,
GtkCssStyle *style,
GtkTextDirection dir,
@@ -326,6 +336,11 @@ gtk_icon_helper_load_paintable (GtkIconHelper *self,
symbolic = FALSE;
break;
+ case GTK_IMAGE_PAINTABLE:
+ paintable = ensure_paintable_from_paintable (self, gtk_image_definition_get_paintable (self->def), &scale);
+ symbolic = FALSE;
+ break;
+
case GTK_IMAGE_ICON_NAME:
scale = gtk_widget_get_scale_factor (self->owner);
if (self->use_fallback)
@@ -379,6 +394,43 @@ gtk_icon_helper_ensure_paintable (GtkIconHelper *self)
self->texture_is_symbolic = symbolic;
}
+static void
+get_size_for_paintable (GtkIconHelper *self,
+ GdkPaintable *paintable,
+ int *width_out,
+ int *height_out)
+{
+ int width = gdk_paintable_get_intrinsic_width (paintable);
+ int height = gdk_paintable_get_intrinsic_height (paintable);
+
+ if (width == 0)
+ {
+ if (height != 0)
+ {
+ double ar = gdk_paintable_get_intrinsic_aspect_ratio (paintable);
+
+ if (ar > 0)
+ width = ceil (height * ar);
+ }
+ }
+ else
+ {
+ if (height == 0)
+ {
+ double ar = gdk_paintable_get_intrinsic_aspect_ratio (paintable);
+
+ if (ar > 0)
+ height = ceil (width / ar);
+ }
+ }
+
+ if (width == 0 || height == 0)
+ ensure_icon_size (self, &width, &height);
+
+ *width_out = width;
+ *height_out = height;
+}
+
void
_gtk_icon_helper_get_size (GtkIconHelper *self,
gint *width_out,
@@ -413,6 +465,14 @@ _gtk_icon_helper_get_size (GtkIconHelper *self,
}
break;
+ case GTK_IMAGE_PAINTABLE:
+ {
+ GdkPaintable *paintable = gtk_image_definition_get_paintable (self->def);
+
+ get_size_for_paintable (self, paintable, &width, &height);
+ }
+ break;
+
case GTK_IMAGE_EMPTY:
default:
break;
@@ -425,17 +485,7 @@ _gtk_icon_helper_get_size (GtkIconHelper *self,
if (self->paintable != NULL)
{
- width = gdk_paintable_get_intrinsic_width (self->paintable);
- height = gdk_paintable_get_intrinsic_height (self->paintable);
- if (width == 0 || height == 0)
- {
- ensure_icon_size (self, &width, &height);
- }
- else
- {
- width = (width + self->texture_scale - 1) / self->texture_scale;
- height = (height + self->texture_scale - 1) / self->texture_scale;
- }
+ get_size_for_paintable (self, self->paintable, &width, &height);
}
else
{
@@ -487,6 +537,13 @@ _gtk_icon_helper_set_texture (GtkIconHelper *self,
gtk_icon_helper_take_definition (self, gtk_image_definition_new_texture (texture));
}
+void
+_gtk_icon_helper_set_paintable (GtkIconHelper *self,
+ GdkPaintable *paintable)
+{
+ gtk_icon_helper_take_definition (self, gtk_image_definition_new_paintable (paintable));
+}
+
gboolean
_gtk_icon_helper_set_pixel_size (GtkIconHelper *self,
gint pixel_size)
@@ -555,6 +612,12 @@ _gtk_icon_helper_peek_texture (GtkIconHelper *self)
return gtk_image_definition_get_texture (self->def);
}
+GdkPaintable *
+_gtk_icon_helper_peek_paintable (GtkIconHelper *self)
+{
+ return gtk_image_definition_get_paintable (self->def);
+}
+
const gchar *
_gtk_icon_helper_get_icon_name (GtkIconHelper *self)
{
diff --git a/gtk/gtkiconhelperprivate.h b/gtk/gtkiconhelperprivate.h
index 6c39294cae..6fd794b70b 100644
--- a/gtk/gtkiconhelperprivate.h
+++ b/gtk/gtkiconhelperprivate.h
@@ -69,6 +69,8 @@ void _gtk_icon_helper_set_surface (GtkIconHelper *self,
cairo_surface_t *surface);
void _gtk_icon_helper_set_texture (GtkIconHelper *self,
GdkTexture *texture);
+void _gtk_icon_helper_set_paintable (GtkIconHelper *self,
+ GdkPaintable *paintable);
gboolean _gtk_icon_helper_set_pixel_size (GtkIconHelper *self,
gint pixel_size);
@@ -82,6 +84,7 @@ gboolean _gtk_icon_helper_get_use_fallback (GtkIconHelper *self);
GIcon *_gtk_icon_helper_peek_gicon (GtkIconHelper *self);
cairo_surface_t *_gtk_icon_helper_peek_surface (GtkIconHelper *self);
GdkTexture *_gtk_icon_helper_peek_texture (GtkIconHelper *self);
+GdkPaintable *_gtk_icon_helper_peek_paintable (GtkIconHelper *self);
GtkImageDefinition *gtk_icon_helper_get_definition (GtkIconHelper *self);
const gchar *_gtk_icon_helper_get_icon_name (GtkIconHelper *self);
diff --git a/gtk/gtkimage.c b/gtk/gtkimage.c
index 31ae0a4d38..7deb8b70d3 100644
--- a/gtk/gtkimage.c
+++ b/gtk/gtkimage.c
@@ -119,6 +119,7 @@ enum
{
PROP_0,
PROP_SURFACE,
+ PROP_PAINTABLE,
PROP_TEXTURE,
PROP_FILE,
PROP_ICON_SIZE,
@@ -161,6 +162,13 @@ gtk_image_class_init (GtkImageClass *class)
CAIRO_GOBJECT_TYPE_SURFACE,
GTK_PARAM_READWRITE);
+ image_props[PROP_PAINTABLE] =
+ g_param_spec_object ("paintable",
+ P_("Paintable"),
+ P_("A GdkPaintable to display"),
+ GDK_TYPE_PAINTABLE,
+ GTK_PARAM_READWRITE);
+
image_props[PROP_TEXTURE] =
g_param_spec_object ("texture",
P_("Texture"),
@@ -284,6 +292,8 @@ gtk_image_finalize (GObject *object)
GtkImage *image = GTK_IMAGE (object);
GtkImagePrivate *priv = gtk_image_get_instance_private (image);
+ gtk_image_clear (image);
+
gtk_icon_helper_destroy (&priv->icon_helper);
g_free (priv->filename);
@@ -306,6 +316,9 @@ gtk_image_set_property (GObject *object,
case PROP_SURFACE:
gtk_image_set_from_surface (image, g_value_get_boxed (value));
break;
+ case PROP_PAINTABLE:
+ gtk_image_set_from_paintable (image, g_value_get_object (value));
+ break;
case PROP_TEXTURE:
gtk_image_set_from_texture (image, g_value_get_object (value));
break;
@@ -353,6 +366,9 @@ gtk_image_get_property (GObject *object,
case PROP_SURFACE:
g_value_set_boxed (value, _gtk_icon_helper_peek_surface (&priv->icon_helper));
break;
+ case PROP_PAINTABLE:
+ g_value_set_object (value, _gtk_icon_helper_peek_paintable (&priv->icon_helper));
+ break;
case PROP_TEXTURE:
g_value_set_object (value, _gtk_icon_helper_peek_texture (&priv->icon_helper));
break;
@@ -480,6 +496,32 @@ gtk_image_new_from_pixbuf (GdkPixbuf *pixbuf)
}
/**
+ * gtk_image_new_from_paintable:
+ * @paintable: (allow-none): a #GdkPaintable, or %NULL
+ *
+ * Creates a new #GtkImage displaying @paintable.
+ * The #GtkImage does not assume a reference to the
+ * paintable; you still need to unref it if you own references.
+ * #GtkImage will add its own reference rather than adopting yours.
+ *
+ * The #GtkImage will track changes to the @paintable and update
+ * its size and contents in response to it.
+ *
+ * Returns: a new #GtkImage
+ **/
+GtkWidget*
+gtk_image_new_from_paintable (GdkPaintable *paintable)
+{
+ GtkImage *image;
+
+ image = g_object_new (GTK_TYPE_IMAGE, NULL);
+
+ gtk_image_set_from_paintable (image, paintable);
+
+ return GTK_WIDGET (image);
+}
+
+/**
* gtk_image_new_from_texture:
* @texture: (allow-none): a #GdkTexture, or %NULL
*
@@ -945,6 +987,64 @@ gtk_image_set_from_surface (GtkImage *image,
g_object_thaw_notify (G_OBJECT (image));
}
+static void
+gtk_image_paintable_invalidate_contents (GdkPaintable *paintable,
+ GtkImage *image)
+{
+ gtk_widget_queue_draw (GTK_WIDGET (image));
+}
+
+static void
+gtk_image_paintable_invalidate_size (GdkPaintable *paintable,
+ GtkImage *image)
+{
+ GtkImagePrivate *priv = gtk_image_get_instance_private (image);
+
+ gtk_icon_helper_invalidate (&priv->icon_helper);
+}
+
+/**
+ * gtk_image_set_from_paintable:
+ * @image: a #GtkImage
+ * @paintable: (nullable): a #GdkPaintable or %NULL
+ *
+ * See gtk_image_new_from_paintable() for details.
+ **/
+void
+gtk_image_set_from_paintable (GtkImage *image,
+ GdkPaintable *paintable)
+{
+ GtkImagePrivate *priv = gtk_image_get_instance_private (image);
+
+ g_return_if_fail (GTK_IS_IMAGE (image));
+ g_return_if_fail (paintable == NULL || GDK_IS_PAINTABLE (paintable));
+
+ g_object_freeze_notify (G_OBJECT (image));
+
+ if (paintable)
+ g_object_ref (paintable);
+
+ gtk_image_clear (image);
+
+ if (paintable)
+ {
+ _gtk_icon_helper_set_paintable (&priv->icon_helper, paintable);
+ g_signal_connect (paintable,
+ "invalidate-contents",
+ G_CALLBACK (gtk_image_paintable_invalidate_contents),
+ image);
+ g_signal_connect (paintable,
+ "invalidate-size",
+ G_CALLBACK (gtk_image_paintable_invalidate_size),
+ image);
+ g_object_unref (paintable);
+ }
+
+ g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_PAINTABLE]);
+
+ g_object_thaw_notify (G_OBJECT (image));
+}
+
/**
* gtk_image_set_from_texture:
* @image: a #GtkImage
@@ -1023,6 +1123,29 @@ gtk_image_get_surface (GtkImage *image)
}
/**
+ * gtk_image_get_paintable:
+ * @image: a #GtkImage
+ *
+ * Gets the image #GdkPaintable being displayed by the #GtkImage.
+ * The storage type of the image must be %GTK_IMAGE_EMPTY or
+ * %GTK_IMAGE_PAINTABLE (see gtk_image_get_storage_type()).
+ * The caller of this function does not own a reference to the
+ * returned paintable.
+ *
+ * Returns: (nullable) (transfer none): the displayed paintable, or %NULL if
+ * the image is empty
+ **/
+GdkPaintable *
+gtk_image_get_paintable (GtkImage *image)
+{
+ GtkImagePrivate *priv = gtk_image_get_instance_private (image);
+
+ g_return_val_if_fail (GTK_IS_IMAGE (image), NULL);
+
+ return _gtk_icon_helper_peek_paintable (&priv->icon_helper);
+}
+
+/**
* gtk_image_get_texture:
* @image: a #GtkImage
*
@@ -1205,6 +1328,9 @@ gtk_image_notify_for_storage_type (GtkImage *image,
case GTK_IMAGE_TEXTURE:
g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_TEXTURE]);
break;
+ case GTK_IMAGE_PAINTABLE:
+ g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_PAINTABLE]);
+ break;
case GTK_IMAGE_EMPTY:
default:
break;
@@ -1277,6 +1403,17 @@ gtk_image_clear (GtkImage *image)
g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_RESOURCE]);
}
+ if (storage_type == GTK_IMAGE_PAINTABLE)
+ {
+ GdkPaintable *paintable = _gtk_icon_helper_peek_paintable (&priv->icon_helper);
+ g_signal_handlers_disconnect_by_func (paintable,
+ gtk_image_paintable_invalidate_contents,
+ image);
+ g_signal_handlers_disconnect_by_func (paintable,
+ gtk_image_paintable_invalidate_size,
+ image);
+ }
+
_gtk_icon_helper_clear (&priv->icon_helper);
g_object_thaw_notify (G_OBJECT (image));
diff --git a/gtk/gtkimage.h b/gtk/gtkimage.h
index 45ac3f8fd2..10ce7da730 100644
--- a/gtk/gtkimage.h
+++ b/gtk/gtkimage.h
@@ -59,6 +59,8 @@ typedef struct _GtkImageClass GtkImageClass;
* This image type was added in GTK+ 3.10
* @GTK_IMAGE_TEXTURE: the widget contains a #GdkTexture.
* This image type was added in GTK+ 3.94
+ * @GTK_IMAGE_PAINTABLE: the widget contains a #GdkPaintable.
+ * This image type was added in GTK+ 3.96
*
* Describes the image data representation used by a #GtkImage. If you
* want to get the image from the widget, you can only get the
@@ -74,7 +76,8 @@ typedef enum
GTK_IMAGE_ICON_NAME,
GTK_IMAGE_GICON,
GTK_IMAGE_SURFACE,
- GTK_IMAGE_TEXTURE
+ GTK_IMAGE_TEXTURE,
+ GTK_IMAGE_PAINTABLE
} GtkImageType;
/**
@@ -113,6 +116,8 @@ GtkWidget* gtk_image_new_from_pixbuf (GdkPixbuf *pixbuf);
GDK_AVAILABLE_IN_ALL
GtkWidget* gtk_image_new_from_texture (GdkTexture *texture);
GDK_AVAILABLE_IN_ALL
+GtkWidget* gtk_image_new_from_paintable (GdkPaintable *paintable);
+GDK_AVAILABLE_IN_ALL
GtkWidget* gtk_image_new_from_icon_name (const gchar *icon_name);
GDK_AVAILABLE_IN_ALL
GtkWidget* gtk_image_new_from_gicon (GIcon *icon);
@@ -134,6 +139,9 @@ GDK_AVAILABLE_IN_ALL
void gtk_image_set_from_texture (GtkImage *image,
GdkTexture *texture);
GDK_AVAILABLE_IN_ALL
+void gtk_image_set_from_paintable (GtkImage *image,
+ GdkPaintable *paintable);
+GDK_AVAILABLE_IN_ALL
void gtk_image_set_from_icon_name (GtkImage *image,
const gchar *icon_name);
GDK_AVAILABLE_IN_ALL
@@ -156,6 +164,8 @@ GDK_AVAILABLE_IN_ALL
cairo_surface_t *gtk_image_get_surface (GtkImage *image);
GDK_AVAILABLE_IN_ALL
GdkTexture *gtk_image_get_texture (GtkImage *image);
+GDK_AVAILABLE_IN_ALL
+GdkPaintable *gtk_image_get_paintable (GtkImage *image);
GDK_AVAILABLE_IN_ALL
const char *gtk_image_get_icon_name (GtkImage *image);
diff --git a/gtk/gtkimagedefinition.c b/gtk/gtkimagedefinition.c
index 6c45ca4305..561b2b296e 100644
--- a/gtk/gtkimagedefinition.c
+++ b/gtk/gtkimagedefinition.c
@@ -24,6 +24,7 @@ typedef struct _GtkImageDefinitionIconName GtkImageDefinitionIconName;
typedef struct _GtkImageDefinitionGIcon GtkImageDefinitionGIcon;
typedef struct _GtkImageDefinitionSurface GtkImageDefinitionSurface;
typedef struct _GtkImageDefinitionTexture GtkImageDefinitionTexture;
+typedef struct _GtkImageDefinitionPaintable GtkImageDefinitionPaintable;
struct _GtkImageDefinitionEmpty {
GtkImageType type;
@@ -58,6 +59,13 @@ struct _GtkImageDefinitionTexture {
GdkTexture *texture;
};
+struct _GtkImageDefinitionPaintable {
+ GtkImageType type;
+ gint ref_count;
+
+ GdkPaintable *paintable;
+};
+
union _GtkImageDefinition
{
GtkImageType type;
@@ -66,6 +74,7 @@ union _GtkImageDefinition
GtkImageDefinitionGIcon gicon;
GtkImageDefinitionSurface surface;
GtkImageDefinitionTexture texture;
+ GtkImageDefinitionPaintable paintable;
};
GtkImageDefinition *
@@ -84,7 +93,8 @@ gtk_image_definition_alloc (GtkImageType type)
sizeof (GtkImageDefinitionIconName),
sizeof (GtkImageDefinitionGIcon),
sizeof (GtkImageDefinitionSurface),
- sizeof (GtkImageDefinitionTexture)
+ sizeof (GtkImageDefinitionTexture),
+ sizeof (GtkImageDefinitionPaintable)
};
GtkImageDefinition *def;
@@ -154,6 +164,20 @@ gtk_image_definition_new_texture (GdkTexture *texture)
}
GtkImageDefinition *
+gtk_image_definition_new_paintable (GdkPaintable *paintable)
+{
+ GtkImageDefinition *def;
+
+ if (paintable == NULL)
+ return NULL;
+
+ def = gtk_image_definition_alloc (GTK_IMAGE_PAINTABLE);
+ def->paintable.paintable = g_object_ref (paintable);
+
+ return def;
+}
+
+GtkImageDefinition *
gtk_image_definition_ref (GtkImageDefinition *def)
{
def->empty.ref_count++;
@@ -181,6 +205,9 @@ gtk_image_definition_unref (GtkImageDefinition *def)
case GTK_IMAGE_TEXTURE:
g_object_unref (def->texture.texture);
break;
+ case GTK_IMAGE_PAINTABLE:
+ g_object_unref (def->paintable.paintable);
+ break;
case GTK_IMAGE_ICON_NAME:
g_free (def->icon_name.icon_name);
break;
@@ -208,6 +235,7 @@ gtk_image_definition_get_scale (const GtkImageDefinition *def)
case GTK_IMAGE_EMPTY:
case GTK_IMAGE_SURFACE:
case GTK_IMAGE_TEXTURE:
+ case GTK_IMAGE_PAINTABLE:
case GTK_IMAGE_ICON_NAME:
case GTK_IMAGE_GICON:
return 1;
@@ -249,3 +277,13 @@ gtk_image_definition_get_texture (const GtkImageDefinition *def)
return def->texture.texture;
}
+
+GdkPaintable *
+gtk_image_definition_get_paintable (const GtkImageDefinition *def)
+{
+ if (def->type != GTK_IMAGE_PAINTABLE)
+ return NULL;
+
+ return def->paintable.paintable;
+}
+
diff --git a/gtk/gtkimagedefinitionprivate.h b/gtk/gtkimagedefinitionprivate.h
index 2dac974ee8..8cdb26c9e6 100644
--- a/gtk/gtkimagedefinitionprivate.h
+++ b/gtk/gtkimagedefinitionprivate.h
@@ -30,6 +30,7 @@ GtkImageDefinition * gtk_image_definition_new_icon_name (const char
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);
+GtkImageDefinition * gtk_image_definition_new_paintable (GdkPaintable *paintable);
GtkImageDefinition * gtk_image_definition_ref (GtkImageDefinition *def);
void gtk_image_definition_unref (GtkImageDefinition *def);
@@ -40,6 +41,7 @@ const gchar * gtk_image_definition_get_icon_name (const GtkImageD
GIcon * gtk_image_definition_get_gicon (const GtkImageDefinition *def);
cairo_surface_t * gtk_image_definition_get_surface (const GtkImageDefinition *def);
GdkTexture * gtk_image_definition_get_texture (const GtkImageDefinition *def);
+GdkPaintable * gtk_image_definition_get_paintable (const GtkImageDefinition *def);
G_END_DECLS