2007-07-16 00:25:35 -07:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <Evas.h>
|
|
|
|
|
|
|
|
#include "evas_common.h"
|
|
|
|
#include "evas_private.h"
|
|
|
|
|
|
|
|
EAPI int
|
|
|
|
evas_cache_image_usage_get(Evas_Cache_Image *cache)
|
|
|
|
{
|
|
|
|
assert(cache != NULL);
|
|
|
|
|
|
|
|
return cache->usage;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI int
|
|
|
|
evas_cache_image_get(Evas_Cache_Image *cache)
|
|
|
|
{
|
|
|
|
assert(cache != NULL);
|
|
|
|
|
|
|
|
return cache->limit;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
evas_cache_image_set(Evas_Cache_Image *cache, int limit)
|
|
|
|
{
|
|
|
|
assert(cache != NULL);
|
|
|
|
|
|
|
|
cache->limit = limit;
|
|
|
|
}
|
|
|
|
|
2007-08-12 22:30:17 -07:00
|
|
|
EAPI Evas_Cache_Image *
|
2007-07-16 00:25:35 -07:00
|
|
|
evas_cache_image_init(const Evas_Cache_Image_Func *cb)
|
|
|
|
{
|
2007-08-12 22:30:17 -07:00
|
|
|
Evas_Cache_Image *new;
|
2007-07-16 00:25:35 -07:00
|
|
|
|
|
|
|
new = malloc(sizeof (Evas_Cache_Image));
|
|
|
|
if (!new)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
new->func = *cb;
|
|
|
|
|
2007-10-07 04:17:09 -07:00
|
|
|
new->limit = 0;
|
2007-07-16 00:25:35 -07:00
|
|
|
new->usage = 0;
|
|
|
|
|
|
|
|
new->dirty = NULL;
|
|
|
|
new->lru = NULL;
|
|
|
|
new->inactiv = NULL;
|
|
|
|
new->activ = NULL;
|
|
|
|
|
|
|
|
new->references = 1;
|
|
|
|
|
|
|
|
return new;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Evas_Bool
|
|
|
|
_evas_cache_image_free_cb(Evas_Hash *hash, const char *key, void *data, void *fdata)
|
|
|
|
{
|
2007-08-12 22:30:17 -07:00
|
|
|
Evas_Cache_Image *cache = fdata;
|
|
|
|
RGBA_Image *im = data;
|
2007-07-16 00:25:35 -07:00
|
|
|
|
|
|
|
if (cache->func.debug)
|
|
|
|
cache->func.debug("shutdown-activ", im);
|
|
|
|
|
2007-08-12 22:30:17 -07:00
|
|
|
if (im->cache_key)
|
|
|
|
{
|
|
|
|
evas_stringshare_del(im->cache_key);
|
|
|
|
im->cache_key = NULL;
|
|
|
|
}
|
2007-07-16 00:25:35 -07:00
|
|
|
|
|
|
|
cache->func.destructor(im);
|
|
|
|
evas_common_image_delete(im);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
evas_cache_image_shutdown(Evas_Cache_Image *cache)
|
|
|
|
{
|
2007-08-12 22:30:17 -07:00
|
|
|
RGBA_Image *im;
|
2007-07-16 00:25:35 -07:00
|
|
|
|
|
|
|
assert(cache != NULL);
|
|
|
|
cache->references--;
|
|
|
|
|
|
|
|
if (cache->references > 0)
|
|
|
|
return ;
|
|
|
|
|
|
|
|
while (cache->lru)
|
|
|
|
{
|
2007-08-12 22:30:17 -07:00
|
|
|
im = (RGBA_Image *) cache->lru;
|
2007-07-16 00:25:35 -07:00
|
|
|
cache->lru = evas_object_list_remove(cache->lru, im);
|
|
|
|
|
2007-08-12 22:30:17 -07:00
|
|
|
if (im->cache_key)
|
|
|
|
{
|
|
|
|
evas_stringshare_del(im->cache_key);
|
|
|
|
im->cache_key = NULL;
|
|
|
|
}
|
2007-07-16 00:25:35 -07:00
|
|
|
|
|
|
|
if (cache->func.debug)
|
|
|
|
cache->func.debug("shutdown-lru", im);
|
|
|
|
cache->func.destructor(im);
|
|
|
|
evas_common_image_delete(im);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This is mad, I am about to destroy image still alive, but we need to prevent leak. */
|
|
|
|
while (cache->dirty)
|
|
|
|
{
|
2007-08-12 22:30:17 -07:00
|
|
|
im = (RGBA_Image *) cache->dirty;
|
2007-07-16 00:25:35 -07:00
|
|
|
cache->dirty = evas_object_list_remove(cache->dirty, im);
|
|
|
|
|
|
|
|
if (cache->func.debug)
|
|
|
|
cache->func.debug("shutdown-dirty", im);
|
|
|
|
cache->func.destructor(im);
|
|
|
|
evas_common_image_delete(im);
|
|
|
|
}
|
|
|
|
|
|
|
|
evas_hash_foreach(cache->activ, _evas_cache_image_free_cb, cache);
|
|
|
|
evas_hash_free(cache->activ);
|
|
|
|
evas_hash_free(cache->inactiv);
|
|
|
|
|
|
|
|
free(cache);
|
|
|
|
}
|
|
|
|
|
2007-08-12 22:30:17 -07:00
|
|
|
EAPI RGBA_Image *
|
2007-07-16 00:25:35 -07:00
|
|
|
evas_cache_image_request(Evas_Cache_Image *cache, const char *file, const char *key, RGBA_Image_Loadopts *lo, int *error)
|
|
|
|
{
|
2007-08-12 22:30:17 -07:00
|
|
|
const char *format;
|
|
|
|
char *hkey;
|
|
|
|
RGBA_Image *im;
|
|
|
|
Evas_Image_Load_Opts prevent;
|
|
|
|
int size;
|
|
|
|
struct stat st;
|
2007-07-16 00:25:35 -07:00
|
|
|
|
|
|
|
assert(cache != NULL);
|
|
|
|
|
|
|
|
if (!file && !key) return NULL;
|
|
|
|
if (!file) return NULL;
|
|
|
|
if ((!lo) ||
|
|
|
|
(lo &&
|
|
|
|
(lo->scale_down_by == 0) &&
|
|
|
|
(lo->dpi = 0.0) &&
|
|
|
|
((lo->w == 0) || (lo->h == 0))))
|
|
|
|
{
|
|
|
|
lo = &prevent;
|
|
|
|
if (key)
|
|
|
|
format = "%s//://%s";
|
|
|
|
else
|
|
|
|
format = "%s//://%p";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (key)
|
|
|
|
format = "%s//://%s//@/%i/%1.5f/%ix%i";
|
|
|
|
else
|
|
|
|
format = "%s//://%p//@/%i/%1.5f/%ix%i";
|
|
|
|
}
|
|
|
|
size = strlen(file) + (key ? strlen(key) : 6) + 64;
|
|
|
|
hkey = alloca(sizeof (char) * size);
|
|
|
|
snprintf(hkey, size, format, file, key, lo->scale_down_by, lo->dpi, lo->w, lo->h);
|
|
|
|
|
2007-08-11 05:22:43 -07:00
|
|
|
if (stat(file, &st) < 0)
|
|
|
|
{
|
|
|
|
im = evas_hash_find(cache->inactiv, hkey);
|
|
|
|
if (im)
|
|
|
|
{
|
|
|
|
cache->lru = evas_object_list_remove(cache->lru, im);
|
|
|
|
cache->inactiv = evas_hash_del(cache->inactiv, im->cache_key, im);
|
|
|
|
cache->usage -= cache->func.mem_size_get(im);
|
|
|
|
if (im->cache_key)
|
|
|
|
{
|
|
|
|
evas_stringshare_del(im->cache_key);
|
|
|
|
im->cache_key = NULL;
|
|
|
|
}
|
|
|
|
cache->func.destructor(im);
|
|
|
|
evas_common_image_delete(im);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
2007-07-16 00:25:35 -07:00
|
|
|
|
|
|
|
im = evas_hash_find(cache->activ, hkey);
|
|
|
|
if (im)
|
2007-08-11 05:14:17 -07:00
|
|
|
{
|
|
|
|
if (st.st_mtime == im->timestamp)
|
|
|
|
goto on_ok;
|
|
|
|
}
|
2007-07-16 00:25:35 -07:00
|
|
|
|
|
|
|
im = evas_hash_find(cache->inactiv, hkey);
|
|
|
|
if (im)
|
|
|
|
{
|
2007-08-11 05:14:17 -07:00
|
|
|
if (st.st_mtime == im->timestamp)
|
|
|
|
{
|
|
|
|
cache->lru = evas_object_list_remove(cache->lru, im);
|
|
|
|
cache->inactiv = evas_hash_del(cache->inactiv, im->cache_key, im);
|
|
|
|
cache->activ = evas_hash_direct_add(cache->activ, im->cache_key, im);
|
|
|
|
cache->usage -= cache->func.mem_size_get(im);
|
|
|
|
goto on_ok;
|
|
|
|
}
|
2007-08-11 05:22:43 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
cache->lru = evas_object_list_remove(cache->lru, im);
|
|
|
|
cache->inactiv = evas_hash_del(cache->inactiv, im->cache_key, im);
|
|
|
|
cache->usage -= cache->func.mem_size_get(im);
|
|
|
|
if (im->cache_key)
|
|
|
|
{
|
|
|
|
evas_stringshare_del(im->cache_key);
|
|
|
|
im->cache_key = NULL;
|
|
|
|
}
|
|
|
|
cache->func.destructor(im);
|
|
|
|
evas_common_image_delete(im);
|
|
|
|
}
|
2007-07-16 00:25:35 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
im = evas_common_image_new();
|
|
|
|
if (!im)
|
|
|
|
{
|
|
|
|
*error = -1;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
im->timestamp = st.st_mtime;
|
|
|
|
im->laststat = time(NULL);
|
|
|
|
|
|
|
|
if (lo) im->load_opts = *lo;
|
|
|
|
|
|
|
|
im->info.file = (char *) evas_stringshare_add(file);
|
|
|
|
if (key) im->info.key = (char *) evas_stringshare_add(key);
|
|
|
|
|
|
|
|
*error = cache->func.constructor(im);
|
|
|
|
if (*error != 0)
|
|
|
|
{
|
|
|
|
evas_common_image_delete(im);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cache->func.debug)
|
|
|
|
cache->func.debug("request", im);
|
|
|
|
|
|
|
|
im->references = 0;
|
2007-08-09 07:44:36 -07:00
|
|
|
im->cache_key = evas_stringshare_add(hkey);
|
2007-07-16 00:25:35 -07:00
|
|
|
im->cache = cache;
|
2007-08-09 07:44:36 -07:00
|
|
|
|
|
|
|
cache->activ = evas_hash_direct_add(cache->activ, im->cache_key, im);
|
|
|
|
|
|
|
|
on_ok:
|
2007-07-16 00:25:35 -07:00
|
|
|
*error = 0;
|
|
|
|
im->references++;
|
|
|
|
return im;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
evas_cache_image_drop(RGBA_Image *im)
|
|
|
|
{
|
2007-08-12 22:30:17 -07:00
|
|
|
Evas_Cache_Image *cache;
|
2007-07-16 00:25:35 -07:00
|
|
|
|
|
|
|
assert(im);
|
|
|
|
assert(im->cache);
|
|
|
|
|
|
|
|
im->references--;
|
|
|
|
cache = im->cache;
|
|
|
|
|
2007-08-08 16:41:31 -07:00
|
|
|
// if (im->cache_key) printf("DROP %s -> ref = %i\n", im->cache_key, im->references);
|
2007-07-16 00:25:35 -07:00
|
|
|
if ((im->flags & RGBA_IMAGE_IS_DIRTY) == RGBA_IMAGE_IS_DIRTY)
|
|
|
|
{
|
2007-08-09 05:21:21 -07:00
|
|
|
cache->usage -= cache->func.mem_size_get(im);
|
2007-08-08 16:41:31 -07:00
|
|
|
// if (im->cache_key) printf("IM-- %s, cache = %i\n", im->cache_key, cache->usage);
|
2007-07-16 00:25:35 -07:00
|
|
|
cache->dirty = evas_object_list_remove(cache->dirty, im);
|
|
|
|
if (cache->func.debug)
|
|
|
|
cache->func.debug("drop", im);
|
|
|
|
|
|
|
|
cache->func.destructor(im);
|
|
|
|
evas_common_image_delete(im);
|
|
|
|
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (im->references == 0)
|
|
|
|
{
|
2007-08-09 07:44:36 -07:00
|
|
|
cache->activ = evas_hash_del(cache->activ, im->cache_key, im);
|
|
|
|
cache->inactiv = evas_hash_direct_add(cache->inactiv, im->cache_key, im);
|
2007-07-16 00:25:35 -07:00
|
|
|
cache->lru = evas_object_list_prepend(cache->lru, im);
|
|
|
|
|
2007-08-08 16:41:31 -07:00
|
|
|
cache->usage += cache->func.mem_size_get(im);
|
|
|
|
// printf("FLUSH!\n");
|
|
|
|
evas_cache_image_flush(cache);
|
2007-07-16 00:25:35 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-08-12 22:30:17 -07:00
|
|
|
EAPI RGBA_Image *
|
2007-07-16 00:25:35 -07:00
|
|
|
evas_cache_image_dirty(RGBA_Image *im, int x, int y, int w, int h)
|
|
|
|
{
|
2007-08-12 22:30:17 -07:00
|
|
|
RGBA_Image *im_dirty = im;
|
|
|
|
Evas_Cache_Image *cache;
|
2007-07-16 00:25:35 -07:00
|
|
|
|
|
|
|
assert(im);
|
|
|
|
assert(im->cache);
|
|
|
|
|
|
|
|
cache = im->cache;
|
|
|
|
if (!(im->flags & RGBA_IMAGE_IS_DIRTY))
|
|
|
|
{
|
|
|
|
if (im->references == 1)
|
|
|
|
{
|
2007-08-09 07:44:36 -07:00
|
|
|
if (im->cache_key)
|
|
|
|
{
|
|
|
|
cache->activ = evas_hash_del(cache->activ, im->cache_key, im);
|
|
|
|
evas_stringshare_del(im->cache_key);
|
|
|
|
im->cache_key = NULL;
|
|
|
|
}
|
2007-07-16 00:25:35 -07:00
|
|
|
im_dirty = im;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
|
|
|
|
im_dirty = evas_common_image_new();
|
|
|
|
if (!im_dirty) goto on_error;
|
|
|
|
im_dirty->image = evas_common_image_surface_new(im);
|
|
|
|
if (!im_dirty->image) goto on_error;
|
|
|
|
im_dirty->image->w = w;
|
|
|
|
im_dirty->image->h = h;
|
|
|
|
|
|
|
|
if (cache->func.debug)
|
|
|
|
cache->func.debug("dirty-src", im);
|
|
|
|
error = cache->func.dirty(im_dirty, im);
|
|
|
|
if (cache->func.debug)
|
|
|
|
cache->func.debug("dirty-out", im_dirty);
|
|
|
|
|
|
|
|
if (error != 0) goto on_error;
|
|
|
|
|
|
|
|
im_dirty->cache = cache;
|
|
|
|
im_dirty->references = 1;
|
|
|
|
|
|
|
|
evas_cache_image_drop(im);
|
|
|
|
}
|
|
|
|
|
|
|
|
im_dirty->flags |= RGBA_IMAGE_IS_DIRTY;
|
|
|
|
cache->dirty = evas_object_list_prepend(cache->dirty, im_dirty);
|
|
|
|
}
|
2007-08-09 07:44:36 -07:00
|
|
|
|
2007-07-16 00:25:35 -07:00
|
|
|
if (cache->func.debug)
|
|
|
|
cache->func.debug("dirty-region", im_dirty);
|
|
|
|
if (cache->func.dirty_region)
|
|
|
|
cache->func.dirty_region(im_dirty, x, y, w, h);
|
2007-08-09 07:44:36 -07:00
|
|
|
|
2007-07-16 00:25:35 -07:00
|
|
|
return im_dirty;
|
2007-08-09 07:44:36 -07:00
|
|
|
|
|
|
|
on_error:
|
2007-07-16 00:25:35 -07:00
|
|
|
if (im_dirty) evas_common_image_delete(im_dirty);
|
|
|
|
evas_cache_image_drop(im);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-08-12 22:30:17 -07:00
|
|
|
EAPI RGBA_Image *
|
2007-07-16 00:25:35 -07:00
|
|
|
evas_cache_image_alone(RGBA_Image *im)
|
|
|
|
{
|
2007-08-12 22:30:17 -07:00
|
|
|
RGBA_Image *im_dirty = im;
|
|
|
|
Evas_Cache_Image *cache;
|
2007-07-16 00:25:35 -07:00
|
|
|
|
|
|
|
assert(im);
|
|
|
|
assert(im->cache);
|
|
|
|
|
|
|
|
cache = im->cache;
|
|
|
|
if (im->references == 1)
|
|
|
|
{
|
|
|
|
if (!(im->flags & RGBA_IMAGE_IS_DIRTY))
|
|
|
|
{
|
2007-08-09 07:44:36 -07:00
|
|
|
if (im->cache_key)
|
|
|
|
{
|
|
|
|
cache->activ = evas_hash_del(cache->activ, im->cache_key, im);
|
|
|
|
evas_stringshare_del(im->cache_key);
|
|
|
|
im->cache_key = NULL;
|
|
|
|
}
|
|
|
|
im->flags |= RGBA_IMAGE_IS_DIRTY;
|
|
|
|
cache->dirty = evas_object_list_prepend(cache->dirty, im);
|
2007-07-16 00:25:35 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
|
|
|
|
im_dirty = evas_common_image_new();
|
|
|
|
if (!im_dirty) goto on_error;
|
|
|
|
im_dirty->image = evas_common_image_surface_new(im);
|
|
|
|
if (!im_dirty->image) goto on_error;
|
|
|
|
im_dirty->image->w = im->image->w;
|
|
|
|
im_dirty->image->h = im->image->h;
|
|
|
|
|
|
|
|
if (cache->func.debug)
|
|
|
|
cache->func.debug("dirty-src", im);
|
|
|
|
error = cache->func.dirty(im_dirty, im);
|
|
|
|
if (cache->func.debug)
|
|
|
|
cache->func.debug("dirty-out", im_dirty);
|
|
|
|
|
|
|
|
if (error != 0) goto on_error;
|
|
|
|
|
2007-08-09 07:44:36 -07:00
|
|
|
if (im_dirty->cache_key)
|
|
|
|
{
|
|
|
|
evas_stringshare_del(im_dirty->cache_key);
|
|
|
|
im_dirty->cache_key = NULL;
|
|
|
|
}
|
2007-07-16 00:25:35 -07:00
|
|
|
im_dirty->flags |= RGBA_IMAGE_IS_DIRTY;
|
|
|
|
im_dirty->references = 1;
|
|
|
|
|
|
|
|
cache->dirty = evas_object_list_prepend(cache->dirty, im_dirty);
|
|
|
|
|
|
|
|
evas_cache_image_drop(im);
|
|
|
|
}
|
|
|
|
|
|
|
|
return im_dirty;
|
2007-08-09 07:44:36 -07:00
|
|
|
|
|
|
|
on_error:
|
2007-07-16 00:25:35 -07:00
|
|
|
if (im_dirty) evas_common_image_delete(im_dirty);
|
|
|
|
evas_cache_image_drop(im);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-08-12 22:30:17 -07:00
|
|
|
static RGBA_Image *
|
|
|
|
_evas_cache_image_push_dirty(Evas_Cache_Image *cache, RGBA_Image *im)
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
|
|
|
cache->dirty = evas_object_list_prepend(cache->dirty, im);
|
|
|
|
|
|
|
|
im->flags |= RGBA_IMAGE_IS_DIRTY;
|
2007-08-09 07:44:36 -07:00
|
|
|
if (im->cache_key)
|
|
|
|
{
|
|
|
|
evas_stringshare_del(im->cache_key);
|
|
|
|
im->cache_key = NULL;
|
|
|
|
}
|
2007-07-16 00:25:35 -07:00
|
|
|
im->cache = cache;
|
|
|
|
return im;
|
|
|
|
}
|
|
|
|
|
2007-08-12 22:30:17 -07:00
|
|
|
EAPI RGBA_Image *
|
2007-07-16 00:25:35 -07:00
|
|
|
evas_cache_image_copied_data(Evas_Cache_Image *cache, int w, int h, DATA32 *image_data, int alpha, int cspace)
|
|
|
|
{
|
2007-08-12 22:30:17 -07:00
|
|
|
RGBA_Image *im;
|
2007-07-16 00:25:35 -07:00
|
|
|
|
|
|
|
assert(cache);
|
|
|
|
|
2007-08-08 16:41:31 -07:00
|
|
|
if ((cspace == EVAS_COLORSPACE_YCBCR422P601_PL) ||
|
|
|
|
(cspace == EVAS_COLORSPACE_YCBCR422P709_PL))
|
2007-07-16 00:25:35 -07:00
|
|
|
w &= ~0x1;
|
|
|
|
|
|
|
|
im = evas_common_image_create(w, h);
|
|
|
|
if (!im) return NULL;
|
|
|
|
|
|
|
|
if (cache->func.copied_data(im, w, h, image_data, alpha, cspace) != 0)
|
|
|
|
{
|
|
|
|
evas_common_image_delete(im);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return _evas_cache_image_push_dirty(cache, im);
|
|
|
|
}
|
|
|
|
|
2007-08-12 22:30:17 -07:00
|
|
|
EAPI RGBA_Image *
|
2007-07-16 00:25:35 -07:00
|
|
|
evas_cache_image_data(Evas_Cache_Image *cache, int w, int h, DATA32 *image_data, int alpha, int cspace)
|
|
|
|
{
|
2007-08-12 22:30:17 -07:00
|
|
|
RGBA_Image *im;
|
2007-07-16 00:25:35 -07:00
|
|
|
|
|
|
|
assert(cache);
|
|
|
|
|
|
|
|
im = evas_common_image_new();
|
|
|
|
if (!im) return NULL;
|
|
|
|
im->image = evas_common_image_surface_new(im);
|
|
|
|
if (!im->image)
|
|
|
|
{
|
|
|
|
evas_common_image_delete(im);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cache->func.data(im, w, h, image_data, alpha, cspace) != 0)
|
|
|
|
{
|
|
|
|
evas_common_image_delete(im);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return _evas_cache_image_push_dirty(cache, im);
|
|
|
|
}
|
|
|
|
|
2007-08-12 22:30:17 -07:00
|
|
|
EAPI RGBA_Image *
|
2007-07-16 00:25:35 -07:00
|
|
|
evas_cache_image_size_set(RGBA_Image *im, int w, int h)
|
|
|
|
{
|
2007-08-12 22:30:17 -07:00
|
|
|
Evas_Cache_Image *cache;
|
|
|
|
RGBA_Image *new;
|
2007-07-16 00:25:35 -07:00
|
|
|
int error;
|
|
|
|
|
|
|
|
assert(im);
|
|
|
|
assert(im->image);
|
|
|
|
assert(im->cache);
|
|
|
|
assert(im->references > 0);
|
|
|
|
|
2007-08-09 07:44:36 -07:00
|
|
|
if ((im->image->w == w) && (im->image->h == h))
|
2007-07-16 00:25:35 -07:00
|
|
|
return im;
|
|
|
|
|
|
|
|
cache = im->cache;
|
|
|
|
|
|
|
|
new = evas_common_image_new();
|
|
|
|
if (!new) goto on_error;
|
|
|
|
new->image = evas_common_image_surface_new(im);
|
|
|
|
if (!new->image) goto on_error;
|
|
|
|
new->image->w = w;
|
|
|
|
new->image->h = h;
|
|
|
|
|
|
|
|
if (cache->func.debug)
|
|
|
|
cache->func.debug("size_set-in", im);
|
|
|
|
error = cache->func.size_set(new, im, w, h);
|
|
|
|
if (cache->func.debug)
|
|
|
|
cache->func.debug("size_set-out", new);
|
|
|
|
|
|
|
|
if (error != 0) goto on_error;
|
|
|
|
|
|
|
|
new->cache = cache;
|
|
|
|
new->cache_key = NULL;
|
|
|
|
|
|
|
|
new->references = 1;
|
2007-08-08 16:41:31 -07:00
|
|
|
// cache->usage += cache->func.mem_size_get(new);
|
2007-07-16 00:25:35 -07:00
|
|
|
|
2007-08-09 07:44:36 -07:00
|
|
|
if (((im->flags & RGBA_IMAGE_IS_DIRTY) == RGBA_IMAGE_IS_DIRTY)
|
|
|
|
|| (im->references > 1))
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
|
|
|
new->flags |= RGBA_IMAGE_IS_DIRTY;
|
|
|
|
cache->dirty = evas_object_list_prepend(cache->dirty, new);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-08-09 07:44:36 -07:00
|
|
|
new->cache_key = im->cache_key ? evas_stringshare_add(im->cache_key) : NULL;
|
|
|
|
cache->activ = evas_hash_direct_add(cache->activ, new->cache_key, new);
|
2007-07-16 00:25:35 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
evas_cache_image_drop(im);
|
2007-08-09 07:44:36 -07:00
|
|
|
|
2007-07-16 00:25:35 -07:00
|
|
|
return new;
|
2007-08-09 07:44:36 -07:00
|
|
|
|
|
|
|
on_error:
|
2007-07-16 00:25:35 -07:00
|
|
|
if (new) evas_common_image_delete(new);
|
|
|
|
evas_cache_image_drop(im);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
evas_cache_image_load_data(RGBA_Image *im)
|
|
|
|
{
|
2007-08-12 22:30:17 -07:00
|
|
|
Evas_Cache_Image *cache;
|
2007-07-16 00:25:35 -07:00
|
|
|
|
|
|
|
assert(im);
|
|
|
|
assert(im->image);
|
|
|
|
assert(im->cache);
|
|
|
|
|
|
|
|
if ((im->flags & RGBA_IMAGE_LOADED) == RGBA_IMAGE_LOADED) return ;
|
2007-08-09 07:44:36 -07:00
|
|
|
|
2007-07-16 00:25:35 -07:00
|
|
|
cache = im->cache;
|
|
|
|
if (cache->func.debug)
|
|
|
|
cache->func.debug("load", im);
|
|
|
|
|
|
|
|
cache->func.load(im);
|
|
|
|
im->flags |= RGBA_IMAGE_LOADED;
|
|
|
|
|
|
|
|
assert(im->image->data);
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI int
|
|
|
|
evas_cache_image_flush(Evas_Cache_Image *cache)
|
|
|
|
{
|
|
|
|
assert(cache);
|
|
|
|
|
|
|
|
if (cache->limit == -1)
|
|
|
|
return -1;
|
|
|
|
|
2007-08-08 16:41:31 -07:00
|
|
|
while ((cache->lru) && (cache->limit < cache->usage))
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
2007-08-12 22:30:17 -07:00
|
|
|
RGBA_Image *im;
|
2007-07-16 00:25:35 -07:00
|
|
|
|
2007-08-12 22:30:17 -07:00
|
|
|
im = (RGBA_Image *) cache->lru->last;
|
2007-07-16 00:25:35 -07:00
|
|
|
cache->lru = evas_object_list_remove(cache->lru, im);
|
|
|
|
cache->inactiv = evas_hash_del(cache->inactiv, im->cache_key, im);
|
|
|
|
cache->usage -= cache->func.mem_size_get(im);
|
|
|
|
|
2007-08-09 07:44:36 -07:00
|
|
|
if (im->cache_key)
|
|
|
|
{
|
|
|
|
evas_stringshare_del(im->cache_key);
|
|
|
|
im->cache_key = NULL;
|
|
|
|
}
|
2007-07-16 00:25:35 -07:00
|
|
|
cache->func.destructor(im);
|
|
|
|
evas_common_image_delete(im);
|
|
|
|
}
|
|
|
|
return cache->usage;
|
|
|
|
}
|
|
|
|
|
2007-08-12 22:30:17 -07:00
|
|
|
EAPI RGBA_Image *
|
|
|
|
evas_cache_image_empty(Evas_Cache_Image *cache)
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
2007-08-12 22:30:17 -07:00
|
|
|
RGBA_Image *new;
|
2007-07-16 00:25:35 -07:00
|
|
|
|
|
|
|
new = evas_common_image_new();
|
|
|
|
if (!new) goto on_error;
|
|
|
|
new->image = evas_common_image_surface_new(new);
|
|
|
|
if (!new->image) goto on_error;
|
|
|
|
|
|
|
|
new->cache = cache;
|
|
|
|
new->references = 1;
|
|
|
|
|
|
|
|
new->cache_key = NULL;
|
|
|
|
new->flags |= RGBA_IMAGE_IS_DIRTY;
|
|
|
|
|
|
|
|
cache->dirty = evas_object_list_prepend(cache->dirty, new);
|
|
|
|
|
|
|
|
return new;
|
|
|
|
|
|
|
|
on_error:
|
|
|
|
if (new) evas_common_image_delete(new);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2007-08-12 22:30:17 -07:00
|
|
|
evas_cache_image_colorspace(RGBA_Image *im, int cspace)
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
|
|
|
if (!im) return ;
|
|
|
|
if (im->cs.space == cspace) return ;
|
|
|
|
|
|
|
|
evas_common_image_colorspace_set(im, cspace);
|
|
|
|
}
|