[libhandy] avatar: Add function to draw avatar to pixbuf



commit 991d026be41fb3cbb65d2109a5f3aaedd7d03b62
Author: Julian Sparber <julian sparber net>
Date:   Tue Oct 27 18:44:52 2020 +0100

    avatar: Add function to draw avatar to pixbuf
    
    Fixes: https://gitlab.gnome.org/GNOME/libhandy/-/issues/346

 debian/libhandy-1-0.symbols |   1 +
 src/hdy-avatar.c            | 109 +++++++++++++++++++++++++++++++-------------
 src/hdy-avatar.h            |   4 ++
 3 files changed, 83 insertions(+), 31 deletions(-)
---
diff --git a/debian/libhandy-1-0.symbols b/debian/libhandy-1-0.symbols
index c5b725da..55042d2a 100644
--- a/debian/libhandy-1-0.symbols
+++ b/debian/libhandy-1-0.symbols
@@ -18,6 +18,7 @@ libhandy-1.so.0 libhandy-1-0 #MINVER#
  hdy_action_row_set_use_underline@LIBHANDY_1_0 0.0.6
  hdy_application_window_get_type@LIBHANDY_1_0 0.80.0
  hdy_application_window_new@LIBHANDY_1_0 0.80.0
+ hdy_avatar_draw_to_pixbuf@LIBHANDY_1_0 1.1.0
  hdy_avatar_get_icon_name@LIBHANDY_1_0 0.85.0
  hdy_avatar_get_show_initials@LIBHANDY_1_0 0.80.0
  hdy_avatar_get_size@LIBHANDY_1_0 0.80.0
diff --git a/src/hdy-avatar.c b/src/hdy-avatar.c
index 733552bd..08a66efb 100644
--- a/src/hdy-avatar.c
+++ b/src/hdy-avatar.c
@@ -144,16 +144,16 @@ extract_initials_from_text (const gchar *text)
 }
 
 static void
-update_custom_image (HdyAvatar *self)
+update_custom_image (HdyAvatar *self,
+                     gint       width,
+                     gint       height,
+                     gint       scale_factor)
 {
   g_autoptr (GdkPixbuf) pixbuf = NULL;
-  gint scale_factor;
   gint new_size;
   GtkStyleContext *context = gtk_widget_get_style_context (GTK_WIDGET (self));
 
-  scale_factor = gtk_widget_get_scale_factor (GTK_WIDGET (self));
-  new_size = MIN (gtk_widget_get_allocated_width (GTK_WIDGET (self)),
-                  gtk_widget_get_allocated_height (GTK_WIDGET (self))) * scale_factor;
+  new_size = MIN (width, height) * scale_factor;
 
   if (self->round_image_size != new_size && self->round_image != NULL) {
     g_clear_pointer (&self->round_image, cairo_surface_destroy);
@@ -344,28 +344,27 @@ hdy_avatar_finalize (GObject *object)
   G_OBJECT_CLASS (hdy_avatar_parent_class)->finalize (object);
 }
 
-static gboolean
-hdy_avatar_draw (GtkWidget *widget,
-                 cairo_t   *cr)
+static void
+draw_for_size (HdyAvatar *self,
+               cairo_t   *cr,
+               gint       width,
+               gint       height,
+               gint       scale_factor)
 {
-  HdyAvatar *self = HDY_AVATAR (widget);
-  GtkStyleContext *context = gtk_widget_get_style_context (widget);
-  gint width = gtk_widget_get_allocated_width (widget);
-  gint height = gtk_widget_get_allocated_height (widget);
+  GtkStyleContext *context = gtk_widget_get_style_context (GTK_WIDGET (self));
   gint size = MIN (width, height);
   gdouble x = (gdouble)(width - size) / 2.0;
   gdouble y = (gdouble)(height - size) / 2.0;
   const gchar *icon_name;
-  gint scale;
   GdkRGBA color;
   g_autoptr (GtkIconInfo) icon = NULL;
   g_autoptr (GdkPixbuf) pixbuf = NULL;
   g_autoptr (GError) error = NULL;
   g_autoptr (cairo_surface_t) surface = NULL;
 
-  set_class_contrasted (HDY_AVATAR (widget), size);
+  set_class_contrasted (self, size);
 
-  update_custom_image (self);
+  update_custom_image (self, width, height, scale_factor);
 
   if (self->round_image) {
     cairo_set_source_surface (cr, self->round_image, x, y);
@@ -373,57 +372,62 @@ hdy_avatar_draw (GtkWidget *widget,
 
     gtk_render_background (context, cr, x, y, size, size);
     gtk_render_frame (context, cr, x, y, size, size);
-
-    return FALSE;
+    return;
   }
 
   gtk_render_background (context, cr, x, y, size, size);
   gtk_render_frame (context, cr, x, y, size, size);
 
-  ensure_pango_layout (HDY_AVATAR (widget));
+  ensure_pango_layout (self);
 
   if (self->show_initials && self->layout != NULL) {
-    set_font_size (HDY_AVATAR (widget), size);
+    set_font_size (self, size);
     pango_layout_get_pixel_size (self->layout, &width, &height);
 
     gtk_render_layout (context, cr,
                        ((gdouble) (size - width) / 2.0) + x,
                        ((gdouble) (size - height) / 2.0) + y,
                        self->layout);
-
-    return FALSE;
+    return;
   }
 
   icon_name = self->icon_name && *self->icon_name != '\0' ?
     self->icon_name : "avatar-default-symbolic";
-  scale = gtk_widget_get_scale_factor (widget);
   icon = gtk_icon_theme_lookup_icon_for_scale (gtk_icon_theme_get_default (),
                                      icon_name,
-                                     size / 2, scale,
+                                     size / 2, scale_factor,
                                      GTK_ICON_LOOKUP_FORCE_SYMBOLIC);
   if (icon == NULL) {
     g_critical ("Failed to load icon `%s'", icon_name);
-
-    return FALSE;
+    return;
   }
 
   gtk_style_context_get_color (context, gtk_style_context_get_state (context), &color);
   pixbuf = gtk_icon_info_load_symbolic (icon, &color, NULL, NULL, NULL, NULL, &error);
   if (error != NULL) {
     g_critical ("Failed to load icon `%s': %s", icon_name, error->message);
-
-    return FALSE;
+    return;
   }
 
-  surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale,
-                                                  gtk_widget_get_window (widget));
+  surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale_factor,
+                                                  gtk_widget_get_window (GTK_WIDGET (self)));
 
   width = cairo_image_surface_get_width (surface);
   height = cairo_image_surface_get_height (surface);
   gtk_render_icon_surface (context, cr, surface,
-                           (((gdouble) size - ((gdouble) width / (gdouble) scale)) / 2.0) + x,
-                           (((gdouble) size - ((gdouble) height / (gdouble) scale)) / 2.0) + y);
+                           (((gdouble) size - ((gdouble) width / (gdouble) scale_factor)) / 2.0) + x,
+                           (((gdouble) size - ((gdouble) height / (gdouble) scale_factor)) / 2.0) + y);
+}
+
+static gboolean
+hdy_avatar_draw (GtkWidget *widget,
+                 cairo_t   *cr)
+{
+  gint width = gtk_widget_get_allocated_width (widget);
+  gint height = gtk_widget_get_allocated_height (widget);
+  gint scale_factor = gtk_widget_get_scale_factor (widget);
 
+  draw_for_size (HDY_AVATAR (widget), cr, width, height, scale_factor);
   return FALSE;
 }
 
@@ -828,3 +832,46 @@ hdy_avatar_set_size (HdyAvatar *self,
   gtk_widget_queue_resize (GTK_WIDGET (self));
   g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SIZE]);
 }
+
+/**
+ * hdy_avatar_draw_to_pixbuf:
+ * @self: a #HdyAvatar
+ * @size: The size of the pixbuf
+ * @scale_factor: The scale factor
+ *
+ * Renders @self into a pixbuf at @size and @scale_factor. This can be used to export the fallback avatar.
+ *
+ * Returns: (transfer full): the pixbuf.
+ *
+ * Since: 1.1
+ */
+GdkPixbuf *
+hdy_avatar_draw_to_pixbuf (HdyAvatar *self,
+                           gint       size,
+                           gint       scale_factor)
+{
+  g_autoptr (cairo_surface_t) surface = NULL;
+  g_autoptr (cairo_t) cr = NULL;
+  GtkStyleContext *context;
+  GtkAllocation bounds;
+
+  g_return_val_if_fail (HDY_IS_AVATAR (self), NULL);
+  g_return_val_if_fail (size > 0, NULL);
+  g_return_val_if_fail (scale_factor > 0, NULL);
+
+  context = gtk_widget_get_style_context (GTK_WIDGET (self));
+  gtk_render_background_get_clip (context, 0, 0, size, size, &bounds);
+
+  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+                                        bounds.width * scale_factor,
+                                        bounds.height * scale_factor);
+  cairo_surface_set_device_scale (surface, scale_factor, scale_factor);
+  cr = cairo_create (surface);
+
+  cairo_translate (cr, -bounds.x, -bounds.y);
+  draw_for_size (self, cr, size, size, scale_factor);
+
+  return gdk_pixbuf_get_from_surface (surface, 0, 0,
+                                      bounds.width * scale_factor,
+                                      bounds.height * scale_factor);
+}
diff --git a/src/hdy-avatar.h b/src/hdy-avatar.h
index 54f37877..e820f9a8 100644
--- a/src/hdy-avatar.h
+++ b/src/hdy-avatar.h
@@ -66,5 +66,9 @@ gint         hdy_avatar_get_size            (HdyAvatar              *self);
 HDY_AVAILABLE_IN_ALL
 void         hdy_avatar_set_size            (HdyAvatar              *self,
                                              gint                    size);
+HDY_AVAILABLE_IN_ALL
+GdkPixbuf   *hdy_avatar_draw_to_pixbuf      (HdyAvatar              *self,
+                                             gint                    size,
+                                             gint                    scale_factor);
 
 G_END_DECLS


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]