summaryrefslogtreecommitdiff
path: root/imgcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'imgcache.c')
-rw-r--r--imgcache.c140
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