diff options
Diffstat (limited to 'openbox/imageload.c')
| -rw-r--r-- | openbox/imageload.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/openbox/imageload.c b/openbox/imageload.c new file mode 100644 index 00000000..c80aa134 --- /dev/null +++ b/openbox/imageload.c @@ -0,0 +1,135 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + imageload.c for the Openbox window manager + by Libor Kadlcik (aka KadlSoft) +*/ + +/* + All loaded images are cached. There's no separate cache for the images, + instead they are simply stored in image cache (RrImageCache) as RrImages, + ready to be used. + Every RrImage loaded from file is associated with name of the file. This is + done by file name table (RrImageCache.file_name_table), which is a simple + hash table, where file names are keys to pointers to RrImage. + If you request to load file that is already in image cache, nothing will be + loaded and you just got the RrImage from cache. + When RrImage is destroyed (see RrImageDestroyNotify), the file name - pointer + to RrImage pair is removed from the file name table. +*/ + +#include "debug.h" +#include "menu.h" +#include "openbox.h" +#include "gettext.h" +#include "obrender/render.h" +#include "obrender/image.h" +#include "obrender/imagecache.h" +#include "imageload.h" +#include <Imlib2.h> + + +static void CreateFileNameTable(RrImageCache *self) +{ + g_assert(self->file_name_table == NULL); + self->file_name_table = g_hash_table_new(&g_str_hash, &g_str_equal); +} + +static void DestroyFileNameTable(RrImageCache *self) +{ + g_assert(g_hash_table_size(self->file_name_table) == 0); + g_hash_table_destroy(self->file_name_table); + self->file_name_table = NULL; +} + +/*! Return file name from which this image has been loaded. */ +static gchar* GetFileName(RrImage *image) +{ + GHashTableIter iter; + void *key, *value; + + g_hash_table_iter_init(&iter, image->cache->file_name_table); + while (g_hash_table_iter_next(&iter, &key, &value)) { + if (value == image) + return key; + } + return NULL; +} + +/* RrImage is about to be deleted. So remove it from file name table. */ +static void RrImageDestroyNotify(RrImage *image) +{ + gchar *file_name = GetFileName(image); + g_assert(file_name != NULL); + ob_debug("Image \"%s\" no longer needed\n", file_name); + g_hash_table_remove(image->cache->file_name_table, file_name); + g_free(file_name); + + if (g_hash_table_size(image->cache->file_name_table) == 0) { + ob_debug("No RrImage in file_name_table, destroying\n"); + DestroyFileNameTable(image->cache); + } +} + +#if (RrDefaultAlphaOffset != 24 || RrDefaultRedOffset != 16 \ + || RrDefaultGreenOffset != 8 || RrDefaultBlueOffset != 0) +#error RrImageFetchFromFile cannot handle current bit layout of RrPixel32. +#endif + +/*! Load image from specified file and create RrImage for it (RrImage will be + linked into specified image cache). Reference count of the RrImage will + be set to 1. + If that image has already been loaded into the image cache, RrImage + from the cache will be returned and its reference count will be incremented. +*/ +RrImage* RrImageFetchFromFile(RrImageCache *cache, const gchar *name) +{ + RrImage *rr_image, *found_rr_image; + gint w, h; + DATA32 *ro_data; + + imlib_set_color_usage(128); + + if (cache->file_name_table == NULL) + CreateFileNameTable(cache); + + /* Find out if that image has already been loaded to this cache. */ + rr_image = g_hash_table_lookup(cache->file_name_table, name); + if (rr_image && rr_image->cache == cache) { + ob_debug("\"%s\" already loaded in this image cache.\n", name); + RrImageRef(rr_image); + return rr_image; + } + + Imlib_Image imlib_image = imlib_load_image(name); + if (imlib_image == NULL) { + g_message(_("Cannot load image from file \"%s\""), name); + return NULL; + } + + /* Get data and dimensions of the image. */ + imlib_context_set_image(imlib_image); + g_message("Alpha = %d\n", imlib_image_has_alpha()); + ro_data = imlib_image_get_data_for_reading_only(); + w = imlib_image_get_width(); + h = imlib_image_get_height(); + ob_debug("Loaded \"%s\", dimensions %dx%d\n", name, w, h); + + /* There must not be any duplicated pictures in RrImageCache. */ + found_rr_image = RrImageCacheFind(cache, ro_data, w, h); + if (found_rr_image) { + rr_image = found_rr_image; + RrImageRef(rr_image); + ob_debug("Image \"%s\" is duplicate\n", name); + } + else { + /* Create RrImage from the image and add it to file name table. */ + rr_image = RrImageNew(cache); + RrImageSetDestroyFunc(rr_image, &RrImageDestroyNotify); + /* XXX: Is Imlib2's format of DATA32 always identical to RrPixel32? */ + RrImageAddPicture(rr_image, ro_data, w, h); + g_hash_table_insert(cache->file_name_table, g_strdup(name), rr_image); + } + + imlib_free_image(); + + return rr_image; +} |
