iconhelper: Implement GdkPaintable

This only implements the vfuncs, but does not actually emit signals
yet.

It's also not useed for anything other than snapshot() so far, this
will come in later commits.
This commit is contained in:
Benjamin Otte 2018-03-15 09:40:52 +01:00
parent af18796312
commit 0a08c03885
4 changed files with 248 additions and 139 deletions

View File

@ -551,7 +551,7 @@ gtk_cell_renderer_pixbuf_snapshot (GtkCellRenderer *cell,
}
gtk_snapshot_offset (snapshot, pix_rect.x, pix_rect.y);
gtk_icon_helper_snapshot (icon_helper, snapshot, pix_rect.width, pix_rect.height);
gdk_paintable_snapshot (GDK_PAINTABLE (icon_helper), snapshot, pix_rect.width, pix_rect.height);
gtk_snapshot_offset (snapshot, - pix_rect.x, - pix_rect.y);
g_object_unref (icon_helper);

View File

@ -53,116 +53,6 @@ struct _GtkIconHelper
int texture_scale;
};
G_DEFINE_TYPE (GtkIconHelper, gtk_icon_helper, G_TYPE_OBJECT)
void
gtk_icon_helper_invalidate (GtkIconHelper *self)
{
g_clear_object (&self->paintable);
self->texture_scale = 1;
self->texture_is_symbolic = FALSE;
if (!GTK_IS_CSS_TRANSIENT_NODE (self->node))
gtk_widget_queue_resize (self->owner);
}
void
gtk_icon_helper_invalidate_for_change (GtkIconHelper *self,
GtkCssStyleChange *change)
{
if (change == NULL ||
((gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_SYMBOLIC_ICON) &&
self->texture_is_symbolic) ||
(gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_ICON) &&
!self->texture_is_symbolic)))
{
/* Avoid the queue_resize in gtk_icon_helper_invalidate */
g_clear_object (&self->paintable);
self->texture_scale = 1;
self->texture_is_symbolic = FALSE;
if (change == NULL ||
(gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_ICON_SIZE) &&
!GTK_IS_CSS_TRANSIENT_NODE (self->node)))
gtk_widget_queue_resize (self->owner);
}
}
static void
gtk_icon_helper_take_definition (GtkIconHelper *self,
GtkImageDefinition *def)
{
_gtk_icon_helper_clear (self);
if (def == NULL)
return;
gtk_image_definition_unref (self->def);
self->def = def;
gtk_icon_helper_invalidate (self);
}
void
_gtk_icon_helper_clear (GtkIconHelper *self)
{
g_clear_object (&self->paintable);
self->texture_scale = 1;
self->texture_is_symbolic = FALSE;
if (gtk_image_definition_get_storage_type (self->def) != GTK_IMAGE_EMPTY)
{
gtk_image_definition_unref (self->def);
self->def = gtk_image_definition_new_empty ();
gtk_icon_helper_invalidate (self);
}
}
static void
gtk_icon_helper_finalize (GObject *object)
{
GtkIconHelper *self = GTK_ICON_HELPER (object);
_gtk_icon_helper_clear (self);
g_signal_handlers_disconnect_by_func (self->owner, G_CALLBACK (gtk_icon_helper_invalidate), self);
gtk_image_definition_unref (self->def);
G_OBJECT_CLASS (gtk_icon_helper_parent_class)->finalize (object);
}
void
gtk_icon_helper_class_init (GtkIconHelperClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = gtk_icon_helper_finalize;
}
void
gtk_icon_helper_init (GtkIconHelper *self)
{
self->def = gtk_image_definition_new_empty ();
}
GtkIconHelper *
gtk_icon_helper_new (GtkCssNode *css_node,
GtkWidget *owner)
{
GtkIconHelper *self;
self = g_object_new (GTK_TYPE_ICON_HELPER, NULL);
self->pixel_size = -1;
self->texture_is_symbolic = FALSE;
self->node = css_node;
self->owner = owner;
g_signal_connect_swapped (owner, "direction-changed", G_CALLBACK (gtk_icon_helper_invalidate), self);
g_signal_connect_swapped (owner, "notify::scale-factor", G_CALLBACK (gtk_icon_helper_invalidate), self);
return self;
}
static int
get_default_size (GtkIconHelper *self)
{
@ -344,6 +234,251 @@ gtk_icon_helper_ensure_paintable (GtkIconHelper *self)
self->texture_is_symbolic = symbolic;
}
static void
gtk_icon_helper_paintable_snapshot (GdkPaintable *paintable,
GdkSnapshot *snapshot,
double width,
double height)
{
GtkIconHelper *self = GTK_ICON_HELPER (paintable);
GtkCssStyle *style;
style = gtk_css_node_get_style (self->node);
gtk_icon_helper_ensure_paintable (self);
if (self->paintable == NULL)
return;
gtk_css_style_snapshot_icon_paintable (style,
snapshot,
self->paintable,
width, height,
self->texture_is_symbolic);
}
static GdkPaintable *
gtk_icon_helper_paintable_get_current_image (GdkPaintable *paintable)
{
GtkIconHelper *self = GTK_ICON_HELPER (paintable);
gtk_icon_helper_ensure_paintable (self);
if (self->paintable == NULL)
return NULL;
return gtk_icon_helper_paintable_get_current_image (self->paintable);
}
static int
gtk_icon_helper_paintable_get_intrinsic_width (GdkPaintable *paintable)
{
GtkIconHelper *self = GTK_ICON_HELPER (paintable);
switch (gtk_image_definition_get_storage_type (self->def))
{
case GTK_IMAGE_TEXTURE:
return gdk_paintable_get_intrinsic_width (GDK_PAINTABLE (gtk_image_definition_get_texture (self->def)));
case GTK_IMAGE_PAINTABLE:
return gdk_paintable_get_intrinsic_width (gtk_image_definition_get_paintable (self->def));
case GTK_IMAGE_ICON_NAME:
case GTK_IMAGE_GICON:
if (self->pixel_size != -1 || self->force_scale_pixbuf)
return get_default_size (self);
gtk_icon_helper_ensure_paintable (self);
if (self->paintable)
return gdk_paintable_get_intrinsic_width (self->paintable);
else
return 0;
case GTK_IMAGE_EMPTY:
return 0;
default:
g_assert_not_reached ();
return 0;
}
}
static int
gtk_icon_helper_paintable_get_intrinsic_height (GdkPaintable *paintable)
{
GtkIconHelper *self = GTK_ICON_HELPER (paintable);
switch (gtk_image_definition_get_storage_type (self->def))
{
case GTK_IMAGE_TEXTURE:
return gdk_paintable_get_intrinsic_height (GDK_PAINTABLE (gtk_image_definition_get_texture (self->def)));
case GTK_IMAGE_PAINTABLE:
return gdk_paintable_get_intrinsic_height (gtk_image_definition_get_paintable (self->def));
case GTK_IMAGE_ICON_NAME:
case GTK_IMAGE_GICON:
if (self->pixel_size != -1 || self->force_scale_pixbuf)
return get_default_size (self);
gtk_icon_helper_ensure_paintable (self);
if (self->paintable)
return gdk_paintable_get_intrinsic_height (self->paintable);
else
return 0;
case GTK_IMAGE_EMPTY:
return 0;
default:
g_assert_not_reached ();
return 0;
}
}
static double gtk_icon_helper_paintable_get_intrinsic_aspect_ratio (GdkPaintable *paintable)
{
GtkIconHelper *self = GTK_ICON_HELPER (paintable);
switch (gtk_image_definition_get_storage_type (self->def))
{
case GTK_IMAGE_TEXTURE:
return gdk_paintable_get_intrinsic_aspect_ratio (GDK_PAINTABLE (gtk_image_definition_get_texture (self->def)));
case GTK_IMAGE_PAINTABLE:
return gdk_paintable_get_intrinsic_aspect_ratio (gtk_image_definition_get_paintable (self->def));
case GTK_IMAGE_ICON_NAME:
case GTK_IMAGE_GICON:
return 1.0;
case GTK_IMAGE_EMPTY:
return 0.0;
default:
g_assert_not_reached ();
return 0.0;
}
};
static void
gtk_icon_helper_paintable_init (GdkPaintableInterface *iface)
{
iface->snapshot = gtk_icon_helper_paintable_snapshot;
iface->get_current_image = gtk_icon_helper_paintable_get_current_image;
iface->get_intrinsic_width = gtk_icon_helper_paintable_get_intrinsic_width;
iface->get_intrinsic_height = gtk_icon_helper_paintable_get_intrinsic_height;
iface->get_intrinsic_aspect_ratio = gtk_icon_helper_paintable_get_intrinsic_aspect_ratio;
}
G_DEFINE_TYPE_WITH_CODE (GtkIconHelper, gtk_icon_helper, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
gtk_icon_helper_paintable_init))
void
gtk_icon_helper_invalidate (GtkIconHelper *self)
{
g_clear_object (&self->paintable);
self->texture_scale = 1;
self->texture_is_symbolic = FALSE;
if (!GTK_IS_CSS_TRANSIENT_NODE (self->node))
gtk_widget_queue_resize (self->owner);
}
void
gtk_icon_helper_invalidate_for_change (GtkIconHelper *self,
GtkCssStyleChange *change)
{
if (change == NULL ||
((gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_SYMBOLIC_ICON) &&
self->texture_is_symbolic) ||
(gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_ICON) &&
!self->texture_is_symbolic)))
{
/* Avoid the queue_resize in gtk_icon_helper_invalidate */
g_clear_object (&self->paintable);
self->texture_scale = 1;
self->texture_is_symbolic = FALSE;
if (change == NULL ||
(gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_ICON_SIZE) &&
!GTK_IS_CSS_TRANSIENT_NODE (self->node)))
gtk_widget_queue_resize (self->owner);
}
}
static void
gtk_icon_helper_take_definition (GtkIconHelper *self,
GtkImageDefinition *def)
{
_gtk_icon_helper_clear (self);
if (def == NULL)
return;
gtk_image_definition_unref (self->def);
self->def = def;
gtk_icon_helper_invalidate (self);
}
void
_gtk_icon_helper_clear (GtkIconHelper *self)
{
g_clear_object (&self->paintable);
self->texture_scale = 1;
self->texture_is_symbolic = FALSE;
if (gtk_image_definition_get_storage_type (self->def) != GTK_IMAGE_EMPTY)
{
gtk_image_definition_unref (self->def);
self->def = gtk_image_definition_new_empty ();
gtk_icon_helper_invalidate (self);
}
}
static void
gtk_icon_helper_finalize (GObject *object)
{
GtkIconHelper *self = GTK_ICON_HELPER (object);
_gtk_icon_helper_clear (self);
g_signal_handlers_disconnect_by_func (self->owner, G_CALLBACK (gtk_icon_helper_invalidate), self);
gtk_image_definition_unref (self->def);
G_OBJECT_CLASS (gtk_icon_helper_parent_class)->finalize (object);
}
void
gtk_icon_helper_class_init (GtkIconHelperClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = gtk_icon_helper_finalize;
}
void
gtk_icon_helper_init (GtkIconHelper *self)
{
self->def = gtk_image_definition_new_empty ();
}
GtkIconHelper *
gtk_icon_helper_new (GtkCssNode *css_node,
GtkWidget *owner)
{
GtkIconHelper *self;
self = g_object_new (GTK_TYPE_ICON_HELPER, NULL);
self->pixel_size = -1;
self->texture_is_symbolic = FALSE;
self->node = css_node;
self->owner = owner;
g_signal_connect_swapped (owner, "direction-changed", G_CALLBACK (gtk_icon_helper_invalidate), self);
g_signal_connect_swapped (owner, "notify::scale-factor", G_CALLBACK (gtk_icon_helper_invalidate), self);
return self;
}
void
gtk_icon_helper_measure (GtkIconHelper *self,
GtkOrientation orientation,
@ -615,27 +750,6 @@ _gtk_icon_helper_get_icon_name (GtkIconHelper *self)
return gtk_image_definition_get_icon_name (self->def);
}
void
gtk_icon_helper_snapshot (GtkIconHelper *self,
GtkSnapshot *snapshot,
double width,
double height)
{
GtkCssStyle *style;
style = gtk_css_node_get_style (self->node);
gtk_icon_helper_ensure_paintable (self);
if (self->paintable == NULL)
return;
gtk_css_style_snapshot_icon_paintable (style,
snapshot,
self->paintable,
width, height,
self->texture_is_symbolic);
}
gboolean
_gtk_icon_helper_get_is_empty (GtkIconHelper *self)
{

View File

@ -76,11 +76,6 @@ void _gtk_icon_helper_get_size (GtkIconHelper *self,
gint *width_out,
gint *height_out);
void gtk_icon_helper_snapshot (GtkIconHelper *self,
GtkSnapshot *snapshot,
double width,
double height);
gboolean _gtk_icon_helper_get_force_scale_pixbuf (GtkIconHelper *self);
void _gtk_icon_helper_set_force_scale_pixbuf (GtkIconHelper *self,
gboolean force_scale);

View File

@ -1211,7 +1211,7 @@ gtk_image_snapshot (GtkWidget *widget,
if (_gtk_icon_helper_get_storage_type (priv->icon_helper) == GTK_IMAGE_PAINTABLE)
{
gtk_icon_helper_snapshot (priv->icon_helper, snapshot, width, height);
gdk_paintable_snapshot (GDK_PAINTABLE (priv->icon_helper), snapshot, width, height);
}
else
{
@ -1226,7 +1226,7 @@ gtk_image_snapshot (GtkWidget *widget,
y = CLAMP (baseline - h * gtk_image_get_baseline_align (image), 0, height - h);
gtk_snapshot_offset (snapshot, x, y);
gtk_icon_helper_snapshot (priv->icon_helper, snapshot, w, h);
gdk_paintable_snapshot (GDK_PAINTABLE (priv->icon_helper), snapshot, w, h);
gtk_snapshot_offset (snapshot, -x, -y);
}
}