summaryrefslogtreecommitdiff
path: root/obrender
diff options
context:
space:
mode:
Diffstat (limited to 'obrender')
-rw-r--r--obrender/image.c89
-rw-r--r--obrender/image.h3
-rw-r--r--obrender/imagecache.c25
-rw-r--r--obrender/imagecache.h13
-rw-r--r--obrender/render.h18
5 files changed, 117 insertions, 31 deletions
diff --git a/obrender/image.c b/obrender/image.c
index c65cd2a5..671b7aee 100644
--- a/obrender/image.c
+++ b/obrender/image.c
@@ -21,6 +21,9 @@
#include "image.h"
#include "color.h"
#include "imagecache.h"
+#ifdef USE_IMLIB2
+#include <Imlib2.h>
+#endif
#include <glib.h>
@@ -28,7 +31,8 @@
#define FLOOR(i) ((i) & (~0UL << FRACTION))
#define AVERAGE(a, b) (((((a) ^ (b)) & 0xfefefefeL) >> 1) + ((a) & (b)))
-void RrImagePicInit(RrImagePic *pic, gint w, gint h, RrPixel32 *data)
+void RrImagePicInit(RrImagePic *pic, const gchar *name,
+ gint w, gint h, RrPixel32 *data)
{
gint i;
@@ -38,12 +42,14 @@ void RrImagePicInit(RrImagePic *pic, gint w, gint h, RrPixel32 *data)
pic->sum = 0;
for (i = w*h; i > 0; --i)
pic->sum += *(data++);
+ pic->name = g_strdup(name);
}
static void RrImagePicFree(RrImagePic *pic)
{
if (pic) {
g_free(pic->data);
+ g_free(pic->name);
g_free(pic);
}
}
@@ -58,7 +64,10 @@ static void AddPicture(RrImage *self, RrImagePic ***list, gint *len,
g_assert(pic->width > 0 && pic->height > 0);
- g_assert(g_hash_table_lookup(self->cache->table, pic) == NULL);
+ if (pic->name)
+ g_assert(!g_hash_table_lookup(self->cache->name_table, pic->name));
+ else
+ g_assert(!g_hash_table_lookup(self->cache->pic_table, pic));
/* grow the list */
*list = g_renew(RrImagePic*, *list, ++*len);
@@ -70,8 +79,12 @@ static void AddPicture(RrImage *self, RrImagePic ***list, gint *len,
/* set the new picture up at the front of the list */
(*list)[0] = pic;
- /* add the picture as a key to point to this image in the cache */
- g_hash_table_insert(self->cache->table, (*list)[0], self);
+ /* add the name or the picture as a key to point to this image in the
+ cache */
+ if (pic->name)
+ g_hash_table_insert(self->cache->name_table, pic->name, self);
+ else
+ g_hash_table_insert(self->cache->pic_table, (*list)[0], self);
/*
#ifdef DEBUG
@@ -100,8 +113,11 @@ static void RemovePicture(RrImage *self, RrImagePic ***list,
#endif
*/
- /* remove the picture as a key in the cache */
- g_hash_table_remove(self->cache->table, (*list)[i]);
+ /* remove the name or picture as a key in the cache */
+ if ((*list)[i]->name)
+ g_hash_table_remove(self->cache->name_table, (*list)[i]->name);
+ else
+ g_hash_table_remove(self->cache->pic_table, (*list)[i]);
/* free the picture */
RrImagePicFree((*list)[i]);
@@ -220,7 +236,7 @@ static RrImagePic* ResizeImage(RrPixel32 *src,
}
pic = g_new(RrImagePic, 1);
- RrImagePicInit(pic, dstW, dstH, dststart);
+ RrImagePicInit(pic, NULL, dstW, dstH, dststart);
return pic;
}
@@ -326,9 +342,11 @@ RrImage* RrImageNew(RrImageCache *cache)
}
/*! Set function that will be called just before RrImage is destroyed. */
-void RrImageSetDestroyFunc(RrImage *image, RrImageDestroyFunc func)
+void RrImageSetDestroyFunc(RrImage *image, RrImageDestroyFunc func,
+ gpointer data)
{
image->destroy_func = func;
+ image->destroy_data = data;
}
void RrImageRef(RrImage *self)
@@ -346,7 +364,7 @@ void RrImageUnref(RrImage *self)
#endif
*/
if (self->destroy_func)
- self->destroy_func(self);
+ self->destroy_func(self, self->destroy_data);
while (self->n_original > 0)
RemovePicture(self, &self->original, 0, &self->n_original);
while (self->n_resized > 0)
@@ -355,10 +373,8 @@ void RrImageUnref(RrImage *self)
}
}
-/*! Add a new picture with the given RGBA pixel data and dimensions into the
- RrImage. This adds an "original" picture to the image.
-*/
-void RrImageAddPicture(RrImage *self, RrPixel32 *data, gint w, gint h)
+static void AddPictureFromData(RrImage *self, const char *name,
+ const RrPixel32 *data, gint w, gint h)
{
gint i;
RrImagePic *pic;
@@ -384,10 +400,55 @@ void RrImageAddPicture(RrImage *self, RrPixel32 *data, gint w, gint h)
/* add the new picture */
pic = g_new(RrImagePic, 1);
- RrImagePicInit(pic, w, h, g_memdup(data, w*h*sizeof(RrPixel32)));
+ RrImagePicInit(pic, name, w, h, g_memdup(data, w*h*sizeof(RrPixel32)));
AddPicture(self, &self->original, &self->n_original, pic);
}
+gboolean RrImageAddPictureName(RrImage *self, const gchar *name)
+{
+#ifdef USE_IMLIB2
+ Imlib_Image img;
+ gint w, h;
+ RrPixel32 *data;
+ gchar *path;
+
+ /* XXX find the path via freedesktop icon spec (use obt) ! */
+ path = g_strdup(name);
+
+ if (!(img = imlib_load_image(path)))
+ g_message("Cannot load image \"%s\" from file \"%s\"", name, path);
+ g_free(path);
+
+ if (!img)
+ return FALSE; /* failed to load it */
+
+ /* Get data and dimensions of the image.
+
+ WARNING: This stuff is NOT threadsafe !!
+ */
+ imlib_context_set_image(img);
+ data = imlib_image_get_data_for_reading_only();
+ w = imlib_image_get_width();
+ h = imlib_image_get_height();
+
+ /* add it to the RrImage, and set its name */
+ AddPictureFromData(self, name, data, w, h);
+
+ imlib_free_image();
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
+/*! Add a new picture with the given RGBA pixel data and dimensions into the
+ RrImage. This adds an "original" picture to the image.
+*/
+void RrImageAddPicture(RrImage *self, const RrPixel32 *data, gint w, gint h)
+{
+ AddPictureFromData(self, NULL, data, w, h);
+}
+
/*! Remove the picture from the RrImage which has the given dimensions. This
removes an "original" picture from the image.
*/
diff --git a/obrender/image.h b/obrender/image.h
index b478daf9..6e4a50e0 100644
--- a/obrender/image.h
+++ b/obrender/image.h
@@ -23,7 +23,8 @@
#include "geom.h"
/*! Initialize an RrImagePicture to the specified dimensions and pixel data */
-void RrImagePicInit(RrImagePic *pic, gint w, gint h, RrPixel32 *data);
+void RrImagePicInit(RrImagePic *pic, const gchar *path,
+ gint w, gint h, RrPixel32 *data);
void RrImageDrawImage(RrPixel32 *target, RrTextureImage *img,
gint target_w, gint target_h,
diff --git a/obrender/imagecache.c b/obrender/imagecache.c
index fde1e7a0..036ac121 100644
--- a/obrender/imagecache.c
+++ b/obrender/imagecache.c
@@ -32,9 +32,9 @@ RrImageCache* RrImageCacheNew(gint max_resized_saved)
self = g_new(RrImageCache, 1);
self->ref = 1;
self->max_resized_saved = max_resized_saved;
- self->table = g_hash_table_new((GHashFunc)RrImagePicHash,
- (GEqualFunc)RrImagePicEqual);
- self->file_name_table = NULL;
+ self->pic_table = g_hash_table_new((GHashFunc)RrImagePicHash,
+ (GEqualFunc)RrImagePicEqual);
+ self->name_table = g_hash_table_new(g_str_hash, g_str_equal);
return self;
}
@@ -46,22 +46,31 @@ void RrImageCacheRef(RrImageCache *self)
void RrImageCacheUnref(RrImageCache *self)
{
if (self && --self->ref == 0) {
- g_assert(g_hash_table_size(self->table) == 0);
- g_assert(self->file_name_table == NULL);
- g_hash_table_unref(self->table);
+ g_assert(g_hash_table_size(self->pic_table) == 0);
+ g_hash_table_unref(self->pic_table);
+ self->pic_table = NULL;
+
+ g_assert(g_hash_table_size(self->name_table) == 0);
+ g_hash_table_destroy(self->name_table);
+ self->name_table = NULL;
g_free(self);
}
}
+RrImage* RrImageCacheFindName(RrImageCache *self, const gchar *name)
+{
+ return g_hash_table_lookup(self->name_table, name);
+}
+
/*! Finds an image in the cache, if it is already in there */
RrImage* RrImageCacheFind(RrImageCache *self,
RrPixel32 *data, gint w, gint h)
{
RrImagePic pic;
- RrImagePicInit(&pic, w, h, data);
- return g_hash_table_lookup(self->table, &pic);
+ RrImagePicInit(&pic, NULL, w, h, data);
+ return g_hash_table_lookup(self->pic_table, &pic);
}
#define hashsize(n) ((RrPixel32)1<<(n))
diff --git a/obrender/imagecache.h b/obrender/imagecache.h
index a61fae67..9baf34bb 100644
--- a/obrender/imagecache.h
+++ b/obrender/imagecache.h
@@ -45,11 +45,14 @@ struct _RrImageCache {
*/
gint max_resized_saved;
- GHashTable *table;
-
- /* Used to find out if an image file has already been loaded.
- Quick file_name -> RrImage lookup. */
- GHashTable *file_name_table;
+ /*! A hash table of images in the cache that don't have a file name
+ attached to them, with their key being a hash of the contents of the
+ image. */
+ GHashTable *pic_table;
+
+ /*! Used to find out if an image file has already been loaded.
+ Provides a quick file_name -> RrImage lookup. */
+ GHashTable *name_table;
};
#endif
diff --git a/obrender/render.h b/obrender/render.h
index 7aa9d698..64c2f6a1 100644
--- a/obrender/render.h
+++ b/obrender/render.h
@@ -230,9 +230,13 @@ struct _RrImagePic {
/* The sum of all the pixels. This is used to compare pictures if their
hashes match. */
gint sum;
+ /* The name of the image. This is used to determine
+ if the named image already is loaded. May be NULL if the image
+ was not loaded from disk. */
+ gchar *name;
};
-typedef void (*RrImageDestroyFunc)(RrImage *image);
+typedef void (*RrImageDestroyFunc)(RrImage *image, gpointer data);
/*! An RrImage is a sort of meta-image. It can contain multiple versions of
an image at different sizes, which may or may not be completely different
@@ -252,10 +256,11 @@ struct _RrImage {
RrImage. */
RrImagePic **resized;
gint n_resized;
-
+
/* This function (if not NULL) will be called just before destroying
RrImage. */
RrImageDestroyFunc destroy_func;
+ gpointer destroy_data;
};
/* these are the same on all endian machines because it seems to be dependant
@@ -343,12 +348,19 @@ void RrImageCacheUnref(RrImageCache *self);
/*! Finds an image in the cache, if it is already in there */
RrImage* RrImageCacheFind(RrImageCache *self,
RrPixel32 *data, gint w, gint h);
+/*! Finds an image in the cache, by searching for the name of the image */
+RrImage* RrImageCacheFindName(RrImageCache *self,
+ const gchar *name);
RrImage* RrImageNew(RrImageCache *cache);
void RrImageRef(RrImage *im);
void RrImageUnref(RrImage *im);
-void RrImageAddPicture(RrImage *im, RrPixel32 *data, gint w, gint h);
+void RrImageAddPicture(RrImage *im, const RrPixel32 *data, gint w, gint h);
+/*! Adds a picture by name, from a file on disk.
+ @name Can be a full path to an image, or it can be a name as per the
+ freedesktop.org icon spec. */
+gboolean RrImageAddPictureName(RrImage *im, const gchar *name);
void RrImageRemovePicture(RrImage *im, gint w, gint h);
G_END_DECLS