[gnome-panel] status-notifier: scale icon pixmaps if needed



commit b2618e6e0768c81b3bedd732505b7cb7a3bba365
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Sat Nov 5 19:09:23 2016 +0200

    status-notifier: scale icon pixmaps if needed

 applets/status-notifier/sn-item-v0.c |  155 ++++++++++++++++++++++++++++++++--
 applets/status-notifier/sn-item.c    |   10 ++
 applets/status-notifier/sn-item.h    |    2 +
 3 files changed, 159 insertions(+), 8 deletions(-)
---
diff --git a/applets/status-notifier/sn-item-v0.c b/applets/status-notifier/sn-item-v0.c
index dea74e1..486dedf 100644
--- a/applets/status-notifier/sn-item-v0.c
+++ b/applets/status-notifier/sn-item-v0.c
@@ -17,6 +17,9 @@
 
 #include "config.h"
 
+#include <math.h>
+
+#include "sn-item.h"
 #include "sn-item-v0.h"
 #include "sn-item-v0-gen.h"
 
@@ -69,6 +72,146 @@ struct _SnItemV0
 
 G_DEFINE_TYPE (SnItemV0, sn_item_v0, SN_TYPE_ITEM)
 
+static cairo_surface_t *
+scale_surface (SnIconPixmap   *pixmap,
+               GtkOrientation  orientation,
+               gint            size)
+{
+  gdouble ratio;
+  gdouble new_width;
+  gdouble new_height;
+  gdouble scale_x;
+  gdouble scale_y;
+  gint width;
+  gint height;
+  cairo_content_t content;
+  cairo_surface_t *scaled;
+  cairo_t *cr;
+
+  ratio = pixmap->width / (gdouble) pixmap->height;
+  if (orientation == GTK_ORIENTATION_HORIZONTAL)
+    {
+      new_height = (gdouble) size;
+      new_width = new_height * ratio;
+    }
+  else
+    {
+      new_width = (gdouble) size;
+      new_height = new_width * ratio;
+    }
+
+  scale_x = new_width / pixmap->width;
+  scale_y = new_height / pixmap->height;
+
+  width = ceil (new_width);
+  height = ceil (new_height);
+
+  content = CAIRO_CONTENT_COLOR_ALPHA;
+  scaled = cairo_surface_create_similar (pixmap->surface, content, width, height);
+  cr = cairo_create (scaled);
+
+  cairo_scale (cr, scale_x, scale_y);
+  cairo_set_source_surface (cr, pixmap->surface, 0, 0);
+  cairo_paint (cr);
+
+  cairo_destroy (cr);
+  return scaled;
+}
+
+static gint
+compare_size (gconstpointer a,
+              gconstpointer b,
+              gpointer      user_data)
+{
+  SnIconPixmap *p1;
+  SnIconPixmap *p2;
+  GtkOrientation orientation;
+
+  p1 = (SnIconPixmap *) a;
+  p2 = (SnIconPixmap *) b;
+  orientation = GPOINTER_TO_UINT (user_data);
+
+  if (orientation == GTK_ORIENTATION_HORIZONTAL)
+    return p1->height - p2->height;
+  else
+    return p1->width - p2->width;
+}
+
+static GList *
+get_pixmaps_sorted (SnItemV0       *v0,
+                    GtkOrientation  orientation,
+                    gint            size)
+{
+  GList *pixmaps;
+  guint i;
+
+  pixmaps = NULL;
+  for (i = 0; v0->icon_pixmap[i] != NULL; i++)
+    pixmaps = g_list_prepend (pixmaps, v0->icon_pixmap[i]);
+
+  return g_list_sort_with_data (pixmaps, compare_size,
+                                GUINT_TO_POINTER (orientation));
+}
+
+static cairo_surface_t *
+get_surface (SnItemV0       *v0,
+             GtkOrientation  orientation,
+             gint            size)
+{
+  GList *pixmaps;
+  cairo_surface_t *surface;
+  SnIconPixmap *best;
+  GList *l;
+
+  g_assert (v0->icon_pixmap != NULL && v0->icon_pixmap[0] != NULL);
+
+  pixmaps = get_pixmaps_sorted (v0, orientation, size);
+  surface = NULL;
+
+  for (l = pixmaps; l != NULL; l = l->next)
+    {
+      SnIconPixmap *pixmap;
+
+      pixmap = (SnIconPixmap *) l->data;
+
+      if (orientation == GTK_ORIENTATION_HORIZONTAL)
+        {
+          if (pixmap->height == size)
+            {
+              surface = pixmap->surface;
+              break;
+            }
+          else if (pixmap->height > size)
+            {
+              best = pixmap;
+              break;
+            }
+        }
+      else
+        {
+          if (pixmap->width == size)
+            {
+              surface = pixmap->surface;
+              break;
+            }
+          else if (pixmap->width > size)
+            {
+              best = pixmap;
+              break;
+            }
+        }
+
+      best = pixmap;
+    }
+
+  g_list_free (pixmaps);
+
+  if (surface != NULL)
+    return cairo_surface_reference (surface);
+
+  return scale_surface (best, orientation, size);
+}
+
 static void
 update (SnItemV0 *v0)
 {
@@ -89,15 +232,11 @@ update (SnItemV0 *v0)
     }
   else if (v0->icon_pixmap != NULL && v0->icon_pixmap[0] != NULL)
     {
-      guint i;
-
-      for (i = 0; v0->icon_pixmap[i] != NULL; i++)
-        {
-          g_debug ("v0->icon_pixmap[%d]: width - %d, height - %d", i,
-                   v0->icon_pixmap[i]->width, v0->icon_pixmap[i]->height);
-        }
+      cairo_surface_t *surface;
 
-      gtk_image_set_from_surface (image, v0->icon_pixmap[0]->surface);
+      surface = get_surface (v0, sn_item_get_orientation (SN_ITEM (v0)), 16);
+      gtk_image_set_from_surface (image, surface);
+      cairo_surface_destroy (surface);
     }
   else
     {
diff --git a/applets/status-notifier/sn-item.c b/applets/status-notifier/sn-item.c
index 224315d..e75db8d 100644
--- a/applets/status-notifier/sn-item.c
+++ b/applets/status-notifier/sn-item.c
@@ -401,6 +401,16 @@ sn_item_get_object_path (SnItem *item)
   return priv->object_path;
 }
 
+GtkOrientation
+sn_item_get_orientation (SnItem *item)
+{
+  SnItemPrivate *priv;
+
+  priv = sn_item_get_instance_private (item);
+
+  return priv->orientation;
+}
+
 void
 sn_item_emit_ready (SnItem *item)
 {
diff --git a/applets/status-notifier/sn-item.h b/applets/status-notifier/sn-item.h
index 86e4c58..666e669 100644
--- a/applets/status-notifier/sn-item.h
+++ b/applets/status-notifier/sn-item.h
@@ -75,6 +75,8 @@ SnItemCategory  sn_item_get_category    (SnItem *item);
 const gchar    *sn_item_get_bus_name    (SnItem *item);
 const gchar    *sn_item_get_object_path (SnItem *item);
 
+GtkOrientation  sn_item_get_orientation (SnItem *item);
+
 void            sn_item_emit_ready      (SnItem *item);
 
 G_END_DECLS


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