1 #ifdef COPYRIGHT_INFORMATION
2 #include "gplv3.h"
3 #endif
4
5
6 static
7 GdkPixbuf *
8 get_pixbuf (const gchar * key, gint size, gboolean replace_pixbuf);
9
10 static pthread_mutex_t lite_hash_mutex = PTHREAD_MUTEX_INITIALIZER;
11
12 // internal hash record structure
13 static GHashTable *lite_hash = NULL;
14 static GHashTable *lite_type_hash = NULL;
15 static GHashTable *lite_key_hash = NULL;
16
17 typedef struct composite_t{
18 const gchar *sub_id;
19 const gchar *where;
20 double scale_factor;
21 gint overall_alpha;
22 }composite_t;
23
24
25
26 static void
free_pixbuf(void * data)27 free_pixbuf(void *data){
28 GdkPixbuf *pixbuf = data;
29 if (pixbuf && !G_IS_OBJECT (pixbuf)) {
30 DBG("This should not happen: pixbuf is not a pixbuf\n");
31 } else {
32 g_object_unref (pixbuf);
33 }
34 }
35
36
37 typedef struct lite_t {
38 gchar *id;
39 gchar *type;
40 gchar *icon;
41 guchar red;
42 guchar green;
43 guchar blue;
44 } lite_t;
45
46 // We could read these from an xml file...
47 // To add a new ad hoc icon, first define the lite key to use to associate
48 // the mimetype to the litetype. Then define the lite type (lite_t) with
49 // the values you wish. The type (translated item) should be the same as
50 // whatever is after the / or - in the lite type. This will be the tag
51 // that shows up (translated).
52 lite_t lite_v[]={
53 {"lite/regular", NULL, NULL, 0xff, 0xff, 0xff},
54 {"lite/image", N_("image"), "xffm/emblem_image", 0xff, 0xcc, 0xff},
55 {"lite/Audio", N_("Audio"), "xffm/emblem_music", 0, 0xff, 0xff},
56 {"lite/Video", N_("Video"), "xffm/emblem_video", 0xff, 0xff, 0},
57 {"lite/office", N_("office"), "xffm/emblem_oo", 0xff, 0xff, 0xff},
58 {"lite/chemical", N_("chemical"), "xffm/emblem_science", 0xff, 0xff, 0xff},
59 {"lite/lyx", N_("lyx"), "xffm/emblem_math", 0xaa, 0xaa, 0xff},
60 {"lite/tex", N_("tex"), "xffm/emblem_math", 0xff, 0xff, 0xff},
61 {"lite/text", N_("text"), "xffm/emblem_text", 0xff, 0xff, 0xff},
62 {"lite/text-log", N_("log"), "xffm/emblem_bookmark", 0xff, 0xff, 0xff},
63 {"lite/text-readme", N_("readme"), "xffm/emblem_star", 0xff, 0xff, 0xff},
64 {"lite/text-credits", N_("credits"), "xffm/emblem_star", 0xff, 0xff, 0xff},
65 {"lite/text-authors", N_("authors"), "xffm/emblem_user", 0xff, 0xff, 0xff},
66 {"lite/text-install", N_("install"), "xffm/emblem_important", 0xff, 0xff, 0xff},
67 {"lite/text-info", N_("info"), "xffm/emblem_important", 0xff, 0xff, 0xff},
68 {"lite/text-html", N_("html"), "xffm/emblem_www", 0xff, 0xff, 0xff},
69 {"lite/text-chdr", N_("chdr"), "xffm/emblem_text", 0xee, 0xd6, 0x80},
70 {"lite/text-c++hdr", N_("c++hdr"), "xffm/emblem_text", 0xee, 0xd6, 0x80},
71 {"lite/text-csrc", N_("csrc"), "xffm/emblem_text", 0x88, 0x7f, 0xa3},
72 {"lite/text-c++", N_("c++"), "xffm/emblem_text", 0x88, 0x7f, 0xa3},
73 {"lite/application", N_("App"), "xffm/emblem_application", 0xdd, 0xdd, 0xff},
74 {"lite/graphics", N_("graphics"), "xffm/emblem_graphics", 0xff, 0xff, 0xff},
75 {"lite/pgp", N_("pgp"), "xffm/emblem_lock", 0x88, 0x88, 0x88},
76 {"lite/trash", N_("trash"), "xffm/emblem_bak", 0x22, 0x22, 0x22},
77 {"lite/pdf", N_("pdf"), "xffm/emblem_pdf", 0xaa, 0xdd, 0xcc},
78 {"lite/ps", N_("ps"), "xffm/emblem_print", 0xaa, 0xdd, 0xcc},
79 {"lite/msoffice", N_("msoffice"), "xffm/emblem_msoffice", 0x44, 0x44, 0x44},
80 {"lite/package", N_("package"), "xffm/emblem_package", 0xaa, 0, 0},
81 {"lite/executable", N_("executable"), "xffm/emblem_exec", 0xaa, 0xff, 0xaa},
82 {"lite/script", N_("script"), "xffm/emblem_script", 0xaa, 0xff, 0xaa},
83 {"lite/core", N_("core"), "xffm/emblem_core", 0xaa, 0xaa, 0xaa},
84 {NULL,NULL,NULL, 0,0,0}
85 };
86
87 gchar *lite_keys[] = {
88 //"image/jpeg", "lite/image",
89
90 "text/x-tex", "lite/tex",
91 "text/x-log", "lite/text-log",
92 "text/x-readme", "lite/text-readme",
93 "text/x-chdr", "lite/text-chdr",
94 "text/x-c++hdr", "lite/text-c++hdr",
95 "text/x-c", "lite/text-csrc",
96 "text/x-c++", "lite/text-c++",
97 "text/x-c++src", "lite/text-c++",
98 "text/x-csrc", "lite/text-csrc",
99 "text/x-credits", "lite/text-credits",
100 "text/x-authors", "lite/text-authors",
101 "text/x-install", "lite/text-install",
102 "text/x-info", "lite/text-info",
103 "text/html", "lite/text-html",
104 "application/x-lyx", "lite/lyx",
105 "application/x-trash", "lite/trash",
106 "application/pdf", "lite/pdf",
107 "application/x-bzpdf", "lite/pdf",
108 "application/x-gzpdf", "lite/pdf",
109
110 "application/x-dia-diagram", "lite/graphics",
111 "application/pgp", "lite/pgp",
112 "application/pgp-encrypted", "lite/pgp",
113
114 "application/x-core", "lite/core",
115 "application/x-coredump", "lite/core",
116
117 "application/postscript", "lite/ps",
118 "application/x-bzpostscript", "lite/ps",
119 "application/x-gzpostscript", "lite/ps",
120
121 "application/msword", "lite/msoffice",
122 "application/ms-powerpoint", "lite/msoffice",
123 "application/ms-excel", "lite/msoffice",
124 "application/ms-project", "lite/msoffice",
125 "application/msword-template", "lite/msoffice",
126 "application/vnd.ms-powerpoint", "lite/msoffice",
127 "application/vnd.ms-excel", "lite/msoffice",
128 "application/vnd.ms-project", "lite/msoffice",
129 "application/msword-template", "lite/msoffice",
130 "application/vnd.msword", "lite/msoffice",
131
132 "application/x-tar", "lite/package",
133 "application/x-compress", "lite/package",
134 "application/x-compressed-tar", "lite/package",
135 "application/x-arj", "lite/package",
136 "application/x-lha", "lite/package",
137 "application/x-lzma", "lite/package",
138 "application/zip", "lite/package",
139 "application/x-gzip", "lite/package",
140 "application/x-lzip", "lite/package",
141 "application/x-cbz", "lite/package",
142 "application/x-cbr", "lite/package",
143 "application/x-xz", "lite/package",
144 "application/x-xz-compressed-tar", "lite/package",
145 "application/x-bzip", "lite/package",
146 "application/x-bzip2", "lite/package",
147 "application/x-bzip-compressed-tar", "lite/package",
148 "application/x-deb", "lite/package",
149 "application/x-rpm", "lite/package",
150 "application/x-java-archive", "lite/package",
151 "application/x-rar", "lite/package",
152 "application/x-ace", "lite/package",
153 "application/x-zoo", "lite/package",
154 "application/x-cpio", "lite/package",
155 "application/x-cpio-compressed", "lite/package",
156 "application/x-7z-compressed", "lite/package",
157
158 "application/x-shellscript", "lite/script",
159 "application/x-csh", "lite/script",
160 "text/x-csh", "lite/script",
161 "text/x-sh", "lite/script",
162 "text/x-shellscript", "lite/script",
163 "text/x-python", "lite/script",
164 "application/javascript", "lite/script",
165 "application/sieve", "lite/script",
166 "application/x-awk", "lite/script",
167 "application/x-m4", "lite/script",
168 "application/x-markaby", "lite/script",
169 "application/x-perl", "lite/script",
170 "application/x-php", "lite/script",
171 "application/x-ruby", "lite/script",
172 "application/x-setupscript", "lite/script",
173 "text/javascript", "lite/script",
174 "text/scriptlet", "lite/script",
175 "text/x-dcl", "lite/script",
176 "text/x-lua", "lite/script",
177 "text/x-matlab", "lite/script",
178 "text/x-tcl", "lite/script",
179 NULL, NULL
180 };
181
182
183 static void
init_lite_hash()184 init_lite_hash () {
185 // g_once init
186 static gsize initialized = 0;
187 if (g_once_init_enter (&initialized)){
188 lite_hash = g_hash_table_new_full (g_str_hash, g_str_equal,g_free, free_pixbuf);
189 lite_type_hash = g_hash_table_new (g_str_hash, g_str_equal);
190 lite_key_hash = g_hash_table_new (g_str_hash, g_str_equal);
191 lite_t *lite_type_p = lite_v;
192 for (;lite_type_p && lite_type_p->id; lite_type_p++){
193 g_hash_table_insert(lite_type_hash, lite_type_p->id, lite_type_p);
194 }
195 gchar **cp = lite_keys;
196 for (;cp && *cp; cp+=2){
197 g_hash_table_insert(lite_key_hash, cp[0], cp[1]);
198 }
199 g_once_init_leave (&initialized, 1);
200 }
201 return;
202 }
203
204
205
206
207 static void *
pixbuf_from_gtkid_f(void * data)208 pixbuf_from_gtkid_f(void *data){
209 void **arg = data;
210 gchar *id = arg[0];
211 gint size = GPOINTER_TO_INT(arg[1]);
212 GdkPixbuf *pixbuf = NULL;
213
214 gchar *file = g_strdup_printf("%s/icons/rfm/scalable/stock/%s.svg",
215 PACKAGE_DATA_DIR, id);
216 NOOP(stderr, "trying: \"%s\"\n", file);
217 if (!g_file_test(file, G_FILE_TEST_EXISTS)) {
218 fprintf(stderr, "Failed to get pixbuf from %s-->%s\n", id, file);
219 g_free(file);
220 file = g_strdup_printf("%s/icons/rfm/scalable/emblems/emblem-%s.svg",
221 PACKAGE_DATA_DIR, id);
222 NOOP(stderr, "now trying: \"%s\"\n", file);
223 if (!g_file_test(file, G_FILE_TEST_EXISTS)){
224 g_free(file);
225 file = NULL;
226 }
227 }
228 if (file){
229 pixbuf = rfm_pixbuf_new_from_file(file, size, size);
230 }
231
232
233 g_free(file);
234 return pixbuf;
235 }
236
237 GdkPixbuf *
pixbuf_from_gtkid(const gchar * id,gint size)238 pixbuf_from_gtkid(const gchar * id, gint size){
239 if (!id) return NULL;
240 GdkPixbuf *pixbuf = NULL;
241 void *arg[] = {(void *)id, GINT_TO_POINTER(size)};
242 arg[0] = g_strdup(id);
243 arg[1] = GINT_TO_POINTER(size);
244
245 pixbuf = pixbuf_from_gtkid_f(arg);
246
247 if (pixbuf) g_object_ref(pixbuf);
248 return pixbuf;
249 }
250
251 static const gchar *
get_mask_color(const gchar * id,guchar * red,guchar * green,guchar * blue,gchar ** tpath)252 get_mask_color(const gchar *id, guchar *red, guchar *green, guchar *blue, gchar **tpath){
253 // 30 black:
254 // 31 red: bright red, tar files
255 // 32 green: document files; bright: executables;
256 // 33 yellow:
257 // 34 blue: directories;
258 // 35 magenta: bright: images;
259 // 36 cyan: audio; bright: symlinks;
260 // 37 white
261
262 lite_t *lite_type_p = NULL;
263
264 const gchar *key = "lite/regular";
265
266 if (strncmp(id,"image/", strlen("image/"))==0)
267 key = "lite/image";
268 else if (strncmp(id,"audio/", strlen("audio/"))==0)
269 key = "lite/Audio";
270 else if (strncmp(id,"video/", strlen("video/"))==0)
271 key = "lite/Video";
272 else if (strstr(id,"opendocument") || strstr(id,"officedocument") || strstr(id,"application/rtf")
273 ||strstr(id,"vnd.sun.xml"))
274 key = "lite/office";
275 else if (strstr(id,"abobe"))
276 key = "lite/graphics";
277 else if (strncmp(id,"text/", strlen("text/"))==0){
278 key = g_hash_table_lookup(lite_key_hash, id);
279 if (!key) key = "lite/text";
280
281 } else if (strncmp(id,"application/", strlen("application/"))==0){
282 key = g_hash_table_lookup(lite_key_hash, id);
283 if (!key) key = "lite/application";
284 }
285 NOOP (stderr, "+++ getting lite id for %s: %s\n", id, key);
286
287 lite_type_p = g_hash_table_lookup(lite_type_hash, key);
288
289 if (!lite_type_p) {
290 lite_type_p = g_hash_table_lookup(lite_type_hash, "lite/regular");
291 }
292
293
294 if (tpath && lite_type_p->icon) {
295 if (!strstr(lite_type_p->icon, "xffm/emblem_")){
296 DBG("get_mask_color(): incorrect lite icon specification: %s\n", lite_type_p->icon);
297 } else {
298 gboolean gtk_theme = (getenv("RFM_USE_GTK_ICON_THEME") &&
299 strlen(getenv("RFM_USE_GTK_ICON_THEME")));
300 if (gtk_theme) {
301 *tpath = ICON_get_filename_from_id(lite_type_p->icon);
302 } else {
303 gchar *icon = g_strdup(lite_type_p->icon + strlen("xffm/emblem_"));
304 *tpath = g_strdup_printf("%s/icons/rfm/scalable/emblems/emblem-%s.svg",
305 PACKAGE_DATA_DIR, icon);
306 NOOP(stderr, "%s->%s\n", icon, file);
307 g_free(icon);
308 }
309 }
310 }
311 if (red) *red = lite_type_p->red;
312 if (green) *green = lite_type_p->green;
313 if (blue) *blue = lite_type_p->blue;
314
315 return lite_type_p->id;
316 }
317
318 static void
add_label_pixbuf(cairo_t * pixbuf_context,GdkPixbuf * pixbuf,const gchar * lite_id,gint size)319 add_label_pixbuf(cairo_t *pixbuf_context,
320 GdkPixbuf *pixbuf,
321 const gchar *lite_id,
322 gint size){
323 rfm_global_t *rfm_global_p = rfm_global();
324 if (!rfm_global_p) return;
325 // Skip regular icons
326 if (strcmp(lite_id, "lite/regular")==0) return;
327 // Insert text into pixbuf
328 gint x = 0;
329 gint y = 0;
330 const gchar *text_size = NULL;
331 switch(size) {
332 case SMALL_ICON_SIZE: text_size="xx-small"; break;
333 case MEDIUM_ICON_SIZE: text_size="x-small"; break;
334 case BIG_ICON_SIZE: text_size="medium"; break;
335 }
336 if (!text_size) return ;
337 GdkPixbuf *t_pixbuf = NULL;
338 const gchar *icon_text;
339 if (strchr(lite_id,'.')) icon_text = strrchr(lite_id,'.')+1;
340 else if (strchr(lite_id,'-')) icon_text = strrchr(lite_id,'-')+1;
341 else icon_text = strrchr(lite_id,'/')+1;
342 const gchar *color = "white";
343 gchar *layout_text = g_strdup_printf("<span foreground=\"black\" background=\"%s\" size=\"%s\">%s </span>", color, text_size, _(icon_text));
344 PangoLayout *layout =
345 gtk_widget_create_pango_layout (rfm_global_p->window, NULL);
346 pango_layout_set_markup(layout, layout_text, -1);
347 g_free(layout_text);
348 PangoRectangle logical_rect;
349 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
350 x = gdk_pixbuf_get_width(pixbuf) - logical_rect.width-2;
351 y = gdk_pixbuf_get_height(pixbuf) - logical_rect.height-2;
352 if (x < 0) x = 0;
353 if (y < 0) y = 0;
354 if (logical_rect.width > gdk_pixbuf_get_width(pixbuf)-1)
355 logical_rect.width = gdk_pixbuf_get_width(pixbuf)-1;
356 if (logical_rect.height > gdk_pixbuf_get_height(pixbuf)-1)
357 logical_rect.height = gdk_pixbuf_get_height(pixbuf)-1;
358
359 //cairo_set_source_rgba(pixbuf_context, 1.0, 0.0, 0.0, 0.75);
360 //
361 t_pixbuf =
362 gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, logical_rect.width+2, logical_rect.height+2);
363 cairo_t *t_pixbuf_context = pixbuf_cairo_create(t_pixbuf);
364
365 //cairo_set_source_rgba(t_pixbuf_context, 1.0, 1.0, 1.0, 1.0);
366
367 cairo_rectangle(t_pixbuf_context, 0, 0, logical_rect.width+2, logical_rect.height+2);
368 //cairo_fill(t_pixbuf_context);
369 cairo_clip(t_pixbuf_context);
370
371
372 cairo_move_to (t_pixbuf_context, 1, 1);
373
374 cairo_set_source_rgba(t_pixbuf_context, 0, 0, 0, 1.0);
375 //cairo_set_source_rgba(t_pixbuf_context, 0, 0, 0, 0.5);
376 if (PANGO_IS_LAYOUT (layout)) {
377 pango_cairo_show_layout (t_pixbuf_context, layout);
378 g_object_unref(layout);
379 }
380 pixbuf_cairo_destroy(t_pixbuf_context, t_pixbuf);
381
382 if (t_pixbuf) {
383 gdk_cairo_set_source_pixbuf(pixbuf_context, t_pixbuf,x,y);
384 cairo_paint_with_alpha(pixbuf_context, 0.650);
385 g_object_unref(t_pixbuf);
386 }
387
388 return ;
389 }
390
391 static void
add_color_pixbuf(cairo_t * pixbuf_context,GdkPixbuf * pixbuf,guchar red,guchar green,guchar blue)392 add_color_pixbuf(cairo_t *pixbuf_context, GdkPixbuf *pixbuf,
393 guchar red, guchar green, guchar blue){
394 GdkPixbuf *pixbuf_mask = create_pixbuf_mask(pixbuf, red, green, blue);
395 gdk_cairo_set_source_pixbuf(pixbuf_context, pixbuf_mask, 0,0);
396 cairo_paint_with_alpha(pixbuf_context, 0.450);
397 g_object_unref(pixbuf_mask);
398 }
399
400 static void
add_emblem_pixbuf(cairo_t * pixbuf_context,GdkPixbuf * pixbuf,gchar * tpath,gint size)401 add_emblem_pixbuf(cairo_t *pixbuf_context, GdkPixbuf *pixbuf, gchar *tpath, gint size){
402
403 if (tpath && g_file_test(tpath, G_FILE_TEST_EXISTS)){
404 gdouble b = (double) size / 1.618;
405 gint ia = size - floor(b);
406 //gint ia = size/4;
407 GdkPixbuf *tag = rfm_pixbuf_new_from_file(tpath, size/2, size/2);
408 gdk_cairo_set_source_pixbuf(pixbuf_context, tag,ia,size/4);
409 cairo_paint_with_alpha(pixbuf_context, 1.0);
410 //cairo_paint_with_alpha(pixbuf_context, 0.650);
411
412 g_object_unref(tag);
413 }
414 }
415
416 static GdkPixbuf *
ad_hoc_pixbuf(GdkPixbuf * pixbuf,const gchar * id,gint size)417 ad_hoc_pixbuf(GdkPixbuf *pixbuf, const gchar *id, gint size){
418 GdkPixbuf *old_p = pixbuf;
419 pixbuf = rfm_pixbuf_duplicate(old_p);
420 g_object_unref(old_p);
421 g_object_ref(pixbuf);
422 rfm_global_t *rfm_global_p = rfm_global();
423 if (!rfm_global_p) return pixbuf;
424
425
426 #if 10
427
428
429 guchar red, green, blue;
430 gchar *tpath = NULL;
431 const gchar *lite_id = get_mask_color(id, &red, &green, &blue, &tpath);
432
433
434
435 #endif
436 cairo_t *pixbuf_context = pixbuf_cairo_create(pixbuf);
437
438 // This proved necessary in opensuse-12.3,
439 // but not in gentoo nor ubuntu. Go figure...
440 gdk_cairo_set_source_pixbuf(pixbuf_context, pixbuf,0,0);
441 cairo_paint_with_alpha(pixbuf_context, 1.0);
442
443 // Color:
444 add_color_pixbuf(pixbuf_context, pixbuf, red, green, blue);
445
446 // Emblem:
447 add_emblem_pixbuf(pixbuf_context, pixbuf,tpath, size);
448 g_free(tpath);
449
450 // Text:
451 add_label_pixbuf(pixbuf_context, pixbuf, lite_id, size);
452
453
454 // Using the same hash is not correct.
455 // rfm_put_in_pixbuf_hash(lite_id, size, pixbuf);
456 pixbuf_cairo_destroy(pixbuf_context, pixbuf);
457
458 gchar *hash_key = rfm_get_hash_key (lite_id, size);
459 pthread_mutex_lock(&lite_hash_mutex);
460 g_hash_table_replace(lite_hash, hash_key, pixbuf);
461 pthread_mutex_unlock(&lite_hash_mutex);
462
463 return pixbuf;
464 }
465
466 static GdkPixbuf *
try_app_icon(const gchar * id,gint size)467 try_app_icon(const gchar *id, gint size){
468 GdkPixbuf *pixbuf = NULL;
469 // try svg application icons?
470 if (!pixbuf){
471 gchar *fullpath = g_strdup_printf("%s/pixmaps/%s.svg", PACKAGE_DATA_DIR, id);
472 pixbuf = rfm_pixbuf_new_from_file(fullpath, size, size);
473 if (!pixbuf) {
474 DBG("svg application icon not found %s -> %s\n", id, fullpath);
475 g_free(fullpath);
476 fullpath = g_strdup_printf("%s/icons/hicolor/scalable/apps/%s.svg",
477 PACKAGE_DATA_DIR, id);
478 pixbuf = rfm_pixbuf_new_from_file(fullpath, size, size);
479 }
480 if (!pixbuf) DBG("svg application icon not found %s -> %s\n", id, fullpath);
481 g_free(fullpath);
482 }
483 // try png application icons?
484 if (!pixbuf){
485 gchar *fullpath = g_strdup_printf("%s/pixmaps/%s.png", PACKAGE_DATA_DIR, id);
486 pixbuf = rfm_pixbuf_new_from_file(fullpath, size, size);
487 if (!pixbuf) {
488 DBG("png application icon not found %s -> %s\n", id, fullpath);
489 g_free(fullpath);
490 fullpath = g_strdup_printf("%s/icons/hicolor/48x48/apps/%s.png",
491 PACKAGE_DATA_DIR, id);
492 pixbuf = rfm_pixbuf_new_from_file(fullpath, size, size);
493 }
494 if (!pixbuf) DBG("svg application icon not found %s -> %s\n", id, fullpath);
495 g_free(fullpath);
496 }
497 // try xpm application icons?
498 if (!pixbuf){
499 gchar *fullpath = g_strdup_printf("%s/pixmaps/%s.xpm", PACKAGE_DATA_DIR, id);
500 pixbuf = rfm_pixbuf_new_from_file(fullpath, size, size);
501 if (!pixbuf) DBG("png application icon not found %s -> %s\n", id, fullpath);
502 g_free(fullpath);
503 }
504 return pixbuf;
505 }
506
507 static GdkPixbuf *
last_resort_pixbuf(gint size,const gchar * id)508 last_resort_pixbuf(gint size, const gchar *id){
509 NOOP("last_resort_pixbuf: %s\n", id);
510 init_lite_hash();
511 GdkPixbuf *pixbuf = NULL;
512 gchar *tpath = NULL;
513 guchar red, green, blue;
514 const gchar *lite_id = get_mask_color(id, &red, &green, &blue, &tpath);
515 g_free(tpath); // No used... really now?
516 tpath = NULL;
517 if (!lite_id) {
518 DBG("Could not retrieve lite_id\n");
519 return NULL;
520 }
521
522 gchar *hash_key = rfm_get_hash_key (lite_id, size);
523 pthread_mutex_lock(&lite_hash_mutex);
524 pixbuf = g_hash_table_lookup(lite_hash, hash_key);
525 pthread_mutex_unlock(&lite_hash_mutex);
526 g_free(hash_key);
527
528 if (pixbuf){
529 g_object_ref(pixbuf);
530 return pixbuf;
531 }
532
533 hash_key = rfm_get_hash_key ("lite/regular", size);
534 pthread_mutex_lock(&lite_hash_mutex);
535 pixbuf = g_hash_table_lookup(lite_hash, hash_key);
536 pthread_mutex_unlock(&lite_hash_mutex);
537 g_free(hash_key);
538
539 if (pixbuf) g_object_ref(pixbuf);
540
541 if ( !pixbuf) pixbuf = try_app_icon(id, size);
542
543
544 if (!pixbuf) {
545 gchar *fullpath = g_strdup_printf("%s/icons/rfm/scalable/emblems/emblem-file.svg", PACKAGE_DATA_DIR);
546 pixbuf = rfm_pixbuf_new_from_file(fullpath, size, size);
547 g_free(fullpath);
548 if (pixbuf) {
549 g_object_ref(pixbuf); // refs.
550 hash_key = rfm_get_hash_key ("lite/regular", size);
551 pthread_mutex_lock(&lite_hash_mutex);
552 g_hash_table_replace(lite_hash, hash_key, pixbuf);
553 pthread_mutex_unlock(&lite_hash_mutex);
554 }
555 }
556
557 gboolean gtk_icontheme = (getenv("RFM_USE_GTK_ICON_THEME") && strlen(getenv("RFM_USE_GTK_ICON_THEME")));
558
559 if (gtk_icontheme && !pixbuf) {
560 pixbuf = pixbuf_from_gtkid("file", size); // refs.
561 if (pixbuf) {
562 hash_key = rfm_get_hash_key ("lite/regular", size);
563 pthread_mutex_lock(&lite_hash_mutex);
564 g_hash_table_replace(lite_hash, hash_key, pixbuf);
565 pthread_mutex_unlock(&lite_hash_mutex);
566 }
567 }
568
569 if (!pixbuf){
570 DBG("unable to get lite/regular pixbuf\n");
571 return NULL;
572 }
573
574 if (strcmp(lite_id, "lite/regular")==0)
575 {
576 return pixbuf;
577 }
578
579 // Create ad hoc pixbuf
580 return ad_hoc_pixbuf(pixbuf, id, size);
581
582 }
583
584
585 static
586 gchar *
fallback_icon_path(const gchar * id)587 fallback_icon_path(const gchar * id){
588 gchar *fullpath=NULL;
589 if (strstr(id, "xffm/emblem_")){
590 fullpath = g_strdup_printf("%s/icons/rfm/scalable/emblems/emblem-%s.svg",
591 PACKAGE_DATA_DIR, id+strlen("xffm/emblem_"));
592 }
593 return fullpath;
594 }
595
596
597
598 static GdkPixbuf *
make_pixbuf_from_id(const gchar * id,int size)599 make_pixbuf_from_id (const gchar * id, int size) {
600 GdkPixbuf *pixbuf=NULL;
601 // Short circuit to items in pixmaps directory... (ghack)
602 pixbuf = try_app_icon(id, size);
603 if(pixbuf){
604 g_object_ref(pixbuf);
605 return pixbuf;
606 }
607
608
609 NOOP (stderr, "ICONx:make_pixbuf_from_id: %s\n", id);
610 if(!id || !strlen (id)) return NULL;
611 const gchar *c_key="/compositeC";
612 const gchar *cc_key="/compositeC/";
613 const gchar *ccc_key="compositeC/";
614 const gchar *position="C";
615 gdouble scale_f=1.8;
616 gint overall_alpha=180;
617
618 if (strstr(id, "/compositeC/")){
619 c_key="/compositeC";
620 cc_key="/compositeC/";
621 ccc_key="compositeC/";
622 scale_f=2.2;
623 position="C";
624 overall_alpha=225;
625 }
626 else if (strstr(id, "/compositeX/")){
627 c_key="/compositeX";
628 cc_key="/compositeX/";
629 ccc_key="compositeX/";
630 scale_f=1.0;
631 position="C";
632 overall_alpha=150;
633 }
634 else if (strstr(id, "/compositeNE/")){
635 c_key="/compositeNE";
636 cc_key="/compositeNE/";
637 ccc_key="compositeNE/";
638 scale_f=3.0;
639 position="NE";
640 }
641 else if (strstr(id, "/compositeNW/")){
642 c_key="/compositeNW";
643 cc_key="/compositeNW/";
644 ccc_key="compositeNW/";
645 position="NW";
646 scale_f=3.0;
647 }
648 else if (strstr(id, "/compositeNC/")){
649 c_key="/compositeNC";
650 cc_key="/compositeNC/";
651 ccc_key="compositeNC/";
652 position="NC";
653 scale_f=3.0;
654 }
655 else if (strstr(id, "/compositeSC/")){
656 c_key="/compositeSC";
657 cc_key="/compositeSC/";
658 ccc_key="compositeSC/";
659 position="SC";
660 }
661 else if (strstr(id, "/compositeSW/")){
662 c_key="/compositeSW";
663 cc_key="/compositeSW/";
664 ccc_key="compositeSW/";
665 position="SW";
666 scale_f=1.5;
667 overall_alpha=210;
668 }
669 /*else if (strstr(id, "/compositeHSW/")){
670 c_key="/compositeSW";
671 cc_key="/compositeSW/";
672 ccc_key="compositeSW/";
673 position="SW";
674 scale_f=1.4;
675 overall_alpha=255;
676 }*/
677 else if (strstr(id, "/compositeSE/")){
678 c_key="/compositeSE";
679 cc_key="/compositeSE/";
680 ccc_key="compositeSE/";
681 position="SE";
682 }
683
684 if(strstr (id, c_key)) {
685 gchar *basic_type = g_strdup (id);
686 NOOP (stderr, "composite type = %s\n", id);
687
688 GdkPixbuf *basic_pixbuf;
689 if (strstr (basic_type, c_key)) *(strstr (basic_type, c_key)) = 0;
690 else DBG("make_pixbuf_from_id(): strstr (basic_type, c_key) returns NULL.");
691
692 basic_pixbuf = get_pixbuf (basic_type, size, FALSE); //refs
693 if(!basic_pixbuf){
694 g_free (basic_type);
695 return NULL;
696 }
697 if(strstr (id, cc_key) == NULL) {
698 DBG("incomplete composite specification: %s\n", id);
699 g_object_unref(basic_pixbuf);
700 g_free (basic_type);
701 return NULL;
702 }
703 NOOP(stderr, "duplicating pixbuf for %s: %s\n", basic_type, id);
704 g_free (basic_type);
705
706 GdkPixbuf *composite_pixbuf = rfm_pixbuf_duplicate(basic_pixbuf);
707
708 if (!composite_pixbuf) {
709 g_error("cannot duplicate basic pixbuf for %s\n", id);
710 return basic_pixbuf;
711 }
712 g_object_unref(basic_pixbuf);
713 g_object_ref(composite_pixbuf);
714
715
716 gchar *composite_id = g_strdup(strstr(id, cc_key) + strlen(cc_key));
717
718 // split
719 gint count=0;
720 gchar *p;
721 gchar *comp_id[10];
722 p=comp_id[count]=composite_id;
723 count++;
724 while (strchr(p,'/')){
725 *strchr(p,'/')=0;
726 p += (strlen(p)+1);
727 if (strncmp(p,ccc_key,strlen(ccc_key)!=0)){
728 NOOP(" composite type= %s\n", p);
729 comp_id[count]=p;
730 count++;
731 }
732 }
733 gint j;
734 const gchar *group="xffm";
735 for (j=0; j<count; j++){
736 // Determine the group to which the icon belongs to
737 gchar *groups[]={
738 "application", "audio",
739 "chemical", "image",
740 "inode", "message",
741 "model", "multipart",
742 "text", "video",
743 "x-conference", "x-content",
744 "x-epoc", "x-world",
745 NULL};
746 gchar **pp=groups;
747 for(; pp && *pp; pp++){
748 if (strcmp(comp_id[j],*pp)==0){
749 group=*pp;
750 continue;
751 }
752 }
753 // Don't composite with group names (only with xffm group).
754 if (strcmp(group, comp_id[j])==0) continue;
755 gchar *c_id = NULL;
756 if (!c_id) {
757 // no special position found
758 c_id = g_strdup_printf ("%s/%s", group, comp_id[j]);
759 }
760 NOOP(stderr, "id = %s composite tag=%s\n", id, c_id);
761
762 GdkPixbuf *tag = get_pixbuf (c_id, size, FALSE); //refs
763 if(!tag) {
764 NOOP ("cannot get pixbuf for id: %s\n", c_id);
765 g_free(c_id);
766 g_free(composite_id);
767 return composite_pixbuf;
768 }
769 rfm_insert_pixbuf_tag (tag, composite_pixbuf, position, scale_f, overall_alpha);
770 g_free(c_id);
771 g_object_unref(tag);
772 }
773 g_free(composite_id);
774
775 return composite_pixbuf;
776 }
777
778 gboolean gtk_icontheme = (getenv("RFM_USE_GTK_ICON_THEME") && strlen(getenv("RFM_USE_GTK_ICON_THEME")));
779
780 // hack...
781 if (strcmp(id, "image/png")==0) id = "xffm/emblem_image";
782 if (strcmp(id, "xffm/")==0) id = "xffm/stock_file";
783
784
785
786
787 gchar *file = NULL;
788 if (strcmp(id, _("unknown"))==0) {
789 if (gtk_icontheme) file = ICON_get_filename_from_id ("xffm/stock_file");
790 else file = ICON_get_filename_from_id ("xffm/emblem_file");
791
792 } else {
793 file = ICON_get_filename_from_id (id);
794 }
795
796 // Fallback icons
797 if (!file) {
798 gboolean is_stock_icon = (strncmp(id, "xffm/stock_", strlen("xffm/stock_")) == 0);
799 gboolean is_dir_icon = (strncmp(id, "xffm/stock_directory", strlen("xffm/stock_directory")) == 0);
800 gboolean is_file_icon = (strncmp(id, "xffm/stock_file", strlen("xffm/stock_file")) == 0);
801 if (is_dir_icon || is_file_icon || !is_stock_icon){
802 gchar *new_id=NULL;
803 if (strcmp(id, "inode/directory")==0) id = "xffm/stock_directory";
804
805 if (!gtk_icontheme && is_dir_icon ) {
806 new_id = g_strdup_printf("xffm/emblem_folder%s", id + strlen("xffm/stock_directory"));
807 } else if (!gtk_icontheme && is_file_icon) {
808 new_id = g_strdup_printf("xffm/emblem_file%s", id + strlen("xffm/stock_file"));
809 } else {
810 new_id = g_strdup(id);
811 }
812 file = fallback_icon_path(new_id);
813 g_free(new_id);
814 }
815 }
816 // Create pixbuf from path to image file
817 if (file){
818 pixbuf = rfm_pixbuf_new_from_file(file, size, size); // refs
819 // This is wrong. Pixbuf already has a reference returned from gdk_pixbuf function.
820 /*if (pixbuf) g_object_ref(pixbuf);
821 else DBG("make_pixbuf_from_id(%s, %d): returns NULL!\n", id, size);*/
822 #ifdef DEBUG
823 if (pixbuf==NULL) DBG("make_pixbuf_from_id(%s, %d): returns NULL!\n", id, size);
824 #endif
825 g_free(file);
826 NOOP(stderr, "id=%s\n", id);
827 if (!strstr(id, "xffm/stock_directory")
828 && !strstr(id, "xffm/emblem")
829 && !strstr(id, "xffm/stock_home")
830 && !strstr(id, "inode/directory")
831 && !strstr(id, "xffm/stock_go-up")){
832 if (pixbuf && GDK_IS_PIXBUF(pixbuf)){
833 guchar red, green, blue;
834 init_lite_hash();
835 gchar *tpath = NULL;
836 const gchar *lite_id = get_mask_color(id, &red, &green, &blue, &tpath);
837 cairo_t *pixbuf_context = pixbuf_cairo_create(pixbuf);
838 // This proved necessary in opensuse-12.3,
839 // but not in gentoo nor ubuntu. Go figure...
840 gdk_cairo_set_source_pixbuf(pixbuf_context, pixbuf,0,0);
841 cairo_paint_with_alpha(pixbuf_context, 1.0);
842
843 // Color:
844 if (red != 0xff || green != 0xff || blue != 0xff)
845 add_color_pixbuf(pixbuf_context, pixbuf, red, green, blue);
846 // Emblem:
847 add_emblem_pixbuf(pixbuf_context, pixbuf,tpath, size);
848 g_free(tpath);
849 // Text:
850 add_label_pixbuf(pixbuf_context, pixbuf, lite_id, size);
851 pixbuf_cairo_destroy(pixbuf_context, pixbuf);
852 }
853 }
854
855
856 } else {
857 if (strncmp(id, "xffm/stock_", strlen("xffm/stock_"))==0) {
858 gchar *gtk_id = g_strdup_printf("%s", id+strlen("xffm/stock_"));
859 pixbuf = pixbuf_from_gtkid(gtk_id, size); // refs
860 NOOP(stderr, "cannot get icon path from \"%s\", trying \"%s\" --> %d\n",
861 id, gtk_id, GPOINTER_TO_INT(pixbuf));
862 g_free(gtk_id);
863 }
864
865 if (!pixbuf) {
866 if (strstr(id, "rodent")) DBG("Unknown pixbuf id: %s\n", id);
867 }
868 }
869 if (!pixbuf) {
870 pixbuf = last_resort_pixbuf(size, id); //refs belongs to litehash
871 if(pixbuf) g_object_ref(pixbuf);
872 }
873 return pixbuf;
874 }
875
876 static
877 GdkPixbuf *
get_pixbuf(const gchar * key,gint size,gboolean replace_pixbuf)878 get_pixbuf (const gchar * key, gint size, gboolean replace_pixbuf) {
879 #if GTK_MAJOR_VERSION==3
880 //Bug workaround for non icontheme gtk-3.14, still present at time of test in gtk-3.16
881 static gsize initialized = 0;
882 if (g_once_init_enter (&initialized)) {
883 // gtk 3.14 non deprecated method...
884 // add emblems and stock
885
886 gchar *resource_path = g_build_filename(PREFIX, "share", "icons", "rfm", NULL);
887 gtk_icon_theme_add_resource_path (gtk_icon_theme_get_default (),resource_path);
888
889 // this works, but icons should be fixed size. scalable vector graphics dont work...
890 // icons should be in the "symbolic" internal gtk name format (hack...)
891 // This is for non icon-themed boxes, like mine.
892 gchar *path = g_build_filename(resource_path, "24x24", NULL);
893 gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), path);
894 g_free(path);
895 g_free(resource_path);
896 g_once_init_leave (&initialized, 1);
897 }
898 #endif
899
900
901
902 NOOP ("get_pixbuf(%s, %d)\n", key, size);
903 if(!key) {
904 NOOP ("get_pixbuf(): key is NULL!\n");
905 return NULL;
906 }
907 GdkPixbuf *pixbuf = NULL;
908 // find in pixbuf hash
909 if (!replace_pixbuf){
910 pixbuf = rfm_find_in_pixbuf_hash (key, size); // refs
911 if(pixbuf) {
912 NOOP ("HASH-primary-icons.c: %s found in pixbuf hash\n", key);
913 return pixbuf;
914 }
915 }
916
917
918 // Pixbuf does not exist or will be replaced in the pixbuf hash table.
919 const gchar *path = key;
920 if(g_path_is_absolute (path)) {
921 NOOP ("Direct access to source pixbuf file.\n");
922 if (!g_file_test (path, G_FILE_TEST_EXISTS) || g_file_test (path, G_FILE_TEST_IS_DIR)){
923 NOOP ("get_pixbuf(%s): is not a pixbuf source file", path);
924 return NULL;
925 }
926 pixbuf = rfm_create_preview (path, size); // refs
927 if(!pixbuf) {
928 NOOP ("create_preview(%s, %d): returns NULL!\n", path, size);
929 return NULL;
930 }
931 } else {
932 NOOP (stderr, "Pixbuf creation from pixbuf id: make_pixbuf_from_id\n");
933 pixbuf = make_pixbuf_from_id (path, size); // refs
934
935 if(!pixbuf) {
936 NOOP ("get_pixbuf(%s, %d): returns NULL!\n", path, size);
937 return NULL;
938 }
939 }
940 if (pixbuf && GDK_IS_PIXBUF(pixbuf)){
941 rfm_put_in_pixbuf_hash(path, size, pixbuf); // no ref
942 }
943 return pixbuf;
944 }
945
946
947