add a bunch of comments for images and image caches. and make the number of resized pictures saved in an image tunable per-icon cache.

This commit is contained in:
Dana Jansens 2008-02-13 08:43:57 -05:00
parent 35b36fc377
commit a2e3026d8a
5 changed files with 83 additions and 18 deletions

View file

@ -183,7 +183,11 @@ gint main(gint argc, gchar **argv)
ob_rr_inst = RrInstanceNew(ob_display, ob_screen);
if (ob_rr_inst == NULL)
ob_exit_with_error(_("Failed to initialize the obrender library."));
ob_rr_icons = RrImageCacheNew();
/* Saving 3 resizes of an RrImage makes a lot of sense for icons, as there
are generally 3 icon sizes needed: the titlebar icon, the menu icon,
and the alt-tab icon
*/
ob_rr_icons = RrImageCacheNew(3);
XSynchronize(ob_display, xsync);

View file

@ -28,6 +28,9 @@
#define FLOOR(i) ((i) & (~0UL << FRACTION))
#define AVERAGE(a, b) (((((a) ^ (b)) & 0xfefefefeL) >> 1) + ((a) & (b)))
/*! Add a picture to an Image, that is, add another copy of the image at
another size. This may add it to the "originals" list or to the
"resized" list. */
static void AddPicture(RrImage *self, RrImagePic ***list, gint *len,
RrImagePic *pic)
{
@ -58,6 +61,8 @@ static void AddPicture(RrImage *self, RrImagePic ***list, gint *len,
#endif
}
/*! Remove a picture from an Image. This may remove it from the "originals"
list or the "resized" list. */
static void RemovePicture(RrImage *self, RrImagePic ***list,
gint i, gint *len)
{
@ -84,9 +89,14 @@ static void RemovePicture(RrImage *self, RrImagePic ***list,
*list = g_renew(RrImagePic*, *list, --*len);
}
/*! Given a picture in RGBA format, of a specified size, resize it to the new
requested size (but keep its aspect ratio). If the image does not need to
be resized (it is already the right size) then this returns NULL. Otherwise
it returns a newly allocated RrImagePic with the resized picture inside it
*/
static RrImagePic* ResizeImage(RrPixel32 *src,
gulong srcW, gulong srcH,
gulong dstW, gulong dstH)
gulong srcW, gulong srcH,
gulong dstW, gulong dstH)
{
RrPixel32 *dst;
RrImagePic *pic;
@ -199,6 +209,8 @@ void DrawRGBA(RrPixel32 *target, gint target_w, gint target_h,
gint dw, dh;
g_assert(source_w <= area->width && source_h <= area->height);
g_assert(area->x + area->width <= target_w);
g_assert(area->y + area->height <= target_h);
/* keep the aspect ratio */
dw = area->width;
@ -246,6 +258,7 @@ void DrawRGBA(RrPixel32 *target, gint target_w, gint target_h,
}
}
/*! Draw an RGBA texture into a target pixel buffer. */
void RrImageDrawRGBA(RrPixel32 *target, RrTextureRGBA *rgba,
gint target_w, gint target_h,
RrRect *area)
@ -270,10 +283,13 @@ void RrImageDrawRGBA(RrPixel32 *target, RrTextureRGBA *rgba,
rgba->alpha, area);
}
/*! Create a new RrImage, which is linked to an image cache */
RrImage* RrImageNew(RrImageCache *cache)
{
RrImage *self;
g_assert(cache != NULL);
self = g_new0(RrImage, 1);
self->ref = 1;
self->cache = cache;
@ -300,6 +316,9 @@ 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)
{
gint i;
@ -330,6 +349,9 @@ void RrImageAddPicture(RrImage *self, RrPixel32 *data, gint w, gint h)
AddPicture(self, &self->original, &self->n_original, pic);
}
/*! Remove the picture from the RrImage which has the given dimensions. This
removes an "original" picture from the image.
*/
void RrImageRemovePicture(RrImage *self, gint w, gint h)
{
gint i;
@ -342,6 +364,11 @@ void RrImageRemovePicture(RrImage *self, gint w, gint h)
}
}
/*! Draw an RrImage texture into a target pixel buffer. If the RrImage does
not contain a picture of the appropriate size, then one of its "original"
pictures will be resized and used (and stored in the RrImage as a "resized"
picture).
*/
void RrImageDrawImage(RrPixel32 *target, RrTextureImage *img,
gint target_w, gint target_h,
RrRect *area)
@ -431,13 +458,13 @@ void RrImageDrawImage(RrPixel32 *target, RrTextureImage *img,
/* add the resized image to the image, as the first in the resized
list */
if (self->n_resized >= MAX_CACHE_RESIZED) {
if (self->n_resized >= self->cache->max_resized_saved)
/* remove the last one (last used one) */
RemovePicture(self, &self->resized, self->n_resized - 1,
&self->n_resized);
}
/* add it to the top of the resized list */
AddPicture(self, &self->resized, &self->n_resized, pic);
if (self->cache->max_resized_saved)
/* add it to the top of the resized list */
AddPicture(self, &self->resized, &self->n_resized, pic);
}
g_assert(pic != NULL);

View file

@ -22,12 +22,15 @@
static gboolean RrImagePicEqual(const RrImagePic *p1,
const RrImagePic *p2);
RrImageCache* RrImageCacheNew()
RrImageCache* RrImageCacheNew(gint max_resized_saved)
{
RrImageCache *self;
g_assert(max_resized_saved >= 0);
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);
return self;
@ -59,9 +62,6 @@ RrImage* RrImageCacheFind(RrImageCache *self,
return g_hash_table_lookup(self->table, &pic);
}
/* This is a fast, reversable hash function called "lookup3", found here:
http://burtleburtle.net/bob/c/lookup3.c
*/
#define hashsize(n) ((RrPixel32)1<<(n))
#define hashmask(n) (hashsize(n)-1)
#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
@ -87,6 +87,13 @@ RrImage* RrImageCacheFind(RrImageCache *self,
c ^= b; c -= rot(b,24); \
}
/* This is a fast, reversable hash function called "lookup3", found here:
http://burtleburtle.net/bob/c/lookup3.c, by Bob Jenkins
This hashing algorithm is "reversible", that is, not cryptographically
secure at all. But we don't care about that, we just want something to
tell when images are the same or different relatively quickly.
*/
guint32 hashword(const guint32 *key, gint length, guint32 initval)
{
guint32 a,b,c;
@ -119,6 +126,9 @@ guint32 hashword(const guint32 *key, gint length, guint32 initval)
return c;
}
/*! This is some arbitrary initial value for the hashing function. It's
constant so that you get the same result from the same data each time.
*/
#define HASH_INITVAL 0xf00d
guint RrImagePicHash(const RrImagePic *p)

View file

@ -21,15 +21,29 @@
#include <glib.h>
/* the number of resized pictures to cache for an image */
#define MAX_CACHE_RESIZED 3
struct _RrImagePic;
guint RrImagePicHash(const struct _RrImagePic *p);
/*! Create a new image cache. An image cache is basically a hash table to look
up RrImages. Each RrImage in the cache may contain one or more Pictures,
that is one or more actual copies of image data at various sizes. For eg,
for a window, all of its various icons are loaded into the same RrImage.
When an RrImage is drawn and a picture inside it needs to be resized, that
is also saved within the RrImage.
For each picture that an RrImage has, the picture is hashed and that is used
as a key to find the RrImage. So, given any picture in any RrImage in the
cache, if you hash it, you will find the RrImage.
*/
struct _RrImageCache {
gint ref;
/*! When an original picture is resized for an RrImage, the resized picture
is saved in the RrImage. This specifies how many pictures should be
saved at a time. When this is exceeded, the least recently used
"resized" picture is deleted.
*/
gint max_resized_saved;
GHashTable *table;
};

View file

@ -234,11 +234,18 @@ struct _RrImagePic {
pictures */
struct _RrImage {
gint ref;
struct _RrImageCache *cache;
RrImageCache *cache;
struct _RrImagePic **original;
/*! An array of "originals", that is of RrPictures that have been added
to the image in various sizes, and that have not been resized. These
are explicitly added to the RrImage. */
RrImagePic **original;
gint n_original;
struct _RrImagePic **resized;
/*! An array of "resized" pictures. When an "original" RrPicture
needs to be resized for drawing, it is saved in here so that it doesn't
need to be resized again. These are automatically added to the
RrImage. */
RrImagePic **resized;
gint n_resized;
};
@ -317,7 +324,10 @@ gboolean RrPixmapToRGBA(const RrInstance *inst,
Pixmap pmap, Pixmap mask,
gint *w, gint *h, RrPixel32 **data);
RrImageCache* RrImageCacheNew();
/*! Create a new image cache for RrImages.
@param max_resized_saved The number of resized copies of an image to save
*/
RrImageCache* RrImageCacheNew(gint max_resized_saved);
void RrImageCacheRef(RrImageCache *self);
void RrImageCacheUnref(RrImageCache *self);