From: Kaj-Michael Lang Date: Fri, 11 Apr 2008 10:23:30 +0000 (+0300) Subject: Add a generic and simple pixbuf cache system. X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d91bc8d0685a2a03b70e32825f7aaa67654e4978;p=mapper Add a generic and simple pixbuf cache system. --- diff --git a/src/Makefile.am b/src/Makefile.am index f89aa56..074f530 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -85,6 +85,8 @@ mapper_SOURCES = \ mapper.h \ path.c \ path.h \ + image-cache.c \ + image-cache.h \ poi-gui.c \ poi-gui.h \ poi.c \ diff --git a/src/image-cache.c b/src/image-cache.c new file mode 100644 index 0000000..6549e2d --- /dev/null +++ b/src/image-cache.c @@ -0,0 +1,129 @@ +#include "image-cache.h" + +ImageCache * +image_cache_new(guint cache_max) +{ +ImageCache *ic; +ic=g_slice_new0(ImageCache); +ic->cache=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_object_unref); +ic->cache_max=cache_max; +return ic; +} + +void +image_cache_free(ImageCache *ic) +{ +g_assert(ic); +g_assert(ic->cache); +image_cache_clear(ic); +g_hash_table_destroy(ic->cache); +g_slice_free(ImageCache, ic); +} + +static void +image_cache_stats(ImageCache *ic) +{ +g_assert(ic); +g_assert(ic->cache); + +g_debug("ICC: %u/%u (E: %u, GC: %u S: %d)", ic->hit, ic->miss, ic->error, ic->gc, g_hash_table_size(ic->cache)); +} + +void +image_cache_clear(ImageCache *ic) +{ +g_assert(ic); +g_assert(ic->cache); + +#if (GLIB_CHECK_VERSION (2, 12, 0)) +g_hash_table_remove_all(ic->cache); +#else +g_hash_table_foreach_remove(ic->cache, gtk_true, NULL); +#endif +} + +void +image_cache_invalidate(ImageCache *ic, const gchar *key) +{ +g_assert(ic); +g_assert(ic->cache); +g_assert(key); +g_hash_table_remove(ic->cache, key); +} + +static gboolean +image_cache_is_same(gchar *key, GdkPixbuf *cpixbuf, GdkPixbuf *pixbuf) +{ +return (pixbuf==cpixbuf) ? TRUE : FALSE; +} + +void +image_cache_invalidate_by_image(ImageCache *ic, GdkPixbuf *pixbuf) +{ +g_assert(ic); +g_assert(ic->cache); +g_return_if_fail(GDK_IS_PIXBUF(pixbuf)); +g_hash_table_foreach_remove(ic->cache, image_cache_is_same, pixbuf); +} + +void +image_cache_replace(ImageCache *ic, const gchar *key, GdkPixbuf *pixbuf) +{ + +} + +static gboolean +image_cache_gc_check(gchar *key, GdkPixbuf *pixbuf, ImageCache *ic) +{ +g_assert(ic); +/* For now just remove everything when over limit */ +return TRUE; +} + +void +image_cache_gc(ImageCache *ic, gint max) +{ +gint m; + +g_assert(ic); +g_assert(ic->cache); + +m=(max>0) ? max : ic->cache_max; +if (g_hash_table_size(ic->cache)>m) { + g_hash_table_foreach_remove(ic->cache,(GHRFunc *)image_cache_gc_check, ic); + ic->gc++; +} +} + +GdkPixbuf * +image_cache_get(ImageCache *ic, const gchar *key, const gchar *image) +{ +GdkPixbuf *pixbuf; +GError *error=NULL; + +g_assert(ic); +g_assert(ic->cache); +g_assert(key); +g_assert(image); + +image_cache_stats(ic); + +pixbuf=g_hash_table_lookup(ic->cache, key); +if (pixbuf) { + ic->hit++; + return pixbuf; +} + +pixbuf=gdk_pixbuf_new_from_file(image, &error); +if (error || !pixbuf) { + ic->error++; + return NULL; +} +g_return_val_if_fail(GDK_IS_PIXBUF(pixbuf), NULL); + +image_cache_gc(ic, 0); + +ic->miss++; +g_hash_table_insert(ic->cache, g_strdup(key), pixbuf); +return pixbuf; +} diff --git a/src/image-cache.h b/src/image-cache.h new file mode 100644 index 0000000..15ccd1f --- /dev/null +++ b/src/image-cache.h @@ -0,0 +1,31 @@ +#ifndef _MAPPER_IMAGE_CACHE_H +#define _MAPPER_IMAGE_CACHE_H + +#include +#include + +typedef struct _image_cache_item ImageCacheItem; +struct _image_cache_item { + GdkPixbuf *pixbuf; + time_t last_hit; +}; + +typedef struct _image_cache ImageCache; +struct _image_cache { + GHashTable *cache; + guint hit; + guint miss; + guint error; + guint cache_max; + guint gc; +}; + +ImageCache *image_cache_new(guint cache_max); +void image_cache_free(ImageCache *ic); +void image_cache_clear(ImageCache *ic); +void image_cache_gc(ImageCache *ic, gint max); +void image_cache_invalidate(ImageCache *ic, const gchar *key); +void image_cache_invalidate_by_image(ImageCache *ic, GdkPixbuf *pixbuf); +GdkPixbuf *image_cache_get(ImageCache *ic, const gchar *key, const gchar *icon); + +#endif