[gnome-desktop] gnome-bg: Cache resized wallpaper to help CPU at startup



commit 63c36f78980a4982d364e37e6c1e6219af2ecd32
Author: Didier Roche <didrocks ubuntu com>
Date:   Thu Nov 25 11:12:43 2010 +0100

    gnome-bg: Cache resized wallpaper to help CPU at startup
    
    Resized and transformed wallpapers are stored in ~/.cache/wallpaper/.
    The cache is refreshed for each new current wallpaper depending on the
    resolution or transformation, and each time the source image is
    refreshed.
    
    The source image format is preserved.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=608419

 libgnome-desktop/gnome-bg.c |  238 ++++++++++++++++++++++++++++++++++++-------
 1 files changed, 199 insertions(+), 39 deletions(-)
---
diff --git a/libgnome-desktop/gnome-bg.c b/libgnome-desktop/gnome-bg.c
index 9ad616b..7caaff6 100644
--- a/libgnome-desktop/gnome-bg.c
+++ b/libgnome-desktop/gnome-bg.c
@@ -34,6 +34,7 @@ Author: Soren Sandmann <sandmann redhat com>
 
 #include <gio/gio.h>
 #include <gdesktop-enums.h>
+#include <glib/gstdio.h>
 
 #include <gdk/gdkx.h>
 #include <X11/Xlib.h>
@@ -168,6 +169,7 @@ static gboolean   get_thumb_annotations (GdkPixbuf             *thumb,
 
 /* Cache */
 static GdkPixbuf *get_pixbuf_for_size  (GnomeBG               *bg,
+					gint                   num_monitor,
 					int                    width,
 					int                    height);
 static void       clear_cache          (GnomeBG               *bg);
@@ -529,6 +531,128 @@ gnome_bg_get_filename (GnomeBG *bg)
 	return bg->filename;
 }
 
+static inline gchar *
+get_wallpaper_cache_dir ()
+{
+	return g_build_filename (g_get_user_cache_dir(), "wallpaper", NULL);
+}
+
+static inline gchar *
+get_wallpaper_cache_prefix_name (gint                     num_monitor,
+				 GDesktopBackgroundStyle  placement,
+				 gint                     width,
+				 gint                     height)
+{
+	return g_strdup_printf ("%i_%i_%i_%i", num_monitor, (gint) placement, width, height);
+}
+
+static char *
+get_wallpaper_cache_filename (const char              *filename,
+			      gint                     num_monitor,
+			      GDesktopBackgroundStyle  placement,
+			      gint                     width,
+			      gint                     height)
+{
+	gchar *cache_filename;
+	gchar *cache_prefix_name;
+	gchar *md5_filename;
+	gchar *cache_basename;
+	gchar *cache_dir;
+
+	md5_filename = g_compute_checksum_for_data (G_CHECKSUM_MD5, (const guchar *) filename, strlen (filename));
+	cache_prefix_name = get_wallpaper_cache_prefix_name (num_monitor, placement, width, height);
+	cache_basename = g_strdup_printf ("%s_%s", cache_prefix_name, md5_filename);
+	cache_dir = get_wallpaper_cache_dir ();
+	cache_filename = g_build_filename (cache_dir, cache_basename, NULL);
+
+	g_free (cache_prefix_name);
+	g_free (md5_filename);
+	g_free (cache_basename);
+	g_free (cache_dir);
+
+	return cache_filename;
+}
+
+static gboolean
+cache_file_is_valid (const char *filename,
+		     const char *cache_filename)
+{
+	time_t mtime;
+	time_t cache_mtime;
+
+	if (!g_file_test (cache_filename, G_FILE_TEST_IS_REGULAR))
+		return FALSE;
+
+	mtime = get_mtime (filename);
+	cache_mtime = get_mtime (cache_filename);
+
+	return (mtime < cache_mtime);
+}
+
+static void
+refresh_cache_file (GnomeBG     *bg,
+		    GdkPixbuf   *new_pixbuf,
+		    gint         num_monitor,
+		    gint         width,
+		    gint         height)
+{
+	gchar           *cache_filename;
+	gchar           *cache_dir;
+	GdkPixbufFormat *format;
+	gchar           *format_name;
+	GDir            *g_cache_dir;
+	gchar           *monitor_prefix;
+	const gchar     *file;
+
+	if ((num_monitor != -1) && (width > 300) && (height > 300))
+		return;
+
+	cache_filename = get_wallpaper_cache_filename (bg->filename, num_monitor, bg->placement, width, height);
+	cache_dir = get_wallpaper_cache_dir ();
+
+	/* Only refresh scaled file on disk if useful (and don't cache slideshow) */
+	if (!cache_file_is_valid (bg->filename, cache_filename)) {
+		format = gdk_pixbuf_get_file_info (bg->filename, NULL, NULL);
+
+		if (format != NULL) {
+			if (!g_file_test (cache_dir, G_FILE_TEST_IS_DIR)) {
+				g_mkdir_with_parents (cache_dir, 0700);
+			} else {
+				g_cache_dir = g_dir_open (cache_dir, 0, NULL);
+				monitor_prefix = g_strdup_printf ("%i_", num_monitor);
+
+				file = g_dir_read_name (g_cache_dir);
+				while (file != NULL) {
+					gchar *path;
+
+					path = g_build_filename (cache_dir, file, NULL);
+					/* purge files with same monitor id */
+					if (g_str_has_prefix (file, monitor_prefix) && g_file_test (path, G_FILE_TEST_IS_REGULAR))
+						g_unlink (path);
+					g_free (path);
+
+					file = g_dir_read_name (g_cache_dir);
+				}
+
+				g_free (monitor_prefix);
+				g_dir_close (g_cache_dir);
+			}
+
+			format_name = gdk_pixbuf_format_get_name (format);
+
+			if (strcmp (format_name, "jpeg") == 0)
+				gdk_pixbuf_save (new_pixbuf, cache_filename, format_name, NULL, "quality", "100", NULL);
+			else
+				gdk_pixbuf_save (new_pixbuf, cache_filename, format_name, NULL, NULL);
+
+			g_free (format_name);
+		}
+	}
+
+	g_free (cache_filename);
+	g_free (cache_dir);
+}
+
 static void
 file_changed (GFileMonitor *file_monitor,
 	      GFile *child,
@@ -724,10 +848,11 @@ get_scaled_pixbuf (GDesktopBackgroundStyle placement,
 }
 
 static void
-draw_image_area (GDesktopBackgroundStyle  placement,
-		 GdkPixbuf               *pixbuf,
-		 GdkPixbuf               *dest,
-		 GdkRectangle            *area)
+draw_image_area (GnomeBG         *bg,
+		 gint             num_monitor,
+		 GdkPixbuf       *pixbuf,
+		 GdkPixbuf       *dest,
+		 GdkRectangle    *area)
 {
 	int dest_width = area->width;
 	int dest_height = area->height;
@@ -737,9 +862,9 @@ draw_image_area (GDesktopBackgroundStyle  placement,
 	if (!pixbuf)
 		return;
 
-	scaled = get_scaled_pixbuf (placement, pixbuf, dest_width, dest_height, &x, &y, &w, &h);
+	scaled = get_scaled_pixbuf (bg->placement, pixbuf, dest_width, dest_height, &x, &y, &w, &h);
 
-	switch (placement) {
+	switch (bg->placement) {
 	case G_DESKTOP_BACKGROUND_STYLE_WALLPAPER:
 		pixbuf_tile (scaled, dest);
 		break;
@@ -756,12 +881,14 @@ draw_image_area (GDesktopBackgroundStyle  placement,
 		g_assert_not_reached ();
 		break;
 	}
-	
+
+	refresh_cache_file (bg, scaled, num_monitor, dest_width, dest_height);
+
 	g_object_unref (scaled);
 }
 
 static void
-draw_image (GDesktopBackgroundStyle  placement,
+draw_image_for_thumb (GnomeBG       *bg,
 	    GdkPixbuf               *pixbuf,
 	    GdkPixbuf               *dest)
 {
@@ -772,7 +899,7 @@ draw_image (GDesktopBackgroundStyle  placement,
 	rect.width = gdk_pixbuf_get_width (dest);
 	rect.height = gdk_pixbuf_get_height (dest);
 
-	draw_image_area (placement, pixbuf, dest, &rect);
+	draw_image_area (bg, -1, pixbuf, dest, &rect);
 }
 
 static void
@@ -782,15 +909,20 @@ draw_once (GnomeBG   *bg,
 {
 	GdkRectangle rect;
 	GdkPixbuf   *pixbuf;
+	gint         num_monitor;
+
+	/* we just draw on the whole screen */
+	num_monitor = 0;
 
 	rect.x = 0;
 	rect.y = 0;
 	rect.width = gdk_pixbuf_get_width (dest);
 	rect.height = gdk_pixbuf_get_height (dest);
 
-	pixbuf = get_pixbuf_for_size (bg, gdk_pixbuf_get_width (dest), gdk_pixbuf_get_height (dest));
+	pixbuf = get_pixbuf_for_size (bg, num_monitor, rect.width, rect.height);
 	if (pixbuf) {
-		draw_image_area (bg->placement,
+		draw_image_area (bg,
+				 num_monitor,
 				 pixbuf,
 				 dest,
 				 &rect);
@@ -811,9 +943,10 @@ draw_each_monitor (GnomeBG   *bg,
 	for (monitor = 0; monitor < num_monitors; monitor++) {
 		GdkPixbuf *pixbuf;
 		gdk_screen_get_monitor_geometry (screen, monitor, &rect);
-		pixbuf = get_pixbuf_for_size (bg, rect.width, rect.height);
+		pixbuf = get_pixbuf_for_size (bg, monitor, rect.width, rect.height);
 		if (pixbuf) {
-			draw_image_area (bg->placement,
+			draw_image_area (bg,
+					 monitor,
 					 pixbuf,
 					 dest, &rect);
 			g_object_unref (pixbuf);
@@ -985,7 +1118,7 @@ gnome_bg_is_dark (GnomeBG *bg,
 		color.green = (bg->primary.green + bg->secondary.green) / 2;
 		color.blue = (bg->primary.blue + bg->secondary.blue) / 2;
 	}
-	pixbuf = get_pixbuf_for_size (bg, width, height);
+	pixbuf = get_pixbuf_for_size (bg, -1, width, height);
 	if (pixbuf) {
 		guint32 argb = pixbuf_average_value (pixbuf);
 		guchar a = (argb >> 24) & 0xff;
@@ -1155,7 +1288,7 @@ gnome_bg_create_thumbnail (GnomeBG               *bg,
 		thumb = create_img_thumbnail (bg, factory, screen, dest_width, dest_height, -1);
 		
 		if (thumb) {
-			draw_image (bg->placement, thumb, result);
+			draw_image_for_thumb (bg, thumb, result);
 			g_object_unref (thumb);
 		}
 	}
@@ -1602,10 +1735,29 @@ file_cache_add_slide_show (GnomeBG *bg,
 }
 
 static GdkPixbuf *
+load_from_cache_file (GnomeBG    *bg,
+		      const char *filename,
+		      gint        num_monitor,
+		      gint        best_width,
+		      gint        best_height)
+{
+	GdkPixbuf *pixbuf = NULL;
+	gchar *cache_filename;
+
+	cache_filename = get_wallpaper_cache_filename (filename, num_monitor, bg->placement, best_width, best_height);
+	if (cache_file_is_valid (filename, cache_filename))
+		pixbuf = gdk_pixbuf_new_from_file (cache_filename, NULL);
+	g_free (cache_filename);
+
+	return pixbuf;
+}
+
+static GdkPixbuf *
 get_as_pixbuf_for_size (GnomeBG    *bg,
 			const char *filename,
-			int         best_width,
-			int         best_height)
+			gint        num_monitor,
+			gint        best_width,
+			gint        best_height)
 {
 	const FileCacheEntry *ent;
 	if ((ent = file_cache_lookup (bg, PIXBUF, filename))) {
@@ -1615,26 +1767,33 @@ get_as_pixbuf_for_size (GnomeBG    *bg,
 		GdkPixbufFormat *format;
 		GdkPixbuf *pixbuf;
                 gchar *tmp;
+		pixbuf = NULL;
 
-		/* If scalable choose maximum size */
-		format = gdk_pixbuf_get_file_info (filename, NULL, NULL);
+		/* Try to hit local cache first if relevant */
+		if (num_monitor != -1)
+			pixbuf = load_from_cache_file (bg, filename, num_monitor, best_width, best_height);
 
-                if (format != NULL) {
-                        tmp = gdk_pixbuf_format_get_name (format);
-                } else {
-                        tmp = NULL;
-                }
+		if (!pixbuf) {
+			/* If scalable choose maximum size */
+			format = gdk_pixbuf_get_file_info (filename, NULL, NULL);
 
-		if (tmp != NULL &&
-		    strcmp (tmp, "svg") == 0 &&
-		    (best_width > 0 && best_height > 0) &&
-		    (bg->placement == G_DESKTOP_BACKGROUND_STYLE_STRETCHED ||
-		     bg->placement == G_DESKTOP_BACKGROUND_STYLE_SCALED ||
-		     bg->placement == G_DESKTOP_BACKGROUND_STYLE_ZOOM))
-			pixbuf = gdk_pixbuf_new_from_file_at_size (filename, best_width, best_height, NULL);
-		else
-			pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
-                g_free (tmp);
+			if (format != NULL) {
+				tmp = gdk_pixbuf_format_get_name (format);
+			} else {
+				tmp = NULL;
+			}
+
+			if (tmp != NULL &&
+			    strcmp (tmp, "svg") == 0 &&
+			    (best_width > 0 && best_height > 0) &&
+			    (bg->placement == G_DESKTOP_BACKGROUND_STYLE_STRETCHED ||
+			     bg->placement == G_DESKTOP_BACKGROUND_STYLE_SCALED ||
+			     bg->placement == G_DESKTOP_BACKGROUND_STYLE_ZOOM))
+				pixbuf = gdk_pixbuf_new_from_file_at_size (filename, best_width, best_height, NULL);
+			else
+				pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
+			g_free (tmp);
+		}
 
 		if (pixbuf)
 			file_cache_add_pixbuf (bg, filename, pixbuf);
@@ -2000,6 +2159,7 @@ find_best_size (GSList *sizes, gint width, gint height)
 
 static GdkPixbuf *
 get_pixbuf_for_size (GnomeBG *bg,
+		     gint num_monitor,
 		     gint best_width,
 		     gint best_height)
 {
@@ -2021,7 +2181,7 @@ get_pixbuf_for_size (GnomeBG *bg,
 	if (!hit_cache && bg->filename) {
 		bg->file_mtime = get_mtime (bg->filename);
 
-		bg->pixbuf_cache = get_as_pixbuf_for_size (bg, bg->filename, best_width, best_height);
+		bg->pixbuf_cache = get_as_pixbuf_for_size (bg, bg->filename, num_monitor, best_width, best_height);
 		time_until_next_change = G_MAXUINT;
 		if (!bg->pixbuf_cache) {
 			SlideShow *show = get_as_slideshow (bg, bg->filename);
@@ -2037,15 +2197,15 @@ get_pixbuf_for_size (GnomeBG *bg,
 				if (slide->fixed) {
 					FileSize *size;
 					size = find_best_size (slide->file1, best_width, best_height);
-					bg->pixbuf_cache = get_as_pixbuf_for_size (bg, size->file, best_width, best_height);
+					bg->pixbuf_cache = get_as_pixbuf_for_size (bg, size->file, num_monitor, best_width, best_height);
 				}
 				else {
 					FileSize *size;
 					GdkPixbuf *p1, *p2;
 					size = find_best_size (slide->file1, best_width, best_height);
-					p1 = get_as_pixbuf_for_size (bg, size->file, best_width, best_height);
+					p1 = get_as_pixbuf_for_size (bg, size->file, num_monitor, best_width, best_height);
 					size = find_best_size (slide->file2, best_width, best_height);
-					p2 = get_as_pixbuf_for_size (bg, size->file, best_width, best_height);
+					p2 = get_as_pixbuf_for_size (bg, size->file, num_monitor, best_width, best_height);
 
 					if (p1 && p2) {
 						bg->pixbuf_cache = blend (p1, p2, alpha);
@@ -2883,7 +3043,7 @@ gnome_bg_create_frame_thumbnail (GnomeBG			*bg,
 		thumb = create_img_thumbnail (bg, factory, screen, dest_width, dest_height, frame_num + skipped);
 
 		if (thumb) {
-			draw_image (bg->placement, thumb, result);
+			draw_image_for_thumb (bg, thumb, result);
 			g_object_unref (thumb);
 		}
 	}



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