diff options
Diffstat (limited to 'imgcache.c')
-rw-r--r-- | imgcache.c | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/imgcache.c b/imgcache.c new file mode 100644 index 0000000..21db093 --- /dev/null +++ b/imgcache.c @@ -0,0 +1,140 @@ +/* imgcache.c + * Image cache + * (c) 2002 Mikulas Patocka + * This file is a part of the Links program, released under GPL. + */ + +#include "cfg.h" + +#ifdef G + +#include "links.h" + +static struct list_head image_cache = { &image_cache, &image_cache }; + +/* xyw_meaning either MEANING_DIMS or MEANING_AUTOSCALE. */ +struct cached_image *find_cached_image(int bg, unsigned char *url, int xw, int + yw, int xyw_meaning, int scale, int aspect) +{ + struct cached_image *i; + if (xw>=0&&yw>=0&&xyw_meaning==MEANING_DIMS){ + /* The xw and yw is already scaled so that scale and + * aspect don't matter. + */ + foreach (i, image_cache) { + if (i->background_color == bg + && !strcmp(i->url, url) + && i->wanted_xw==xw + && i->wanted_yw==yw + && i->wanted_xyw_meaning==xyw_meaning + ) goto hit; + } + }else{ + foreach (i, image_cache) { + if (i->background_color == bg + && !strcmp(i->url, url) + && i->wanted_xw==xw + && i->wanted_yw==yw + && i->wanted_xyw_meaning==xyw_meaning + && i->scale==scale + && i->aspect==aspect) goto hit; + } + } + return NULL; + +hit: + i->refcount++; + del_from_list(i); + add_to_list(image_cache, i); + return i; +} + +void add_image_to_cache(struct cached_image *ci) +{ + add_to_list(image_cache, ci); +} + +static unsigned long image_size(struct cached_image *cimg) +{ + unsigned long siz = sizeof(struct cached_image); + switch(cimg->state){ + case 0: + case 1: + case 2: + case 3: + case 8: + case 9: + case 10: + case 11: + break; + + case 12: + case 14: + siz+=(unsigned long)cimg->width*cimg->height*cimg->buffer_bytes_per_pixel; + if (cimg->bmp.user){ + case 13: + case 15: + siz+=(unsigned long)cimg->bmp.x*cimg->bmp.y*(drv->depth&7); + } + break; + +#ifdef DEBUG + default: + fprintf(stderr,"cimg->state=%d\n",cimg->state); + internal("Invalid cimg->state in image_size\n"); + break; +#endif /* #ifdef DEBUG */ + } + return siz; +} + +static int shrink_image_cache(int u) +{ + struct cached_image *i; + longlong si = 0; + int r = 0; + foreach(i, image_cache) if (!i->refcount) si += image_size(i); + while ((si >= image_cache_size || u == SH_FREE_ALL || u == SH_FREE_SOMETHING) && !list_empty(image_cache)) { + i = image_cache.prev; + while (i->refcount) { + i = i->prev; + if ((void *)i == &image_cache) goto no; + } + r |= ST_SOMETHING_FREED; + si -= image_size(i); + del_from_list(i); + img_destruct_cached_image(i); + if (u == SH_FREE_SOMETHING) break; + } + no: + return r | (list_empty(image_cache) ? ST_CACHE_EMPTY : 0); +} + +unsigned long imgcache_info(int type) +{ + struct cached_image *i; + unsigned long n = 0; + foreach(i, image_cache) { + switch (type) { + case CI_BYTES: + n += image_size(i); + break; + case CI_LOCKED: + if (!i->refcount) break; + /* fall through */ + case CI_FILES: + n++; + break; + default: + internal("imgcache_info: query %d", type); + } + } + return n; +} + +void init_imgcache(void) +{ + register_cache_upcall(shrink_image_cache, "imgcache"); +} + +#endif |