gnome-panel r11029 - trunk/applets/clock



Author: vuntz
Date: Thu Apr 10 05:37:14 2008
New Revision: 11029
URL: http://svn.gnome.org/viewvc/gnome-panel?rev=11029&view=rev

Log:
2008-04-10  Vincent Untz  <vuntz gnome org>

	Implement a cache for clock face pixbufs. They're loaded from SVG, so
	it can be a bit slow to read the file. With the cache, we win around
	0.01s and 0.02s per face clock that can use it.
	It's totally useless if you have only one location or all the locations
	are in completely different timezones (always using different SVG
	files), but it doesn't cost us anything, so it's a good thing in the
	end.

	* clock-face.c: (clock_face_finalize): don't use deprecated
	gdk_pixbuf_unref(), free the cache if it's empty
	(remove_pixbuf_from_cache): helper, to remove a unused pixbuf from the
	cache when it's reference count reaches 0
	(clock_face_load_face): initialize the cache (implemented with a
	hashtable) if needed, and try to use it. If the searched pixbuf isn't
	there, load it as we did before and add it to the cache.


Modified:
   trunk/applets/clock/ChangeLog
   trunk/applets/clock/clock-face.c

Modified: trunk/applets/clock/clock-face.c
==============================================================================
--- trunk/applets/clock/clock-face.c	(original)
+++ trunk/applets/clock/clock-face.c	Thu Apr 10 05:37:14 2008
@@ -20,6 +20,8 @@
 #include "clock-face.h"
 #include "clock-location.h"
 
+static GHashTable *pixbuf_cache = NULL;
+
 #define CLOCK_FACE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), INTL_TYPE_CLOCK_FACE, ClockFacePrivate))
 
 G_DEFINE_TYPE (ClockFace, clock_face, GTK_TYPE_WIDGET);
@@ -408,7 +410,7 @@
         }
 
         if (priv->face_pixbuf) {
-                gdk_pixbuf_unref (priv->face_pixbuf);
+                g_object_unref (priv->face_pixbuf);
                 priv->face_pixbuf = NULL;
         }
 
@@ -418,6 +420,11 @@
         }
 
         G_OBJECT_CLASS (clock_face_parent_class)->finalize (obj);
+
+        if (g_hash_table_size (pixbuf_cache) == 0) {
+                g_hash_table_destroy (pixbuf_cache);
+                pixbuf_cache = NULL;
+        }
 }
 
 static void
@@ -430,28 +437,74 @@
         GTK_WIDGET_CLASS (clock_face_parent_class)->unmap (this);
 }
 
+/* The pixbuf is being disposed, so remove it from the cache */
+static void
+remove_pixbuf_from_cache (const char *key,
+                          GObject    *pixbuf)
+{
+        g_hash_table_remove (pixbuf_cache, key);
+}
+
 static void
 clock_face_load_face (ClockFace *this, gint width, gint height)
 {
         ClockFacePrivate *priv = CLOCK_FACE_GET_PRIVATE (this);
 	const gchar *size_string[2] = { "small", "large" };
         const gchar *daytime_string[4] = { "morning", "day", "evening", "night" };
+	gchar *cache_name;
 	gchar *name;
 
+        if (!pixbuf_cache)
+                pixbuf_cache = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                      g_free, NULL);
+
         if (priv->face_pixbuf != NULL) {
-                gdk_pixbuf_unref (priv->face_pixbuf);
+                /* This might empty the cache, but it's useless to destroy
+                 * it since this object is still alive and might add another
+                 * pixbuf in the cache later (eg, a few lines below) */
+                g_object_unref (priv->face_pixbuf);
                 priv->face_pixbuf = NULL;
         }
 
-	name = g_strconcat (ICONDIR, "/clock-face-", size_string[priv->size], "-", daytime_string[priv->timeofday], ".svg", NULL);
+        /* Look for the pixbuf in the process-wide cache first */
+        cache_name = g_strdup_printf ("%d-%d-%d-%d",
+                                      priv->size, priv->timeofday,
+                                      width, height);
 
-	priv->face_pixbuf = rsvg_pixbuf_from_file_at_size (name, width, height, NULL);
+        priv->face_pixbuf = g_hash_table_lookup (pixbuf_cache, cache_name);
+        if (priv->face_pixbuf) {
+                g_object_ref (priv->face_pixbuf);
+                return;
+        }
+
+        /* The pixbuf is not cached, let's load it */
+	name = g_strconcat (ICONDIR, "/clock-face-", size_string[priv->size],
+                            "-", daytime_string[priv->timeofday], ".svg",
+                            NULL);
+	priv->face_pixbuf = rsvg_pixbuf_from_file_at_size (name,
+                                                           width, height,
+                                                           NULL);
 	g_free (name);
 
-	if (priv->face_pixbuf)
-		return;
+	if (!priv->face_pixbuf) {
+                name = g_strconcat (ICONDIR, "/clock-face-",
+                                    size_string[priv->size], ".svg", NULL);
+                priv->face_pixbuf = rsvg_pixbuf_from_file_at_size (name,
+                                                                   width,
+                                                                   height,
+                                                                   NULL);
+                g_free (name);
+        }
 
-	name = g_strconcat (ICONDIR, "/clock-face-", size_string[priv->size], ".svg", NULL);
-	priv->face_pixbuf = rsvg_pixbuf_from_file_at_size (name, width, height, NULL);
-	g_free (name);
+        /* Save the found pixbuf in the cache */
+        if (priv->face_pixbuf) {
+                g_hash_table_replace (pixbuf_cache,
+                                      cache_name, priv->face_pixbuf);
+                /* This will handle automatic removal from the cache when
+                 * the pixbuf isn't needed anymore */
+                g_object_weak_ref (G_OBJECT (priv->face_pixbuf),
+                                   (GWeakNotify) remove_pixbuf_from_cache,
+                                   cache_name);
+        } else
+                g_free (cache_name);
 }



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