ob_rr_inst = RrInstanceNew(obt_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(obt_display, xsync);
#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)
{
#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)
{
*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;
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;
}
}
+/*! Draw an RGBA texture into a target pixel buffer. */
void RrImageDrawRGBA(RrPixel32 *target, RrTextureRGBA *rgba,
gint target_w, gint target_h,
RrRect *area)
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;
}
}
+/*! 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;
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;
}
}
+/*! 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)
/* 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);
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;
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))))
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;
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)
#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;
};
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;
};
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);