]> Dogcows Code - chaz/openbox/blob - openbox/imageload.c
This patch implements support for icons in user-defined menus into Openbox
[chaz/openbox] / openbox / imageload.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
2 imageload.c for the Openbox window manager
3 by Libor Kadlcik (aka KadlSoft)
4 */
5
6 /*
7 All loaded images are cached. There's no separate cache for the images,
8 instead they are simply stored in image cache (RrImageCache) as RrImages,
9 ready to be used.
10 Every RrImage loaded from file is associated with name of the file. This is
11 done by file name table (RrImageCache.file_name_table), which is a simple
12 hash table, where file names are keys to pointers to RrImage.
13 If you request to load file that is already in image cache, nothing will be
14 loaded and you just got the RrImage from cache.
15 When RrImage is destroyed (see RrImageDestroyNotify), the file name - pointer
16 to RrImage pair is removed from the file name table.
17 */
18
19 #include "debug.h"
20 #include "menu.h"
21 #include "openbox.h"
22 #include "gettext.h"
23 #include "obrender/render.h"
24 #include "obrender/image.h"
25 #include "obrender/imagecache.h"
26 #include "imageload.h"
27 #include <Imlib2.h>
28
29
30 static void CreateFileNameTable(RrImageCache *self)
31 {
32 g_assert(self->file_name_table == NULL);
33 self->file_name_table = g_hash_table_new(&g_str_hash, &g_str_equal);
34 }
35
36 static void DestroyFileNameTable(RrImageCache *self)
37 {
38 g_assert(g_hash_table_size(self->file_name_table) == 0);
39 g_hash_table_destroy(self->file_name_table);
40 self->file_name_table = NULL;
41 }
42
43 /*! Return file name from which this image has been loaded. */
44 static gchar* GetFileName(RrImage *image)
45 {
46 GHashTableIter iter;
47 void *key, *value;
48
49 g_hash_table_iter_init(&iter, image->cache->file_name_table);
50 while (g_hash_table_iter_next(&iter, &key, &value)) {
51 if (value == image)
52 return key;
53 }
54 return NULL;
55 }
56
57 /* RrImage is about to be deleted. So remove it from file name table. */
58 static void RrImageDestroyNotify(RrImage *image)
59 {
60 gchar *file_name = GetFileName(image);
61 g_assert(file_name != NULL);
62 ob_debug("Image \"%s\" no longer needed\n", file_name);
63 g_hash_table_remove(image->cache->file_name_table, file_name);
64 g_free(file_name);
65
66 if (g_hash_table_size(image->cache->file_name_table) == 0) {
67 ob_debug("No RrImage in file_name_table, destroying\n");
68 DestroyFileNameTable(image->cache);
69 }
70 }
71
72 #if (RrDefaultAlphaOffset != 24 || RrDefaultRedOffset != 16 \
73 || RrDefaultGreenOffset != 8 || RrDefaultBlueOffset != 0)
74 #error RrImageFetchFromFile cannot handle current bit layout of RrPixel32.
75 #endif
76
77 /*! Load image from specified file and create RrImage for it (RrImage will be
78 linked into specified image cache). Reference count of the RrImage will
79 be set to 1.
80 If that image has already been loaded into the image cache, RrImage
81 from the cache will be returned and its reference count will be incremented.
82 */
83 RrImage* RrImageFetchFromFile(RrImageCache *cache, const gchar *name)
84 {
85 RrImage *rr_image, *found_rr_image;
86 gint w, h;
87 DATA32 *ro_data;
88
89 imlib_set_color_usage(128);
90
91 if (cache->file_name_table == NULL)
92 CreateFileNameTable(cache);
93
94 /* Find out if that image has already been loaded to this cache. */
95 rr_image = g_hash_table_lookup(cache->file_name_table, name);
96 if (rr_image && rr_image->cache == cache) {
97 ob_debug("\"%s\" already loaded in this image cache.\n", name);
98 RrImageRef(rr_image);
99 return rr_image;
100 }
101
102 Imlib_Image imlib_image = imlib_load_image(name);
103 if (imlib_image == NULL) {
104 g_message(_("Cannot load image from file \"%s\""), name);
105 return NULL;
106 }
107
108 /* Get data and dimensions of the image. */
109 imlib_context_set_image(imlib_image);
110 g_message("Alpha = %d\n", imlib_image_has_alpha());
111 ro_data = imlib_image_get_data_for_reading_only();
112 w = imlib_image_get_width();
113 h = imlib_image_get_height();
114 ob_debug("Loaded \"%s\", dimensions %dx%d\n", name, w, h);
115
116 /* There must not be any duplicated pictures in RrImageCache. */
117 found_rr_image = RrImageCacheFind(cache, ro_data, w, h);
118 if (found_rr_image) {
119 rr_image = found_rr_image;
120 RrImageRef(rr_image);
121 ob_debug("Image \"%s\" is duplicate\n", name);
122 }
123 else {
124 /* Create RrImage from the image and add it to file name table. */
125 rr_image = RrImageNew(cache);
126 RrImageSetDestroyFunc(rr_image, &RrImageDestroyNotify);
127 /* XXX: Is Imlib2's format of DATA32 always identical to RrPixel32? */
128 RrImageAddPicture(rr_image, ro_data, w, h);
129 g_hash_table_insert(cache->file_name_table, g_strdup(name), rr_image);
130 }
131
132 imlib_free_image();
133
134 return rr_image;
135 }
This page took 0.03974 seconds and 4 git commands to generate.