Icon scaling



Currently the list view spends a lot of time scaling down icons that
have a greater nominal size than base size. 

Every time the list model is asked for an icon, and it finds out that
that icon is too large, it scales it down. This means that every
expose of the list view results in a lot icons getting scaled down
which is showing up on profiles.

This patch adds the ability to cache these scaled icons. 

(It also adds a hash table to stop warnings from being displayed more
than once, but that's not really related).


Søren

Index: libnautilus-private/nautilus-file.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-file.c,v
retrieving revision 1.344
diff -u -p -u -r1.344 nautilus-file.c
--- libnautilus-private/nautilus-file.c	8 Mar 2004 09:50:30 -0000	1.344
+++ libnautilus-private/nautilus-file.c	27 Mar 2004 21:18:26 -0000
@@ -4701,10 +4701,19 @@ get_description (NautilusFile *file)
 			     "probably means that your gnome-vfs.keys file is in the wrong place "
 			     "or isn't being found for some other reason."));
 	} else {
-		g_warning (_("No description found for mime type \"%s\" (file is \"%s\"), "
-			     "please tell the gnome-vfs mailing list."),
-			   mime_type,
-			   file->details->relative_uri);
+		static GHashTable *warned = NULL;
+
+		if (!warned)
+			warned = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+		if (!g_hash_table_lookup (warned, mime_type)) {
+			g_warning (_("No description found for mime type \"%s\" (file is \"%s\"), "
+				     "please tell the gnome-vfs mailing list."),
+				   mime_type,
+				   file->details->relative_uri);
+
+			g_hash_table_insert (warned, g_strdup (mime_type), GINT_TO_POINTER (1));
+		}
 	}
 	return mime_type;
 }
Index: libnautilus-private/nautilus-icon-factory.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-icon-factory.c,v
retrieving revision 1.302
diff -u -p -u -r1.302 nautilus-icon-factory.c
--- libnautilus-private/nautilus-icon-factory.c	5 Mar 2004 13:33:53 -0000	1.302
+++ libnautilus-private/nautilus-icon-factory.c	27 Mar 2004 21:18:27 -0000
@@ -99,6 +99,7 @@ typedef struct {
 	char *name; /* Icon name or absolute filename */
 	char *modifier;
 	guint nominal_size;
+	gboolean force_nominal;
 } CacheKey;
 
 /* The value in the same table. */
@@ -186,7 +187,8 @@ static CacheIcon *cache_icon_new        
 							  double                    scale_y);
 static CacheIcon *get_icon_from_cache                    (const char               *icon,
 							  const char               *modifier,
-							  guint                     nominal_size);
+							  guint                     nominal_size,
+							  gboolean		    force_nominal);
 static void nautilus_icon_factory_clear                  (void);
 
 GNOME_CLASS_BOILERPLATE (NautilusIconFactory,
@@ -1084,6 +1086,7 @@ static GdkPixbuf *
 load_icon_file (const char    *filename,
 		guint          base_size,
 		guint          nominal_size,
+		gboolean       force_nominal,
 		double        *scale_x,
 		double        *scale_y)
 {
@@ -1129,6 +1132,14 @@ load_icon_file (const char    *filename,
 					base_size = NAUTILUS_ICON_SIZE_STANDARD;
 				}
 			}
+		} else if (force_nominal) {
+			width = gdk_pixbuf_get_width (pixbuf); 
+			height = gdk_pixbuf_get_height (pixbuf);
+			size = MAX (width, height);
+
+			if (size > base_size) {
+				base_size = size;
+			}
 		}
 		
 		if (base_size != nominal_size) {
@@ -1147,7 +1158,8 @@ load_icon_file (const char    *filename,
 static CacheIcon *
 create_normal_cache_icon (const char *icon,
 			  const char *modifier,
-			  guint       nominal_size)
+			  guint       nominal_size,
+			  gboolean    force_nominal)
 {
 	NautilusIconFactory *factory;
 	const char *filename;
@@ -1208,6 +1220,7 @@ create_normal_cache_icon (const char *ic
 	pixbuf = load_icon_file (filename,
 				 base_size,
 				 nominal_size,
+				 force_nominal,
 				 &scale_x, &scale_y);
 	if (pixbuf == NULL) {
 		if (info) {
@@ -1232,11 +1245,14 @@ create_normal_cache_icon (const char *ic
  * If @picky is true, then only an unscaled icon is acceptable.
  * Also, if @picky is true, the icon must be a custom icon if
  * @custom is true or a standard icon is @custom is false.
+ * If @force_nominal is #TRUE, the returned icon will be guaranteed
+ * to be smaller than the nominal size
  */
 static CacheIcon *
 get_icon_from_cache (const char *icon,
 		     const char *modifier,
-		     guint       nominal_size)
+		     guint       nominal_size,
+		     gboolean    force_nominal)
 {
 	NautilusIconFactory *factory;
 	GHashTable *hash_table;
@@ -1258,6 +1274,7 @@ get_icon_from_cache (const char *icon,
 	lookup_key.name = (char *)icon;
 	lookup_key.modifier = (char *)modifier;
 	lookup_key.nominal_size = nominal_size;
+	lookup_key.force_nominal = force_nominal;
 
 	if (g_hash_table_lookup_extended (hash_table, &lookup_key,
 					  &key_in_table, &value)) {
@@ -1288,12 +1305,14 @@ get_icon_from_cache (const char *icon,
 		
 		cached_icon = create_normal_cache_icon (icon,
 							modifier,
-							nominal_size);
+							nominal_size,
+							force_nominal);
 		/* Try to fallback without modifier */
 		if (cached_icon == NULL && modifier != NULL) {
 			cached_icon = create_normal_cache_icon (icon,
 								NULL,
-								nominal_size);
+								nominal_size,
+								force_nominal);
 		}
 		
 		if (cached_icon == NULL) {
@@ -1306,6 +1325,7 @@ get_icon_from_cache (const char *icon,
 		key->name = g_strdup (icon);
 		key->modifier = g_strdup (modifier);
 		key->nominal_size = nominal_size;
+		key->force_nominal = force_nominal;
 
 		g_hash_table_insert (hash_table, key, cached_icon);
 	}
@@ -1322,14 +1342,15 @@ get_icon_from_cache (const char *icon,
         return cached_icon;
 }
 
-GdkPixbuf *
-nautilus_icon_factory_get_pixbuf_for_icon (const char                  *icon,
-					   const char                  *modifier,
-					   guint                        nominal_size,
-					   NautilusEmblemAttachPoints  *attach_points,
-					   GdkRectangle                *embedded_text_rect,
-					   gboolean                     wants_default,
-					   char                       **display_name)
+static GdkPixbuf *
+nautilus_icon_factory_get_pixbuf_for_icon_internal (const char                  *icon,
+						    const char                  *modifier,
+						    guint                        nominal_size,
+						    gboolean                     force_size,
+						    NautilusEmblemAttachPoints  *attach_points,
+						    GdkRectangle                *embedded_text_rect,
+						    gboolean                     wants_default,
+						    char                       **display_name)
 {
 	NautilusIconFactory *factory;
 	CacheIcon *cached_icon;
@@ -1339,7 +1360,8 @@ nautilus_icon_factory_get_pixbuf_for_ico
 	factory = get_icon_factory ();
 	cached_icon = get_icon_from_cache (icon,
 					   modifier,
-					   nominal_size);
+					   nominal_size,
+					   force_size);
 
 	if (attach_points != NULL) {
 		if (cached_icon->attach_points != NULL) {
@@ -1381,6 +1403,20 @@ nautilus_icon_factory_get_pixbuf_for_ico
 	return pixbuf;
 }
 
+GdkPixbuf *
+nautilus_icon_factory_get_pixbuf_for_icon (const char                  *icon,
+					   const char                  *modifier,
+					   guint                        nominal_size,
+					   NautilusEmblemAttachPoints  *attach_points,
+					   GdkRectangle                *embedded_text_rect,
+					   gboolean                     wants_default,
+					   char                       **display_name)
+{
+	return nautilus_icon_factory_get_pixbuf_for_icon_internal (icon, modifier, nominal_size, FALSE,
+								   attach_points, embedded_text_rect,
+								   wants_default, display_name);
+}
+
 static guint
 cache_key_hash (gconstpointer p)
 {
@@ -1390,12 +1426,12 @@ cache_key_hash (gconstpointer p)
 	key = p;
 
 	hash =  g_str_hash (key->name) ^
-		(key->nominal_size << 4);
+		((key->nominal_size << 4) + (gint)key->force_nominal);
 	
 	if (key->modifier) {
 		hash ^= g_str_hash (key->modifier);
 	}
-		
+
 	return hash;
 }
 
@@ -1409,6 +1445,7 @@ cache_key_equal (gconstpointer a, gconst
 
 	return eel_strcmp (key_a->name, key_b->name) == 0 &&
 		key_a->nominal_size ==  key_b->nominal_size &&
+		key_a->force_nominal == key_b->force_nominal &&
 		eel_strcmp (key_a->modifier, key_b->modifier) == 0;
 }
 
@@ -1443,10 +1480,11 @@ nautilus_get_icon_size_for_zoom_level (N
 /* Convenience cover for nautilus_icon_factory_get_icon_for_file
  * and nautilus_icon_factory_get_pixbuf_for_icon.
  */
-GdkPixbuf *
-nautilus_icon_factory_get_pixbuf_for_file (NautilusFile *file,
-					   const char *modifier,
-					   guint size_in_pixels)
+static GdkPixbuf *
+nautilus_icon_factory_get_pixbuf_for_file_internal (NautilusFile *file,
+						    const char *modifier,
+						    guint size_in_pixels,
+						    gboolean force_size)
 {
 	char *icon;
 	GdkPixbuf *pixbuf;
@@ -1458,16 +1496,39 @@ nautilus_icon_factory_get_pixbuf_for_fil
 		return NULL;
 	}
 
-	pixbuf = nautilus_icon_factory_get_pixbuf_for_icon (icon, modifier,
-							    size_in_pixels,
-							    NULL, NULL,
-							    TRUE, NULL);
+	pixbuf = nautilus_icon_factory_get_pixbuf_for_icon_internal (icon, modifier,
+								     size_in_pixels,
+								     force_size,
+								     NULL, NULL,
+								     TRUE, NULL);
 	
 	g_free (icon);
 
 	return pixbuf;
 }
 
+GdkPixbuf *
+nautilus_icon_factory_get_pixbuf_for_file (NautilusFile *file,
+					   const char *modifier,
+					   guint size_in_pixels)
+{
+	return nautilus_icon_factory_get_pixbuf_for_file_internal (file,
+								   modifier,
+								   size_in_pixels,
+								   FALSE);
+}
+
+GdkPixbuf *
+nautilus_icon_factory_get_pixbuf_for_file_force_size (NautilusFile *file,
+						      const char *modifier,
+						      guint size_in_pixels)
+{
+	return nautilus_icon_factory_get_pixbuf_for_file_internal (file,
+								   modifier,
+								   size_in_pixels,
+								   TRUE);
+}
+
 /* Convenience routine for getting a pixbuf from an icon name. */
 GdkPixbuf *
 nautilus_icon_factory_get_pixbuf_from_name (const char *icon_name,
Index: libnautilus-private/nautilus-icon-factory.h
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-icon-factory.h,v
retrieving revision 1.48
diff -u -p -u -r1.48 nautilus-icon-factory.h
--- libnautilus-private/nautilus-icon-factory.h	18 Dec 2003 18:38:23 -0000	1.48
+++ libnautilus-private/nautilus-icon-factory.h	27 Mar 2004 21:18:28 -0000
@@ -138,6 +138,9 @@ GdkPixbuf *           nautilus_icon_fact
 GdkPixbuf *           nautilus_icon_factory_get_pixbuf_for_file          (NautilusFile                *file,
 									  const char                  *modifer,
 									  guint                        size_in_pixels);
+GdkPixbuf *	      nautilus_icon_factory_get_pixbuf_for_file_force_size (NautilusFile *file,
+									    const char *modifier,
+									    guint size_in_pixels);
 
 /* Convenience routine for getting a pixbuf from an icon name
  */
Index: src/file-manager/fm-list-model.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-list-model.c,v
retrieving revision 1.28
diff -u -p -u -r1.28 fm-list-model.c
--- src/file-manager/fm-list-model.c	10 Mar 2004 12:44:17 -0000	1.28
+++ src/file-manager/fm-list-model.c	27 Mar 2004 21:18:29 -0000
@@ -229,16 +229,8 @@ fm_list_model_get_value (GtkTreeModel *t
 			modifier = "visiting";
 		}
 		
-		icon = nautilus_icon_factory_get_pixbuf_for_file (file, modifier, icon_size);
+		icon = nautilus_icon_factory_get_pixbuf_for_file_force_size (file, modifier, icon_size);
 
-		height = gdk_pixbuf_get_height (icon);
-		if (height > icon_size) {
-			width = gdk_pixbuf_get_width (icon) * icon_size / height;
-			height = icon_size;
-			tmp = gdk_pixbuf_scale_simple (icon, width, height, GDK_INTERP_BILINEAR);
-			g_object_unref (icon);
-			icon = tmp;
-		}
 		g_value_set_object (value, icon);
 		g_object_unref (icon);
 		break;
@@ -265,8 +257,9 @@ fm_list_model_get_value (GtkTreeModel *t
 		if (emblem_icons != NULL) {
 			zoom_level = fm_list_model_get_zoom_level_from_emblem_column_id (column);
 			icon_size = nautilus_get_icon_size_for_zoom_level (zoom_level);
-			icon = nautilus_icon_factory_get_pixbuf_for_icon (emblem_icons->data, NULL, icon_size,
-									  NULL, NULL, FALSE, NULL);
+			icon = nautilus_icon_factory_get_pixbuf_for_icon_force_size (
+				emblem_icons->data, NULL, icon_size,
+				NULL, NULL, FALSE, NULL);
 			eel_g_list_free_deep (emblem_icons);
 	
 			height = gdk_pixbuf_get_height (icon);


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