1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /* caja-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 St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #include <config.h>
22 #include <string.h>
23 #include "caja-icon-info.h"
24 #include "caja-icon-names.h"
25 #include "caja-default-file-icon.h"
26 #include <gtk/gtk.h>
27 #include <gio/gio.h>
28
29 struct _CajaIconInfo
30 {
31 GObject parent;
32
33 gboolean sole_owner;
34 gint64 last_use_time;
35 GdkPixbuf *pixbuf;
36
37 gboolean got_embedded_rect;
38 GdkRectangle embedded_rect;
39 gint n_attach_points;
40 GdkPoint *attach_points;
41 char *display_name;
42 char *icon_name;
43
44 gint orig_scale;
45 };
46
47 struct _CajaIconInfoClass
48 {
49 GObjectClass parent_class;
50 };
51
52 static void schedule_reap_cache (void);
53
54 G_DEFINE_TYPE (CajaIconInfo,
55 caja_icon_info,
56 G_TYPE_OBJECT);
57
58 static void
caja_icon_info_init(CajaIconInfo * icon)59 caja_icon_info_init (CajaIconInfo *icon)
60 {
61 icon->last_use_time = g_get_monotonic_time ();
62 icon->sole_owner = TRUE;
63 }
64
65 gboolean
caja_icon_info_is_fallback(CajaIconInfo * icon)66 caja_icon_info_is_fallback (CajaIconInfo *icon)
67 {
68 return icon->pixbuf == NULL;
69 }
70
71 static void
pixbuf_toggle_notify(gpointer info,GObject * object,gboolean is_last_ref)72 pixbuf_toggle_notify (gpointer info,
73 GObject *object,
74 gboolean is_last_ref)
75 {
76 CajaIconInfo *icon = info;
77
78 if (is_last_ref)
79 {
80 icon->sole_owner = TRUE;
81 g_object_remove_toggle_ref (object,
82 pixbuf_toggle_notify,
83 info);
84 icon->last_use_time = g_get_monotonic_time ();
85 schedule_reap_cache ();
86 }
87 }
88
89 static void
caja_icon_info_finalize(GObject * object)90 caja_icon_info_finalize (GObject *object)
91 {
92 CajaIconInfo *icon;
93
94 icon = CAJA_ICON_INFO (object);
95
96 if (!icon->sole_owner && icon->pixbuf)
97 {
98 g_object_remove_toggle_ref (G_OBJECT (icon->pixbuf),
99 pixbuf_toggle_notify,
100 icon);
101 }
102
103 if (icon->pixbuf)
104 {
105 g_object_unref (icon->pixbuf);
106 }
107 g_free (icon->attach_points);
108 g_free (icon->display_name);
109 g_free (icon->icon_name);
110
111 G_OBJECT_CLASS (caja_icon_info_parent_class)->finalize (object);
112 }
113
114 static void
caja_icon_info_class_init(CajaIconInfoClass * icon_info_class)115 caja_icon_info_class_init (CajaIconInfoClass *icon_info_class)
116 {
117 GObjectClass *gobject_class;
118
119 gobject_class = (GObjectClass *) icon_info_class;
120
121 gobject_class->finalize = caja_icon_info_finalize;
122
123 }
124
125 CajaIconInfo *
caja_icon_info_new_for_pixbuf(GdkPixbuf * pixbuf,gint scale)126 caja_icon_info_new_for_pixbuf (GdkPixbuf *pixbuf,
127 gint scale)
128 {
129 CajaIconInfo *icon;
130
131 icon = g_object_new (CAJA_TYPE_ICON_INFO, NULL);
132
133 if (pixbuf)
134 {
135 icon->pixbuf = g_object_ref (pixbuf);
136 }
137
138 icon->orig_scale = scale;
139
140 return icon;
141 }
142
143 static CajaIconInfo *
caja_icon_info_new_for_icon_info(GtkIconInfo * icon_info,gint scale)144 caja_icon_info_new_for_icon_info (GtkIconInfo *icon_info,
145 gint scale)
146 {
147 CajaIconInfo *icon;
148 GdkPoint *points;
149 gint n_points;
150 const char *filename;
151 char *basename;
152
153 icon = g_object_new (CAJA_TYPE_ICON_INFO, NULL);
154
155 icon->pixbuf = gtk_icon_info_load_icon (icon_info, NULL);
156
157 icon->got_embedded_rect = gtk_icon_info_get_embedded_rect (icon_info,
158 &icon->embedded_rect);
159
160 if (gtk_icon_info_get_attach_points (icon_info, &points, &n_points))
161 {
162 icon->n_attach_points = n_points;
163 icon->attach_points = points;
164 }
165
166 icon->display_name = g_strdup (gtk_icon_info_get_display_name (icon_info));
167
168 filename = gtk_icon_info_get_filename (icon_info);
169 if (filename != NULL)
170 {
171 char *p;
172
173 basename = g_path_get_basename (filename);
174 p = strrchr (basename, '.');
175 if (p)
176 {
177 *p = 0;
178 }
179 icon->icon_name = basename;
180 }
181
182 icon->orig_scale = scale;
183
184 return icon;
185 }
186
187
188 typedef struct
189 {
190 GIcon *icon;
191 int scale;
192 int size;
193 } IconKey;
194
195 static GHashTable *loadable_icon_cache = NULL;
196 static GHashTable *themed_icon_cache = NULL;
197 static guint reap_cache_timeout = 0;
198
199 #define MICROSEC_PER_SEC ((guint64)1000000L)
200
201 static guint time_now;
202
203 static gboolean
reap_old_icon(gpointer key,gpointer value,gpointer user_info)204 reap_old_icon (gpointer key,
205 gpointer value,
206 gpointer user_info)
207 {
208 CajaIconInfo *icon = value;
209 gboolean *reapable_icons_left = user_info;
210
211 if (icon->sole_owner)
212 {
213 if (time_now - icon->last_use_time > 30 * MICROSEC_PER_SEC)
214 {
215 /* This went unused 30 secs ago. reap */
216 return TRUE;
217 }
218 else
219 {
220 /* We can reap this soon */
221 *reapable_icons_left = TRUE;
222 }
223 }
224
225 return FALSE;
226 }
227
228 static gboolean
reap_cache(gpointer data)229 reap_cache (gpointer data)
230 {
231 gboolean reapable_icons_left;
232
233 reapable_icons_left = TRUE;
234
235 time_now = g_get_monotonic_time ();
236
237 if (loadable_icon_cache)
238 {
239 g_hash_table_foreach_remove (loadable_icon_cache,
240 reap_old_icon,
241 &reapable_icons_left);
242 }
243
244 if (themed_icon_cache)
245 {
246 g_hash_table_foreach_remove (themed_icon_cache,
247 reap_old_icon,
248 &reapable_icons_left);
249 }
250
251 if (reapable_icons_left)
252 {
253 return TRUE;
254 }
255 else
256 {
257 reap_cache_timeout = 0;
258 return FALSE;
259 }
260 }
261
262 static void
schedule_reap_cache(void)263 schedule_reap_cache (void)
264 {
265 if (reap_cache_timeout == 0)
266 {
267 reap_cache_timeout = g_timeout_add_seconds_full (0, 5,
268 reap_cache,
269 NULL, NULL);
270 }
271 }
272
273 void
caja_icon_info_clear_caches(void)274 caja_icon_info_clear_caches (void)
275 {
276 if (loadable_icon_cache)
277 {
278 g_hash_table_remove_all (loadable_icon_cache);
279 }
280
281 if (themed_icon_cache)
282 {
283 g_hash_table_remove_all (themed_icon_cache);
284 }
285 }
286
287 static guint
icon_key_hash(IconKey * key)288 icon_key_hash (IconKey *key)
289 {
290 return g_icon_hash (key->icon) ^ key->size;
291 }
292
293 static gboolean
icon_key_equal(const IconKey * a,const IconKey * b)294 icon_key_equal (const IconKey *a,
295 const IconKey *b)
296 {
297 return a->size == b->size &&
298 a->scale == b->scale &&
299 g_icon_equal (a->icon, b->icon);
300 }
301
302 static IconKey *
icon_key_new(GIcon * icon,int scale,int size)303 icon_key_new (GIcon *icon,
304 int scale,
305 int size)
306 {
307 IconKey *key;
308
309 key = g_slice_new (IconKey);
310 key->icon = g_object_ref (icon);
311 key->size = size;
312
313 return key;
314 }
315
316 static void
icon_key_free(IconKey * key)317 icon_key_free (IconKey *key)
318 {
319 g_object_unref (key->icon);
320 g_slice_free (IconKey, key);
321 }
322
323 CajaIconInfo *
caja_icon_info_lookup(GIcon * icon,int size,int scale)324 caja_icon_info_lookup (GIcon *icon,
325 int size,
326 int scale)
327 {
328 GtkIconTheme *icon_theme;
329 GtkIconInfo *gtkicon_info;
330
331 CajaIconInfo *icon_info;
332
333 icon_theme = gtk_icon_theme_get_default ();
334
335 if (G_IS_LOADABLE_ICON (icon)) {
336 GdkPixbuf *pixbuf;
337 IconKey lookup_key;
338 IconKey *key;
339 GInputStream *stream;
340
341 if (loadable_icon_cache == NULL) {
342 loadable_icon_cache = g_hash_table_new_full ((GHashFunc) icon_key_hash,
343 (GEqualFunc) icon_key_equal,
344 (GDestroyNotify) icon_key_free,
345 (GDestroyNotify) g_object_unref);
346 }
347
348 lookup_key.icon = icon;
349 lookup_key.scale = scale;
350 lookup_key.size = size * scale;
351
352 icon_info = g_hash_table_lookup (loadable_icon_cache, &lookup_key);
353 if (icon_info)
354 {
355 return g_object_ref (icon_info);
356 }
357
358 pixbuf = NULL;
359 stream = g_loadable_icon_load (G_LOADABLE_ICON (icon),
360 size * scale,
361 NULL, NULL, NULL);
362 if (stream)
363 {
364 pixbuf = gdk_pixbuf_new_from_stream_at_scale (stream,
365 size * scale, size * scale,
366 TRUE,
367 NULL, NULL);
368 g_input_stream_close (stream, NULL, NULL);
369 g_object_unref (stream);
370 }
371
372 if (!pixbuf) {
373 gtkicon_info = gtk_icon_theme_lookup_icon_for_scale (icon_theme,
374 "text-x-generic",
375 size,
376 scale,
377 GTK_ICON_LOOKUP_FORCE_SIZE);
378 pixbuf = gtk_icon_info_load_icon (gtkicon_info, NULL);
379 }
380
381
382 icon_info = caja_icon_info_new_for_pixbuf (pixbuf, scale);
383
384 key = icon_key_new (icon, scale, size);
385 g_hash_table_insert (loadable_icon_cache, key, icon_info);
386 g_clear_object (&pixbuf);
387
388 return g_object_ref (icon_info);
389 } else {
390 IconKey lookup_key;
391 IconKey *key;
392 if (themed_icon_cache == NULL) {
393 themed_icon_cache = g_hash_table_new_full ((GHashFunc) icon_key_hash,
394 (GEqualFunc) icon_key_equal,
395 (GDestroyNotify) icon_key_free,
396 (GDestroyNotify) g_object_unref);
397 }
398 lookup_key.icon = icon;
399 lookup_key.scale = scale;
400 lookup_key.size = size;
401
402 icon_info = g_hash_table_lookup (themed_icon_cache, &lookup_key);
403 if (icon_info) {
404 return g_object_ref (icon_info);
405 }
406
407 gtkicon_info = NULL;
408
409 gtkicon_info = gtk_icon_theme_lookup_by_gicon_for_scale (icon_theme,
410 icon,
411 size,
412 scale,
413 GTK_ICON_LOOKUP_FORCE_SIZE);
414
415 if (!gtkicon_info) {
416 gtkicon_info = gtk_icon_theme_lookup_icon_for_scale (icon_theme,
417 "text-x-generic",
418 size,
419 scale,
420 GTK_ICON_LOOKUP_FORCE_SIZE);
421 }
422
423 icon_info = caja_icon_info_new_for_icon_info (gtkicon_info, scale);
424 g_object_unref (gtkicon_info);
425
426 key = icon_key_new (icon,scale, size);
427 g_hash_table_insert (themed_icon_cache, key, icon_info);
428
429 return g_object_ref (icon_info);
430 }
431
432 }
433
434 CajaIconInfo *
caja_icon_info_lookup_from_name(const char * name,int size,int scale)435 caja_icon_info_lookup_from_name (const char *name,
436 int size,
437 int scale)
438 {
439 GIcon *icon;
440 CajaIconInfo *info;
441
442 icon = g_themed_icon_new (name);
443 info = caja_icon_info_lookup (icon, size, scale);
444 g_object_unref (icon);
445 return info;
446 }
447
448 CajaIconInfo *
caja_icon_info_lookup_from_path(const char * path,int size,int scale)449 caja_icon_info_lookup_from_path (const char *path,
450 int size,
451 int scale)
452 {
453 GFile *icon_file;
454 GIcon *icon;
455 CajaIconInfo *info;
456
457 icon_file = g_file_new_for_path (path);
458 icon = g_file_icon_new (icon_file);
459 info = caja_icon_info_lookup (icon, size, scale);
460 g_object_unref (icon);
461 g_object_unref (icon_file);
462 return info;
463 }
464
465 GdkPixbuf *
caja_icon_info_get_pixbuf_nodefault(CajaIconInfo * icon)466 caja_icon_info_get_pixbuf_nodefault (CajaIconInfo *icon)
467 {
468 GdkPixbuf *res;
469
470 if (icon->pixbuf == NULL)
471 {
472 res = NULL;
473 }
474 else
475 {
476 res = g_object_ref (icon->pixbuf);
477
478 if (icon->sole_owner)
479 {
480 icon->sole_owner = FALSE;
481 g_object_add_toggle_ref (G_OBJECT (res),
482 pixbuf_toggle_notify,
483 icon);
484 }
485 }
486
487 return res;
488 }
489
490 cairo_surface_t *
caja_icon_info_get_surface_nodefault(CajaIconInfo * icon)491 caja_icon_info_get_surface_nodefault (CajaIconInfo *icon)
492 {
493 GdkPixbuf *pixbuf;
494 cairo_surface_t *surface;
495
496 pixbuf = caja_icon_info_get_pixbuf_nodefault (icon);
497 surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, icon->orig_scale, NULL);
498 g_object_unref (pixbuf);
499
500 return surface;
501 }
502
503 GdkPixbuf *
caja_icon_info_get_pixbuf(CajaIconInfo * icon)504 caja_icon_info_get_pixbuf (CajaIconInfo *icon)
505 {
506 GdkPixbuf *res;
507
508 res = caja_icon_info_get_pixbuf_nodefault (icon);
509 if (res == NULL)
510 {
511 res = gdk_pixbuf_new_from_data (caja_default_file_icon,
512 GDK_COLORSPACE_RGB,
513 TRUE,
514 8,
515 caja_default_file_icon_width,
516 caja_default_file_icon_height,
517 caja_default_file_icon_width * 4, /* stride */
518 NULL, /* don't destroy info */
519 NULL);
520 }
521
522 return res;
523 }
524
525 cairo_surface_t *
caja_icon_info_get_surface(CajaIconInfo * icon)526 caja_icon_info_get_surface (CajaIconInfo *icon)
527 {
528 GdkPixbuf *pixbuf;
529 cairo_surface_t *surface;
530
531 pixbuf = caja_icon_info_get_pixbuf (icon);
532 surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, icon->orig_scale, NULL);
533 g_object_unref (pixbuf);
534
535 return surface;
536 }
537
538 GdkPixbuf *
caja_icon_info_get_pixbuf_nodefault_at_size(CajaIconInfo * icon,gsize forced_size)539 caja_icon_info_get_pixbuf_nodefault_at_size (CajaIconInfo *icon,
540 gsize forced_size)
541 {
542 GdkPixbuf *pixbuf, *scaled_pixbuf;
543 int w, h, s;
544 double scale;
545
546 pixbuf = caja_icon_info_get_pixbuf_nodefault (icon);
547
548 if (pixbuf == NULL)
549 return NULL;
550
551 w = gdk_pixbuf_get_width (pixbuf) / icon->orig_scale;
552 h = gdk_pixbuf_get_height (pixbuf) / icon->orig_scale;
553 s = MAX (w, h);
554 if (s == forced_size)
555 {
556 return pixbuf;
557 }
558
559 scale = (double)forced_size / s;
560 scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf,
561 w * scale, h * scale,
562 GDK_INTERP_BILINEAR);
563 g_object_unref (pixbuf);
564 return scaled_pixbuf;
565 }
566
567 cairo_surface_t *
caja_icon_info_get_surface_nodefault_at_size(CajaIconInfo * icon,gsize forced_size)568 caja_icon_info_get_surface_nodefault_at_size (CajaIconInfo *icon,
569 gsize forced_size)
570 {
571 GdkPixbuf *pixbuf;
572 cairo_surface_t *surface;
573
574 pixbuf = caja_icon_info_get_pixbuf_nodefault_at_size (icon, forced_size);
575 /*catch the case of caja_icon_info_get_pixbuf_nodefault_at_size returning NULL */
576 if (!pixbuf)
577 return NULL;
578 surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, icon->orig_scale, NULL);
579 g_object_unref (pixbuf);
580
581 return surface;
582 }
583
584 GdkPixbuf *
caja_icon_info_get_pixbuf_at_size(CajaIconInfo * icon,gsize forced_size)585 caja_icon_info_get_pixbuf_at_size (CajaIconInfo *icon,
586 gsize forced_size)
587 {
588 GdkPixbuf *pixbuf, *scaled_pixbuf;
589 int w, h, s;
590 double scale;
591
592 pixbuf = caja_icon_info_get_pixbuf (icon);
593
594 if (pixbuf == NULL)
595 return NULL;
596
597 w = gdk_pixbuf_get_width (pixbuf) / icon->orig_scale;
598 h = gdk_pixbuf_get_height (pixbuf) / icon->orig_scale;
599 s = MAX (w, h);
600 if (s == forced_size)
601 {
602 return pixbuf;
603 }
604
605 scale = (double)forced_size / s;
606 scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf,
607 w * scale, h * scale,
608 GDK_INTERP_BILINEAR);
609 g_object_unref (pixbuf);
610 return scaled_pixbuf;
611 }
612
613 cairo_surface_t *
caja_icon_info_get_surface_at_size(CajaIconInfo * icon,gsize forced_size)614 caja_icon_info_get_surface_at_size (CajaIconInfo *icon,
615 gsize forced_size)
616 {
617 GdkPixbuf *pixbuf;
618 cairo_surface_t *surface;
619
620 pixbuf = caja_icon_info_get_pixbuf_at_size (icon, forced_size);
621 surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, icon->orig_scale, NULL);
622 g_object_unref (pixbuf);
623
624 return surface;
625 }
626
627 gboolean
caja_icon_info_get_embedded_rect(CajaIconInfo * icon,GdkRectangle * rectangle)628 caja_icon_info_get_embedded_rect (CajaIconInfo *icon,
629 GdkRectangle *rectangle)
630 {
631 *rectangle = icon->embedded_rect;
632 return icon->got_embedded_rect;
633 }
634
635 gboolean
caja_icon_info_get_attach_points(CajaIconInfo * icon,GdkPoint ** points,gint * n_points)636 caja_icon_info_get_attach_points (CajaIconInfo *icon,
637 GdkPoint **points,
638 gint *n_points)
639 {
640 *n_points = icon->n_attach_points;
641 *points = icon->attach_points;
642 return icon->n_attach_points != 0;
643 }
644
caja_icon_info_get_display_name(CajaIconInfo * icon)645 const char* caja_icon_info_get_display_name(CajaIconInfo* icon)
646 {
647 return icon->display_name;
648 }
649
caja_icon_info_get_used_name(CajaIconInfo * icon)650 const char* caja_icon_info_get_used_name(CajaIconInfo* icon)
651 {
652 return icon->icon_name;
653 }
654
655 /* Return nominal icon size for given zoom level.
656 * @zoom_level: zoom level for which to find matching icon size.
657 *
658 * Return value: icon size between CAJA_ICON_SIZE_SMALLEST and
659 * CAJA_ICON_SIZE_LARGEST, inclusive.
660 */
661 guint
caja_get_icon_size_for_zoom_level(CajaZoomLevel zoom_level)662 caja_get_icon_size_for_zoom_level (CajaZoomLevel zoom_level)
663 {
664 switch (zoom_level)
665 {
666 case CAJA_ZOOM_LEVEL_SMALLEST:
667 return CAJA_ICON_SIZE_SMALLEST;
668 case CAJA_ZOOM_LEVEL_SMALLER:
669 return CAJA_ICON_SIZE_SMALLER;
670 case CAJA_ZOOM_LEVEL_SMALL:
671 return CAJA_ICON_SIZE_SMALL;
672 case CAJA_ZOOM_LEVEL_STANDARD:
673 return CAJA_ICON_SIZE_STANDARD;
674 case CAJA_ZOOM_LEVEL_LARGE:
675 return CAJA_ICON_SIZE_LARGE;
676 case CAJA_ZOOM_LEVEL_LARGER:
677 return CAJA_ICON_SIZE_LARGER;
678 case CAJA_ZOOM_LEVEL_LARGEST:
679 return CAJA_ICON_SIZE_LARGEST;
680 }
681 g_return_val_if_reached (CAJA_ICON_SIZE_STANDARD);
682 }
683
684 float
caja_get_relative_icon_size_for_zoom_level(CajaZoomLevel zoom_level)685 caja_get_relative_icon_size_for_zoom_level (CajaZoomLevel zoom_level)
686 {
687 return (float)caja_get_icon_size_for_zoom_level (zoom_level) / CAJA_ICON_SIZE_STANDARD;
688 }
689
690 guint
caja_icon_get_larger_icon_size(guint size)691 caja_icon_get_larger_icon_size (guint size)
692 {
693 if (size < CAJA_ICON_SIZE_SMALLEST)
694 {
695 return CAJA_ICON_SIZE_SMALLEST;
696 }
697 if (size < CAJA_ICON_SIZE_SMALLER)
698 {
699 return CAJA_ICON_SIZE_SMALLER;
700 }
701 if (size < CAJA_ICON_SIZE_SMALL)
702 {
703 return CAJA_ICON_SIZE_SMALL;
704 }
705 if (size < CAJA_ICON_SIZE_STANDARD)
706 {
707 return CAJA_ICON_SIZE_STANDARD;
708 }
709 if (size < CAJA_ICON_SIZE_LARGE)
710 {
711 return CAJA_ICON_SIZE_LARGE;
712 }
713 if (size < CAJA_ICON_SIZE_LARGER)
714 {
715 return CAJA_ICON_SIZE_LARGER;
716 }
717 return CAJA_ICON_SIZE_LARGEST;
718 }
719
720 guint
caja_icon_get_smaller_icon_size(guint size)721 caja_icon_get_smaller_icon_size (guint size)
722 {
723 if (size > CAJA_ICON_SIZE_LARGEST)
724 {
725 return CAJA_ICON_SIZE_LARGEST;
726 }
727 if (size > CAJA_ICON_SIZE_LARGER)
728 {
729 return CAJA_ICON_SIZE_LARGER;
730 }
731 if (size > CAJA_ICON_SIZE_LARGE)
732 {
733 return CAJA_ICON_SIZE_LARGE;
734 }
735 if (size > CAJA_ICON_SIZE_STANDARD)
736 {
737 return CAJA_ICON_SIZE_STANDARD;
738 }
739 if (size > CAJA_ICON_SIZE_SMALL)
740 {
741 return CAJA_ICON_SIZE_SMALL;
742 }
743 if (size > CAJA_ICON_SIZE_SMALLER)
744 {
745 return CAJA_ICON_SIZE_SMALLER;
746 }
747 return CAJA_ICON_SIZE_SMALLEST;
748 }
749
750 gint
caja_get_icon_size_for_stock_size(GtkIconSize size)751 caja_get_icon_size_for_stock_size (GtkIconSize size)
752 {
753 gint w, h;
754
755 if (gtk_icon_size_lookup (size, &w, &h))
756 {
757 return MAX (w, h);
758 }
759 return CAJA_ZOOM_LEVEL_STANDARD;
760 }
761
762
763 guint
caja_icon_get_emblem_size_for_icon_size(guint size)764 caja_icon_get_emblem_size_for_icon_size (guint size)
765 {
766 if (size >= 96)
767 return 48;
768 if (size >= 64)
769 return 32;
770 if (size >= 48)
771 return 24;
772 if (size >= 24)
773 return 16;
774 if (size >= 16)
775 return 12;
776
777 return 0; /* no emblems for smaller sizes */
778 }
779
780 gboolean
caja_icon_theme_can_render(GThemedIcon * icon)781 caja_icon_theme_can_render (GThemedIcon *icon)
782 {
783 GtkIconTheme *icon_theme;
784 const gchar * const *names;
785 gint idx;
786
787 names = g_themed_icon_get_names (icon);
788
789 icon_theme = gtk_icon_theme_get_default ();
790
791 for (idx = 0; names[idx] != NULL; idx++) {
792 if (gtk_icon_theme_has_icon (icon_theme, names[idx])) {
793 return TRUE;
794 }
795 }
796
797 return FALSE;
798 }
799
800 GIcon *
caja_user_special_directory_get_gicon(GUserDirectory directory)801 caja_user_special_directory_get_gicon (GUserDirectory directory)
802 {
803
804 #define ICON_CASE(x) \
805 case G_USER_DIRECTORY_ ## x:\
806 return g_themed_icon_new (CAJA_ICON_FOLDER_ ## x);
807
808 switch (directory) {
809
810 ICON_CASE (DESKTOP);
811 ICON_CASE (DOCUMENTS);
812 ICON_CASE (DOWNLOAD);
813 ICON_CASE (MUSIC);
814 ICON_CASE (PICTURES);
815 ICON_CASE (PUBLIC_SHARE);
816 ICON_CASE (TEMPLATES);
817 ICON_CASE (VIDEOS);
818
819 default:
820 return g_themed_icon_new ("folder");
821 }
822
823 #undef ICON_CASE
824 }
825