1 /* -*- Mode: C; indent-tabs-mode: f; c-basic-offset: 4; tab-width: 4 -*- */
2 /* nemo-icon-info.c
3  * Copyright (C) 2007  Red Hat, Inc.,  Alexander Larsson <alexl@redhat.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin Street - Suite 500,
18  * Boston, MA 02110-1335, USA.
19  */
20 
21 #include <config.h>
22 #include <string.h>
23 #include "nemo-icon-info.h"
24 #include "nemo-icon-names.h"
25 #include "nemo-default-file-icon.h"
26 #include <gtk/gtk.h>
27 #include <gio/gio.h>
28 
29 static void schedule_reap_cache (void);
30 
31 static void
pixbuf_toggle_notify(gpointer info,GObject * object,gboolean is_last_ref)32 pixbuf_toggle_notify (gpointer      info,
33               GObject      *object,
34               gboolean      is_last_ref)
35 {
36     NemoIconInfo  *icon = info;
37 
38     if (is_last_ref) {
39         icon->sole_owner = TRUE;
40         g_object_remove_toggle_ref (object,
41                         pixbuf_toggle_notify,
42                         info);
43         icon->last_use_time = g_get_monotonic_time ();
44         schedule_reap_cache ();
45     }
46 }
47 
48 static void
nemo_icon_info_free(NemoIconInfo * icon)49 nemo_icon_info_free (NemoIconInfo *icon)
50 {
51     g_return_if_fail (icon != NULL);
52 
53     if (!icon->sole_owner && icon->pixbuf) {
54         g_object_remove_toggle_ref (G_OBJECT (icon->pixbuf),
55                                     pixbuf_toggle_notify,
56                                     icon);
57     }
58 
59     if (icon->pixbuf) {
60         g_object_unref (icon->pixbuf);
61     }
62 
63     g_free (icon->icon_name);
64 
65     g_slice_free (NemoIconInfo, icon);
66 }
67 
68 NemoIconInfo *
nemo_icon_info_ref(NemoIconInfo * icon)69 nemo_icon_info_ref (NemoIconInfo *icon)
70 {
71     g_return_val_if_fail (icon != NULL, NULL);
72 
73     icon->ref_count++;
74 
75     return icon;
76 }
77 
78 void
nemo_icon_info_unref(NemoIconInfo * icon)79 nemo_icon_info_unref (NemoIconInfo *icon)
80 {
81     g_return_if_fail (icon != NULL);
82     g_return_if_fail (icon->ref_count > 0);
83 
84     icon->ref_count--;
85 
86     if (icon->ref_count == 0) {
87         nemo_icon_info_free (icon);
88     }
89 }
90 
91 void
nemo_icon_info_clear(NemoIconInfo ** info)92 nemo_icon_info_clear (NemoIconInfo **info)
93 {
94     gpointer _info;
95 
96     _info = *info;
97 
98     if (_info) {
99         *info = NULL;
100         nemo_icon_info_unref (_info);
101     }
102 }
103 
104 static NemoIconInfo *
nemo_icon_info_create(void)105 nemo_icon_info_create (void)
106 {
107     NemoIconInfo *icon;
108 
109     icon = g_slice_new0 (NemoIconInfo);
110 
111 	icon->last_use_time = g_get_monotonic_time ();
112 	icon->sole_owner = TRUE;
113     icon->ref_count = 1;
114 
115     return icon;
116 }
117 
118 gboolean
nemo_icon_info_is_fallback(NemoIconInfo * icon)119 nemo_icon_info_is_fallback (NemoIconInfo  *icon)
120 {
121   return icon->pixbuf == NULL;
122 }
123 
124 NemoIconInfo *
nemo_icon_info_new_for_pixbuf(GdkPixbuf * pixbuf,gint scale)125 nemo_icon_info_new_for_pixbuf (GdkPixbuf *pixbuf,
126                                 gint      scale)
127 {
128 	NemoIconInfo *icon;
129 
130 	icon = nemo_icon_info_create ();
131 
132 	if (pixbuf) {
133 		icon->pixbuf = g_object_ref (pixbuf);
134 	}
135 
136     icon->orig_scale = scale;
137 
138 	return icon;
139 }
140 
141 static NemoIconInfo *
nemo_icon_info_new_for_icon_info(GtkIconInfo * icon_info,gint scale)142 nemo_icon_info_new_for_icon_info (GtkIconInfo *icon_info,
143                                   gint         scale)
144 {
145 	NemoIconInfo *icon;
146 	const char *filename;
147 	char *basename, *p;
148 
149 	icon = nemo_icon_info_create ();
150 
151 	icon->pixbuf = gtk_icon_info_load_icon (icon_info, NULL);
152 
153 	filename = gtk_icon_info_get_filename (icon_info);
154 	if (filename != NULL) {
155 		basename = g_path_get_basename (filename);
156 		p = strrchr (basename, '.');
157 		if (p) {
158 			*p = 0;
159 		}
160 		icon->icon_name = basename;
161 	}
162 
163     icon->orig_scale = scale;
164 
165 	return icon;
166 }
167 
168 
169 typedef struct  {
170 	GIcon *icon;
171 	int size;
172 } IconKey;
173 
174 static GHashTable *loadable_icon_cache = NULL;
175 static GHashTable *themed_icon_cache = NULL;
176 static guint reap_cache_timeout = 0;
177 
178 #define MICROSEC_PER_SEC ((guint64)1000000L)
179 
180 static guint time_now;
181 
182 static gboolean
reap_old_icon(gpointer key,gpointer value,gpointer user_info)183 reap_old_icon (gpointer  key,
184 	       gpointer  value,
185 	       gpointer  user_info)
186 {
187 	NemoIconInfo *icon = value;
188 	gboolean *reapable_icons_left = user_info;
189 
190 	if (icon->sole_owner) {
191 		if (time_now - icon->last_use_time > (gint64)(30 * MICROSEC_PER_SEC)) {
192 			/* This went unused 30 secs ago. reap */
193 			return TRUE;
194 		} else {
195 			/* We can reap this soon */
196 			*reapable_icons_left = TRUE;
197 		}
198 	}
199 
200 	return FALSE;
201 }
202 
203 static gboolean
reap_cache(gpointer data)204 reap_cache (gpointer data)
205 {
206 	gboolean reapable_icons_left;
207 
208 	reapable_icons_left = TRUE;
209 
210 	time_now = g_get_monotonic_time ();
211 
212 	if (loadable_icon_cache) {
213 		g_hash_table_foreach_remove (loadable_icon_cache,
214 					     reap_old_icon,
215 					     &reapable_icons_left);
216 	}
217 
218 	if (themed_icon_cache) {
219 		g_hash_table_foreach_remove (themed_icon_cache,
220 					     reap_old_icon,
221 					     &reapable_icons_left);
222 	}
223 
224 	if (reapable_icons_left) {
225 		return TRUE;
226 	} else {
227 		reap_cache_timeout = 0;
228 		return FALSE;
229 	}
230 }
231 
232 static void
schedule_reap_cache(void)233 schedule_reap_cache (void)
234 {
235 	if (reap_cache_timeout == 0) {
236 		reap_cache_timeout = g_timeout_add_seconds_full (0, 5,
237 								 reap_cache,
238 								 NULL, NULL);
239 	}
240 }
241 
242 void
nemo_icon_info_clear_caches(void)243 nemo_icon_info_clear_caches (void)
244 {
245 	if (loadable_icon_cache) {
246 		g_hash_table_remove_all (loadable_icon_cache);
247 	}
248 
249 	if (themed_icon_cache) {
250 		g_hash_table_remove_all (themed_icon_cache);
251 	}
252 }
253 
254 static guint
icon_key_hash(IconKey * key)255 icon_key_hash (IconKey *key)
256 {
257 	return g_icon_hash (key->icon) ^ key->size;
258 }
259 
260 static gboolean
icon_key_equal(const IconKey * a,const IconKey * b)261 icon_key_equal (const IconKey *a,
262                 const IconKey *b)
263 {
264 	return a->size == b->size &&
265 		g_icon_equal (a->icon, b->icon);
266 }
267 
268 static IconKey *
icon_key_new(GIcon * icon,int size)269 icon_key_new (GIcon *icon, int size)
270 {
271 	IconKey *key;
272 
273 	key = g_slice_new (IconKey);
274 	key->icon = g_object_ref (icon);
275 	key->size = size;
276 
277 	return key;
278 }
279 
280 static void
icon_key_free(IconKey * key)281 icon_key_free (IconKey *key)
282 {
283 	g_object_unref (key->icon);
284 	g_slice_free (IconKey, key);
285 }
286 
287 NemoIconInfo *
nemo_icon_info_lookup(GIcon * icon,int size,int scale)288 nemo_icon_info_lookup (GIcon *icon,
289                int size,
290                int scale)
291 {
292     GtkIconTheme *icon_theme;
293     GtkIconInfo *gtkicon_info;
294 
295     NemoIconInfo *icon_info;
296 
297     icon_theme = gtk_icon_theme_get_default ();
298 
299     if (G_IS_LOADABLE_ICON (icon)) {
300         GdkPixbuf *pixbuf;
301 
302         IconKey lookup_key;
303         IconKey *key;
304         GInputStream *stream;
305 
306         if (loadable_icon_cache == NULL) {
307             loadable_icon_cache = g_hash_table_new_full ((GHashFunc) icon_key_hash,
308                                                          (GEqualFunc) icon_key_equal,
309                                                          (GDestroyNotify) icon_key_free,
310                                                          (GDestroyNotify) nemo_icon_info_free);
311         }
312 
313         lookup_key.icon = icon;
314         lookup_key.size = size;
315 
316         icon_info = g_hash_table_lookup (loadable_icon_cache, &lookup_key);
317         if (icon_info) {
318             return nemo_icon_info_ref (icon_info);
319         }
320 
321         pixbuf = NULL;
322         stream = g_loadable_icon_load (G_LOADABLE_ICON (icon),
323                            size * scale,
324                            NULL, NULL, NULL);
325 
326         if (stream) {
327             pixbuf = gdk_pixbuf_new_from_stream_at_scale (stream,
328                                       size * scale, size * scale,
329                                       TRUE,
330                                       NULL, NULL);
331             g_input_stream_close (stream, NULL, NULL);
332             g_object_unref (stream);
333         }
334 
335         if (!pixbuf) {
336             gtkicon_info = gtk_icon_theme_lookup_icon_for_scale (icon_theme,
337                                                                  "text-x-generic",
338                                                                  size,
339                                                                  scale,
340                                                                  GTK_ICON_LOOKUP_FORCE_SIZE);
341 
342             pixbuf = gtk_icon_info_load_icon (gtkicon_info, NULL);
343         }
344 
345         icon_info = nemo_icon_info_new_for_pixbuf (pixbuf, scale);
346 
347         key = icon_key_new (icon, size);
348         g_hash_table_insert (loadable_icon_cache, key, icon_info);
349 
350         g_clear_object (&pixbuf);
351 
352         return nemo_icon_info_ref (icon_info);
353     } else  {
354         IconKey lookup_key;
355         IconKey *key;
356 
357         if (themed_icon_cache == NULL) {
358             themed_icon_cache = g_hash_table_new_full ((GHashFunc) icon_key_hash,
359                                                        (GEqualFunc) icon_key_equal,
360                                                        (GDestroyNotify) icon_key_free,
361                                                        (GDestroyNotify) nemo_icon_info_free);
362         }
363 
364         lookup_key.icon = icon;
365         lookup_key.size = size;
366 
367         icon_info = g_hash_table_lookup (themed_icon_cache, &lookup_key);
368         if (icon_info) {
369             return nemo_icon_info_ref (icon_info);
370         }
371 
372         gtkicon_info = NULL;
373 
374         gtkicon_info = gtk_icon_theme_lookup_by_gicon_for_scale (icon_theme,
375                                                                  icon,
376                                                                  size,
377                                                                  scale,
378                                                                  GTK_ICON_LOOKUP_FORCE_SIZE);
379 
380         if (!gtkicon_info) {
381             gtkicon_info = gtk_icon_theme_lookup_icon_for_scale (icon_theme,
382                                                                  "text-x-generic",
383                                                                  size,
384                                                                  scale,
385                                                                  GTK_ICON_LOOKUP_FORCE_SIZE);
386         }
387 
388         icon_info = nemo_icon_info_new_for_icon_info (gtkicon_info, scale);
389         g_object_unref (gtkicon_info);
390 
391         key = icon_key_new (icon, size);
392         g_hash_table_insert (themed_icon_cache, key, icon_info);
393 
394         return nemo_icon_info_ref (icon_info);
395     }
396 }
397 
398 NemoIconInfo *
nemo_icon_info_lookup_from_name(const char * name,int size,int scale)399 nemo_icon_info_lookup_from_name (const char *name,
400                                  int size,
401                                  int scale)
402 {
403 	GIcon *icon;
404 	NemoIconInfo *info;
405 
406 	icon = g_themed_icon_new (name);
407 	info = nemo_icon_info_lookup (icon, size, scale);
408 	g_object_unref (icon);
409 	return info;
410 }
411 
412 NemoIconInfo *
nemo_icon_info_lookup_from_path(const char * path,int size,int scale)413 nemo_icon_info_lookup_from_path (const char *path,
414                                  int size,
415                                  int scale)
416 {
417 	GFile *icon_file;
418 	GIcon *icon;
419 	NemoIconInfo *info;
420 
421 	icon_file = g_file_new_for_path (path);
422 	icon = g_file_icon_new (icon_file);
423 	info = nemo_icon_info_lookup (icon, size, scale);
424 	g_object_unref (icon);
425 	g_object_unref (icon_file);
426 	return info;
427 }
428 
429 GdkPixbuf *
nemo_icon_info_get_pixbuf_nodefault(NemoIconInfo * icon)430 nemo_icon_info_get_pixbuf_nodefault (NemoIconInfo  *icon)
431 {
432 	GdkPixbuf *res;
433 
434 	if (icon->pixbuf == NULL) {
435 		res = NULL;
436 	} else {
437 		res = g_object_ref (icon->pixbuf);
438 
439 		if (icon->sole_owner) {
440 			icon->sole_owner = FALSE;
441 			g_object_add_toggle_ref (G_OBJECT (res),
442 						 pixbuf_toggle_notify,
443 						 icon);
444 		}
445 	}
446 
447 	return res;
448 }
449 
450 
451 GdkPixbuf *
nemo_icon_info_get_pixbuf(NemoIconInfo * icon)452 nemo_icon_info_get_pixbuf (NemoIconInfo *icon)
453 {
454 	GdkPixbuf *res;
455 
456 	res = nemo_icon_info_get_pixbuf_nodefault (icon);
457 	if (res == NULL) {
458 		res = gdk_pixbuf_new_from_data (nemo_default_file_icon,
459 						GDK_COLORSPACE_RGB,
460 						TRUE,
461 						8,
462 						nemo_default_file_icon_width,
463 						nemo_default_file_icon_height,
464 						nemo_default_file_icon_width * 4, /* stride */
465 						NULL, /* don't destroy info */
466 						NULL);
467 	}
468 
469 	return res;
470 }
471 
472 GdkPixbuf *
nemo_icon_info_get_pixbuf_nodefault_at_size(NemoIconInfo * icon,gsize forced_size)473 nemo_icon_info_get_pixbuf_nodefault_at_size (NemoIconInfo  *icon,
474 						 gsize              forced_size)
475 {
476 	GdkPixbuf *pixbuf, *scaled_pixbuf;
477 	guint w, h, s;
478 	double scale;
479 
480 	pixbuf = nemo_icon_info_get_pixbuf_nodefault (icon);
481 
482 	if (pixbuf == NULL)
483 	  return NULL;
484 
485 	w = gdk_pixbuf_get_width (pixbuf) / icon->orig_scale;
486 	h = gdk_pixbuf_get_height (pixbuf) / icon->orig_scale;
487 	s = MAX (w, h);
488 	if (s == forced_size) {
489 		return pixbuf;
490 	}
491 
492 	scale = (double)forced_size / s;
493 	scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf,
494 						 MAX (w * scale, 1), MAX (h * scale, 1),
495 						 GDK_INTERP_BILINEAR);
496 	g_object_unref (pixbuf);
497 	return scaled_pixbuf;
498 }
499 
500 
501 GdkPixbuf *
nemo_icon_info_get_pixbuf_at_size(NemoIconInfo * icon,gsize forced_size)502 nemo_icon_info_get_pixbuf_at_size (NemoIconInfo  *icon,
503 				       gsize              forced_size)
504 {
505 	GdkPixbuf *pixbuf, *scaled_pixbuf;
506 	guint w, h, s;
507 	double scale;
508 
509 	pixbuf = nemo_icon_info_get_pixbuf (icon);
510 
511 	w = gdk_pixbuf_get_width (pixbuf) / icon->orig_scale;
512 	h = gdk_pixbuf_get_height (pixbuf) / icon->orig_scale;
513 	s = MAX (w, h);
514 	if (s == forced_size) {
515 		return pixbuf;
516 	}
517 
518 	scale = (double)forced_size / s;
519 	scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf,
520 						 MAX (w * scale, 1), MAX (h * scale, 1),
521 						 GDK_INTERP_BILINEAR);
522 	g_object_unref (pixbuf);
523 	return scaled_pixbuf;
524 }
525 
526 GdkPixbuf *
nemo_icon_info_get_desktop_pixbuf_at_size(NemoIconInfo * icon,gsize max_height,gsize max_width)527 nemo_icon_info_get_desktop_pixbuf_at_size (NemoIconInfo  *icon,
528                                            gsize          max_height,
529                                            gsize          max_width)
530 {
531     GdkPixbuf *pixbuf, *scaled_pixbuf;
532     guint w, h;
533     double scale;
534 
535     pixbuf = nemo_icon_info_get_pixbuf (icon);
536 
537     w = gdk_pixbuf_get_width (pixbuf) / icon->orig_scale;
538     h = gdk_pixbuf_get_height (pixbuf) / icon->orig_scale;
539 
540     if (w == max_width || h == max_height) {
541         return pixbuf;
542     }
543 
544     scale = (gdouble) max_height / h;
545 
546     if (w * scale > max_width) {
547         scale = (gdouble) max_width / w;
548     }
549 
550     scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf,
551                          MAX (w * scale, 1), MAX (h * scale, 1),
552                          GDK_INTERP_BILINEAR);
553     g_object_unref (pixbuf);
554     return scaled_pixbuf;
555 }
556 
557 const char *
nemo_icon_info_get_used_name(NemoIconInfo * icon)558 nemo_icon_info_get_used_name (NemoIconInfo  *icon)
559 {
560 	return icon->icon_name;
561 }
562 
563 /* Return nominal icon size for given zoom level.
564  * @zoom_level: zoom level for which to find matching icon size.
565  *
566  * Return value: icon size between NEMO_ICON_SIZE_SMALLEST and
567  * NEMO_ICON_SIZE_LARGEST, inclusive.
568  */
569 guint
nemo_get_icon_size_for_zoom_level(NemoZoomLevel zoom_level)570 nemo_get_icon_size_for_zoom_level (NemoZoomLevel zoom_level)
571 {
572 	switch (zoom_level) {
573 	case NEMO_ZOOM_LEVEL_SMALLEST:
574 		return NEMO_ICON_SIZE_SMALLEST;
575 	case NEMO_ZOOM_LEVEL_SMALLER:
576 		return NEMO_ICON_SIZE_SMALLER;
577 	case NEMO_ZOOM_LEVEL_SMALL:
578 		return NEMO_ICON_SIZE_SMALL;
579 	case NEMO_ZOOM_LEVEL_STANDARD:
580 		return NEMO_ICON_SIZE_STANDARD;
581 	case NEMO_ZOOM_LEVEL_LARGE:
582 		return NEMO_ICON_SIZE_LARGE;
583 	case NEMO_ZOOM_LEVEL_LARGER:
584 		return NEMO_ICON_SIZE_LARGER;
585 	case NEMO_ZOOM_LEVEL_LARGEST:
586 		return NEMO_ICON_SIZE_LARGEST;
587     case NEMO_ZOOM_LEVEL_NULL:
588     default:
589         g_return_val_if_reached (NEMO_ICON_SIZE_STANDARD);
590 	}
591 }
592 
593 guint
nemo_get_icon_text_width_for_zoom_level(NemoZoomLevel zoom_level)594 nemo_get_icon_text_width_for_zoom_level (NemoZoomLevel  zoom_level)
595 {
596     switch (zoom_level) {
597     case NEMO_ZOOM_LEVEL_SMALLEST:
598         return NEMO_ICON_TEXT_WIDTH_SMALLEST;
599     case NEMO_ZOOM_LEVEL_SMALLER:
600         return NEMO_ICON_TEXT_WIDTH_SMALLER;
601     case NEMO_ZOOM_LEVEL_SMALL:
602         return NEMO_ICON_TEXT_WIDTH_SMALL;
603     case NEMO_ZOOM_LEVEL_STANDARD:
604         return NEMO_ICON_TEXT_WIDTH_STANDARD;
605     case NEMO_ZOOM_LEVEL_LARGE:
606         return NEMO_ICON_TEXT_WIDTH_LARGE;
607     case NEMO_ZOOM_LEVEL_LARGER:
608         return NEMO_ICON_TEXT_WIDTH_LARGER;
609     case NEMO_ZOOM_LEVEL_LARGEST:
610         return NEMO_ICON_TEXT_WIDTH_LARGEST;
611     case NEMO_ZOOM_LEVEL_NULL:
612     default:
613         g_return_val_if_reached (NEMO_ICON_TEXT_WIDTH_STANDARD);
614     }
615 }
616 
617 
618 
619 guint
nemo_get_desktop_icon_size_for_zoom_level(NemoZoomLevel zoom_level)620 nemo_get_desktop_icon_size_for_zoom_level (NemoZoomLevel zoom_level)
621 {
622     switch (zoom_level) {
623         case NEMO_ZOOM_LEVEL_SMALLER:
624             return NEMO_DESKTOP_ICON_SIZE_SMALLER;
625         case NEMO_ZOOM_LEVEL_SMALL:
626             return NEMO_DESKTOP_ICON_SIZE_SMALL;
627         case NEMO_ZOOM_LEVEL_STANDARD:
628             return NEMO_DESKTOP_ICON_SIZE_STANDARD;
629         case NEMO_ZOOM_LEVEL_LARGE:
630             return NEMO_DESKTOP_ICON_SIZE_LARGE;
631         case NEMO_ZOOM_LEVEL_LARGER:
632             return NEMO_DESKTOP_ICON_SIZE_LARGER;
633         case NEMO_ZOOM_LEVEL_SMALLEST:
634         case NEMO_ZOOM_LEVEL_LARGEST:
635         case NEMO_ZOOM_LEVEL_NULL:
636         default:
637             g_return_val_if_reached (NEMO_ICON_SIZE_STANDARD);
638     }
639 }
640 
641 guint
nemo_get_desktop_text_width_for_zoom_level(NemoZoomLevel zoom_level)642 nemo_get_desktop_text_width_for_zoom_level (NemoZoomLevel  zoom_level)
643 {
644     switch (zoom_level) {
645     case NEMO_ZOOM_LEVEL_SMALLER:
646         return NEMO_DESKTOP_TEXT_WIDTH_SMALLER;
647     case NEMO_ZOOM_LEVEL_SMALL:
648         return NEMO_DESKTOP_TEXT_WIDTH_SMALL;
649     case NEMO_ZOOM_LEVEL_STANDARD:
650         return NEMO_DESKTOP_TEXT_WIDTH_STANDARD;
651     case NEMO_ZOOM_LEVEL_LARGE:
652         return NEMO_DESKTOP_TEXT_WIDTH_LARGE;
653     case NEMO_ZOOM_LEVEL_LARGER:
654         return NEMO_DESKTOP_TEXT_WIDTH_LARGER;
655     case NEMO_ZOOM_LEVEL_NULL:
656     default:
657         g_return_val_if_reached (NEMO_DESKTOP_TEXT_WIDTH_STANDARD);
658     }
659 }
660 
661 guint
nemo_get_list_icon_size_for_zoom_level(NemoZoomLevel zoom_level)662 nemo_get_list_icon_size_for_zoom_level (NemoZoomLevel zoom_level)
663 {
664     switch (zoom_level) {
665     case NEMO_ZOOM_LEVEL_SMALLEST:
666         return NEMO_LIST_ICON_SIZE_SMALLEST;
667     case NEMO_ZOOM_LEVEL_SMALLER:
668         return NEMO_LIST_ICON_SIZE_SMALLEST;
669     case NEMO_ZOOM_LEVEL_SMALL:
670         return NEMO_LIST_ICON_SIZE_SMALLER;
671     case NEMO_ZOOM_LEVEL_STANDARD:
672         return NEMO_LIST_ICON_SIZE_SMALL;
673     case NEMO_ZOOM_LEVEL_LARGE:
674         return NEMO_LIST_ICON_SIZE_STANDARD;
675     case NEMO_ZOOM_LEVEL_LARGER:
676         return NEMO_LIST_ICON_SIZE_LARGE;
677     case NEMO_ZOOM_LEVEL_LARGEST:
678         return NEMO_LIST_ICON_SIZE_LARGER;
679     case NEMO_ZOOM_LEVEL_NULL:
680     default:
681         g_return_val_if_reached (NEMO_ICON_SIZE_STANDARD);
682     }
683 }
684 
685 gint
nemo_get_icon_size_for_stock_size(GtkIconSize size)686 nemo_get_icon_size_for_stock_size (GtkIconSize size)
687 {
688   gint w, h;
689 
690   if (gtk_icon_size_lookup (size, &w, &h)) {
691     return MAX (w, h);
692   }
693   return NEMO_ICON_SIZE_STANDARD;
694 }
695 
696 
697 guint
nemo_icon_get_emblem_size_for_icon_size(guint size)698 nemo_icon_get_emblem_size_for_icon_size (guint size)
699 {
700 	if (size >= 96)
701 		return 48;
702 	if (size >= 64)
703 		return 32;
704 	if (size >= 48)
705 		return 24;
706 	if (size >= 24)
707 		return 16;
708 	if (size >= 16)
709 		return 12;
710 
711 	return 0; /* no emblems for smaller sizes */
712 }
713 
714 GIcon *
nemo_user_special_directory_get_gicon(GUserDirectory directory)715 nemo_user_special_directory_get_gicon (GUserDirectory directory)
716 {
717 
718 	#define ICON_CASE(x) \
719 		case G_USER_DIRECTORY_ ## x:\
720 			return g_themed_icon_new (NEMO_ICON_FOLDER_ ## x);
721 
722 	switch (directory) {
723 
724 		ICON_CASE (DESKTOP);
725 		ICON_CASE (DOCUMENTS);
726 		ICON_CASE (DOWNLOAD);
727 		ICON_CASE (MUSIC);
728 		ICON_CASE (PICTURES);
729 		ICON_CASE (PUBLIC_SHARE);
730 		ICON_CASE (TEMPLATES);
731 		ICON_CASE (VIDEOS);
732 
733     case G_USER_N_DIRECTORIES:
734 	default:
735 		return g_themed_icon_new ("folder");
736 	}
737 
738 	#undef ICON_CASE
739 }
740