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:
parent
35b36fc377
commit
a2e3026d8a
5 changed files with 83 additions and 18 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue