evas: add infrastructure to open from Eina_File.

This commit is contained in:
Cedric Bail 2013-05-08 15:37:37 +09:00
parent ba46068c09
commit d833244100
16 changed files with 493 additions and 169 deletions

View File

@ -5474,6 +5474,7 @@ enum
{
EVAS_OBJ_IMAGE_SUB_ID_MEMFILE_SET,
EVAS_OBJ_IMAGE_SUB_ID_FILE_SET,
EVAS_OBJ_IMAGE_SUB_ID_MMAP_SET,
EVAS_OBJ_IMAGE_SUB_ID_FILE_GET,
EVAS_OBJ_IMAGE_SUB_ID_SOURCE_SET,
EVAS_OBJ_IMAGE_SUB_ID_SOURCE_GET,
@ -5583,6 +5584,20 @@ enum
*/
#define evas_obj_image_file_set(file, key) EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_FILE_SET), EO_TYPECHECK(const char *, file), EO_TYPECHECK(const char*, key)
/**
* @def evas_obj_image_mmap_set
* @since 1.8
*
* Set the source mmaped file from where an image object must fetch the real
* image data (it may be any Eina_File).
*
* @param[in] file in
* @param[in] key in
*
* @see evas_obj_image_file_set
*/
#define evas_obj_image_mmap_set(f, key) EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_MMAP_SET), EO_TYPECHECK(Eina_File *, f), EO_TYPECHECK(const char*, key)
/**
* @def evas_obj_image_file_get
* @since 1.8

View File

@ -3912,6 +3912,23 @@ EAPI void evas_object_image_memfile_set(Evas_Object *ob
*/
EAPI void evas_object_image_file_set(Evas_Object *obj, const char *file, const char *key) EINA_ARG_NONNULL(1);
/**
* Set the source mmaped file from where an image object must fetch the real
* image data (it must be an Eina_File).
*
* @param obj The given image object.
* @param f The mmaped file
* @param key The image key in @p file (if its an Eet one), or @c
* NULL, otherwise.
*
* If the file supports multiple data stored in it (as Eet files do),
* you can specify the key to be used as the index of the image in
* this file.
*
* @since 1.8
*/
EAPI void evas_object_image_mmap_set(Evas_Object *eo_obj, Eina_File *f, const char *key);
/**
* Retrieve the source file from where an image object is to fetch the
* real image data (it may be an Eet file, besides pure image ones).

View File

@ -55,6 +55,12 @@ struct _Evas_Cache_Image
Eina_Inlist *lru_nodata;
Eina_Hash *inactiv;
Eina_Hash *activ;
Eina_Hash *mmap_activ;
Eina_Hash *mmap_inactiv;
Eina_Inlist *mmap_lru;
Eina_Inlist *mmap_lru_nodata;
void *data;
int usage;
@ -90,14 +96,14 @@ struct _Evas_Cache_Engine_Image
{
Evas_Cache_Engine_Image_Func func;
Eina_Inlist* dirty;
Eina_Inlist *dirty;
Eina_Hash* activ;
Eina_Hash* inactiv;
Eina_Inlist* lru;
Eina_Hash *activ;
Eina_Hash *inactiv;
Eina_Inlist *lru;
Evas_Cache_Image* parent;
Evas_Cache_Engine_Image* brother;
Evas_Cache_Image *parent;
Evas_Cache_Engine_Image *brother;
int usage;
int limit;
@ -114,6 +120,7 @@ extern "C" {
EAPI Evas_Cache_Image* evas_cache_image_init(const Evas_Cache_Image_Func *cb);
EAPI void evas_cache_image_shutdown(Evas_Cache_Image *cache);
EAPI Image_Entry* evas_cache_image_request(Evas_Cache_Image *cache, const char *file, const char *key, Evas_Image_Load_Opts *lo, int *error);
EAPI Image_Entry* evas_cache_image_mmap_request(Evas_Cache_Image *cache, Eina_File *f, const char *key, Evas_Image_Load_Opts *lo, int *error);
EAPI void evas_cache_image_ref(Image_Entry *im);
EAPI void evas_cache_image_drop(Image_Entry *im);
EAPI void evas_cache_image_data_not_needed(Image_Entry *im);

View File

@ -72,7 +72,7 @@ _evas_cache_image_dirty_del(Image_Entry *im)
if (!im->flags.dirty) return;
im->flags.dirty = 0;
im->flags.cached = 0;
im->cache->dirty = eina_inlist_remove(im->cache->dirty, EINA_INLIST_GET(im));
im->cache->dirty = eina_inlist_remove(im->cache->dirty, EINA_INLIST_GET(im));
}
static void
@ -85,7 +85,10 @@ _evas_cache_image_activ_add(Image_Entry *im)
if (!im->cache_key) return;
im->flags.activ = 1;
im->flags.cached = 1;
eina_hash_direct_add(im->cache->activ, im->cache_key, im);
if (im->flags.given_mmap)
eina_hash_direct_add(im->cache->mmap_activ, im->cache_key, im);
else
eina_hash_direct_add(im->cache->activ, im->cache_key, im);
}
static void
@ -95,7 +98,10 @@ _evas_cache_image_activ_del(Image_Entry *im)
if (!im->cache_key) return;
im->flags.activ = 0;
im->flags.cached = 0;
eina_hash_del(im->cache->activ, im->cache_key, im);
if (im->flags.given_mmap)
eina_hash_del(im->cache->mmap_activ, im->cache_key, im);
else
eina_hash_del(im->cache->activ, im->cache_key, im);
}
static void
@ -108,8 +114,16 @@ _evas_cache_image_lru_add(Image_Entry *im)
if (!im->cache_key) return;
im->flags.lru = 1;
im->flags.cached = 1;
eina_hash_direct_add(im->cache->inactiv, im->cache_key, im);
im->cache->lru = eina_inlist_prepend(im->cache->lru, EINA_INLIST_GET(im));
if (im->flags.given_mmap)
{
eina_hash_direct_add(im->cache->mmap_inactiv, im->cache_key, im);
im->cache->mmap_lru = eina_inlist_prepend(im->cache->mmap_lru, EINA_INLIST_GET(im));
}
else
{
eina_hash_direct_add(im->cache->inactiv, im->cache_key, im);
im->cache->lru = eina_inlist_prepend(im->cache->lru, EINA_INLIST_GET(im));
}
im->cache->usage += im->cache->func.mem_size_get(im);
}
@ -120,8 +134,16 @@ _evas_cache_image_lru_del(Image_Entry *im)
if (!im->cache_key) return;
im->flags.lru = 0;
im->flags.cached = 0;
eina_hash_del(im->cache->inactiv, im->cache_key, im);
im->cache->lru = eina_inlist_remove(im->cache->lru, EINA_INLIST_GET(im));
if (im->flags.given_mmap)
{
eina_hash_del(im->cache->mmap_inactiv, im->cache_key, im);
im->cache->mmap_lru = eina_inlist_remove(im->cache->mmap_lru, EINA_INLIST_GET(im));
}
else
{
eina_hash_del(im->cache->inactiv, im->cache_key, im);
im->cache->lru = eina_inlist_remove(im->cache->lru, EINA_INLIST_GET(im));
}
im->cache->usage -= im->cache->func.mem_size_get(im);
}
@ -134,7 +156,10 @@ _evas_cache_image_lru_nodata_add(Image_Entry *im)
_evas_cache_image_lru_del(im);
im->flags.lru = 1;
im->flags.cached = 1;
im->cache->lru_nodata = eina_inlist_prepend(im->cache->lru_nodata, EINA_INLIST_GET(im));
if (im->flags.given_mmap)
im->cache->mmap_lru_nodata = eina_inlist_prepend(im->cache->mmap_lru_nodata, EINA_INLIST_GET(im));
else
im->cache->lru_nodata = eina_inlist_prepend(im->cache->lru_nodata, EINA_INLIST_GET(im));
}
static void
@ -143,7 +168,10 @@ _evas_cache_image_lru_nodata_del(Image_Entry *im)
if (!im->flags.lru_nodata) return;
im->flags.lru = 0;
im->flags.cached = 0;
im->cache->lru_nodata = eina_inlist_remove(im->cache->lru_nodata, EINA_INLIST_GET(im));
if (im->flags.given_mmap)
im->cache->mmap_lru_nodata = eina_inlist_remove(im->cache->mmap_lru_nodata, EINA_INLIST_GET(im));
else
im->cache->lru_nodata = eina_inlist_remove(im->cache->lru_nodata, EINA_INLIST_GET(im));
}
static void
@ -213,6 +241,7 @@ static Image_Entry *
_evas_cache_image_entry_new(Evas_Cache_Image *cache,
const char *hkey,
Image_Timestamp *tstamp,
Eina_File *f,
const char *file,
const char *key,
Evas_Image_Load_Opts *lo,
@ -233,6 +262,9 @@ _evas_cache_image_entry_new(Evas_Cache_Image *cache,
ie->w = -1;
ie->h = -1;
ie->scale = 1;
ie->f = f;
ie->loader_data = NULL;
if (ie->f) ie->flags.given_mmap = EINA_TRUE;
if (file) ie->file = eina_stringshare_add(file);
if (key) ie->key = eina_stringshare_add(key);
if (tstamp) ie->tstamp = *tstamp;
@ -242,7 +274,7 @@ _evas_cache_image_entry_new(Evas_Cache_Image *cache,
LKI(ie->lock_cancel);
if (lo) ie->load_opts = *lo;
if (ie->file)
if (ie->file || ie->f)
{
*error = cache->func.constructor(ie);
if (*error != EVAS_LOAD_ERROR_NONE)
@ -485,6 +517,8 @@ evas_cache_image_init(const Evas_Cache_Image_Func *cb)
cache->func = *cb;
cache->inactiv = eina_hash_string_superfast_new(NULL);
cache->activ = eina_hash_string_superfast_new(NULL);
cache->mmap_activ = eina_hash_string_superfast_new(NULL);
cache->mmap_inactiv = eina_hash_string_superfast_new(NULL);
cache->references = 1;
return cache;
}
@ -534,6 +568,9 @@ evas_cache_image_shutdown(Evas_Cache_Image *cache)
}
delete_list = NULL;
eina_hash_foreach(cache->activ, _evas_cache_image_free_cb, &delete_list);
eina_hash_foreach(cache->mmap_activ, _evas_cache_image_free_cb, &delete_list);
eina_hash_foreach(cache->inactiv, _evas_cache_image_free_cb, &delete_list);
eina_hash_foreach(cache->mmap_inactiv, _evas_cache_image_free_cb, &delete_list);
while (delete_list)
{
_evas_cache_image_entry_delete(cache, eina_list_data_get(delete_list));
@ -553,6 +590,8 @@ evas_cache_image_shutdown(Evas_Cache_Image *cache)
}
eina_hash_free(cache->activ);
eina_hash_free(cache->inactiv);
eina_hash_free(cache->mmap_activ);
eina_hash_free(cache->mmap_inactiv);
free(cache);
if (--_evas_cache_mutex_init == 0)
@ -563,6 +602,140 @@ evas_cache_image_shutdown(Evas_Cache_Image *cache)
}
}
static const Evas_Image_Load_Opts prevent = {
{ 0, 0, 0, 0 },
{
0, 0, 0, 0,
0, 0,
0,
0
},
0.0,
0, 0,
0,
0,
EINA_FALSE
};
static size_t
_evas_cache_image_loadopts_append(char *hkey, Evas_Image_Load_Opts **plo)
{
Evas_Image_Load_Opts *lo = *plo;
size_t offset = 0;
if ((!lo) ||
(lo &&
(lo->scale_down_by == 0) &&
(lo->dpi == 0.0) &&
((lo->w == 0) || (lo->h == 0)) &&
((lo->region.w == 0) || (lo->region.h == 0)) &&
(lo->orientation == 0)
))
{
*plo = (Evas_Image_Load_Opts*) &prevent;
}
else
{
memcpy(hkey, "//@/", 4);
offset += 4;
offset += eina_convert_xtoa(lo->scale_down_by, hkey + offset);
hkey[offset] = '/';
offset += 1;
offset += eina_convert_dtoa(lo->dpi, hkey + offset);
hkey[offset] = '/';
offset += 1;
offset += eina_convert_xtoa(lo->w, hkey + offset);
hkey[offset] = 'x';
offset += 1;
offset += eina_convert_xtoa(lo->h, hkey + offset);
hkey[offset] = '/';
offset += 1;
offset += eina_convert_xtoa(lo->region.x, hkey + offset);
hkey[offset] = '+';
offset += 1;
offset += eina_convert_xtoa(lo->region.y, hkey + offset);
hkey[offset] = '.';
offset += 1;
offset += eina_convert_xtoa(lo->region.w, hkey + offset);
hkey[offset] = 'x';
offset += 1;
offset += eina_convert_xtoa(lo->region.h, hkey + offset);
if (lo->orientation)
{
hkey[offset] = '/';
offset += 1;
hkey[offset] = 'o';
offset += 1;
}
}
hkey[offset] = '\0';
return offset;
}
EAPI Image_Entry *
evas_cache_image_mmap_request(Evas_Cache_Image *cache,
Eina_File *f, const char *key,
Evas_Image_Load_Opts *lo, int *error)
{
const char *hexcode = "0123456789abcdef";
const char *ckey = "(null)";
char *hkey;
char *pf;
Image_Entry *im;
size_t size;
size_t file_length;
size_t key_length;
unsigned int i;
// FIXME: In the long term we should certainly merge both mmap and filename path
// by just using the mmap path. But for the time being, let's just have two path
// as it is unlikely to really have an impact on real world application
if ((!f) || (!f && !key))
{
*error = EVAS_LOAD_ERROR_GENERIC;
return NULL;
}
/* generate hkey from file+key+load opts */
file_length = sizeof (Eina_File*) * 2;
key_length = key ? strlen(key) : 6;
size = file_length + key_length + 132;
hkey = alloca(sizeof (char) * size);
pf = (char*) &f;
for (size = 0, i = 0; i < sizeof (Eina_File*); i++)
{
hkey[size++] = hexcode[(pf[i] & 0xF0) >> 4];
hkey[size++] = hexcode[(pf[i] & 0x0F)];
}
memcpy(hkey + size, "//://", 5);
size += 5;
if (key) ckey = key;
memcpy(hkey + size, ckey, key_length);
size += key_length;
size += _evas_cache_image_loadopts_append(hkey + size, &lo);
/* find image by key in active mmap hash */
im = eina_hash_find(cache->mmap_activ, hkey);
if (im) goto on_ok;
/* find image by key in inactive/lru hash */
im = eina_hash_find(cache->mmap_inactiv, hkey);
if (im) goto on_ok;
im = _evas_cache_image_entry_new(cache, hkey, NULL, f, NULL, key, lo, error);
if (!im) return NULL;
on_ok:
*error = EVAS_LOAD_ERROR_NONE;
im->references++;
return im;
}
EAPI Image_Entry *
evas_cache_image_request(Evas_Cache_Image *cache, const char *file,
const char *key, Evas_Image_Load_Opts *lo, int *error)
@ -570,7 +743,6 @@ evas_cache_image_request(Evas_Cache_Image *cache, const char *file,
const char *ckey = "(null)";
char *hkey;
Image_Entry *im;
Evas_Image_Load_Opts prevent;
size_t size;
int stat_done = 0, stat_failed = 0;
size_t file_length;
@ -584,8 +756,6 @@ evas_cache_image_request(Evas_Cache_Image *cache, const char *file,
return NULL;
}
memset(&prevent, 0, sizeof prevent);
/* generate hkey from file+key+load opts */
file_length = strlen(file);
key_length = key ? strlen(key) : 6;
@ -598,53 +768,7 @@ evas_cache_image_request(Evas_Cache_Image *cache, const char *file,
if (key) ckey = key;
memcpy(hkey + size, ckey, key_length);
size += key_length;
if ((!lo) ||
(lo &&
(lo->scale_down_by == 0) &&
(lo->dpi == 0.0) &&
((lo->w == 0) || (lo->h == 0)) &&
((lo->region.w == 0) || (lo->region.h == 0)) &&
(lo->orientation == 0)
))
{
lo = &prevent;
}
else
{
memcpy(hkey + size, "//@/", 4);
size += 4;
size += eina_convert_xtoa(lo->scale_down_by, hkey + size);
hkey[size] = '/';
size += 1;
size += eina_convert_dtoa(lo->dpi, hkey + size);
hkey[size] = '/';
size += 1;
size += eina_convert_xtoa(lo->w, hkey + size);
hkey[size] = 'x';
size += 1;
size += eina_convert_xtoa(lo->h, hkey + size);
hkey[size] = '/';
size += 1;
size += eina_convert_xtoa(lo->region.x, hkey + size);
hkey[size] = '+';
size += 1;
size += eina_convert_xtoa(lo->region.y, hkey + size);
hkey[size] = '.';
size += 1;
size += eina_convert_xtoa(lo->region.w, hkey + size);
hkey[size] = 'x';
size += 1;
size += eina_convert_xtoa(lo->region.h, hkey + size);
if (lo->orientation)
{
hkey[size] = '/';
size += 1;
hkey[size] = 'o';
size += 1;
}
}
hkey[size] = '\0';
size += _evas_cache_image_loadopts_append(hkey + size, &lo);
/* find image by key in active hash */
im = eina_hash_find(cache->activ, hkey);
@ -707,7 +831,7 @@ evas_cache_image_request(Evas_Cache_Image *cache, const char *file,
if (stat(file, &st) < 0) goto on_stat_error;
}
_timestamp_build(&tstamp, &st);
im = _evas_cache_image_entry_new(cache, hkey, &tstamp, file, key,
im = _evas_cache_image_entry_new(cache, hkey, &tstamp, NULL, file, key,
lo, error);
if (!im) goto on_stat_error;
if (cache->func.debug) cache->func.debug("request", im);
@ -866,7 +990,7 @@ evas_cache_image_copied_data(Evas_Cache_Image *cache,
(cspace == EVAS_COLORSPACE_YCBCR422601_PL))
w &= ~0x1;
im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL);
im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (!im) return NULL;
im->space = cspace;
im->flags.alpha = alpha;
@ -892,7 +1016,7 @@ evas_cache_image_data(Evas_Cache_Image *cache, unsigned int w, unsigned int h, D
(cspace == EVAS_COLORSPACE_YCBCR422601_PL))
w &= ~0x1;
im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL);
im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (!im) return NULL;
im->w = w;
im->h = h;
@ -936,7 +1060,7 @@ evas_cache_image_size_set(Image_Entry *im, unsigned int w, unsigned int h)
if ((im->w == w) && (im->h == h)) return im;
cache = im->cache;
im2 = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, &error);
im2 = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL, &error);
if (!im2) goto on_error;
im2->flags.alpha = im->flags.alpha;
@ -1021,7 +1145,7 @@ evas_cache_image_unload_data(Image_Entry *im)
}
LKU(im->lock_cancel);
if ((!im->flags.loaded) || (!im->file) || (!im->info.module) ||
if ((!im->flags.loaded) || (!im->file && !im->f) || (!im->info.module) ||
(im->flags.dirty))
{
LKU(im->lock);
@ -1091,7 +1215,7 @@ _dump_img(Image_Entry *im, const char *type)
im->references,
im->cache->func.mem_size_get(im),
im->w, im->h, im->allocated.w, im->allocated.h,
im->file, im->key);
im->f ? eina_file_filename_get(im->f) : im->file, im->key);
}
static Eina_Bool
@ -1159,7 +1283,7 @@ evas_cache_image_empty(Evas_Cache_Image *cache)
{
Image_Entry *im;
im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL);
im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (!im) return NULL;
im->references = 1;
return im;

View File

@ -85,6 +85,7 @@ struct _Evas_Object_Image_State
Evas_Map *defmap;
const char *file;
const char *key;
Eina_File *f;
int frame;
int spread;
@ -196,7 +197,7 @@ static const Evas_Object_Image_State default_state = {
{ 0, 0, 0 }, // image
{ 1.0, 0, 0, 0, 0, 1 }, // border
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
0,
EVAS_TEXTURE_REPEAT,
EVAS_COLORSPACE_ARGB8888,
@ -483,51 +484,18 @@ _image_memfile_set(Eo *eo_obj, void *_pd, va_list *list)
}
}
EAPI void
evas_object_image_file_set(Evas_Object *eo_obj, const char *file, const char *key)
{
MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
return;
MAGIC_CHECK_END();
eo_do(eo_obj, evas_obj_image_file_set(file, key));
}
static void
_image_file_set(Eo *eo_obj, void *_pd, va_list *list)
_image_init_set(Eina_File *f, const char *file, const char *key,
Eo *eo_obj, Evas_Object_Protected_Data *obj, Evas_Object_Image *o,
Evas_Image_Load_Opts *lo)
{
Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJ_CLASS);
Evas_Object_Image *o = _pd;
Evas_Image_Load_Opts lo;
Eina_Bool resize_call = EINA_FALSE;
const char *file = va_arg(*list, const char*);
const char *key = va_arg(*list, const char*);
if ((o->pixels->tmpf) && (file != o->pixels->tmpf)) _cleanup_tmpf(eo_obj);
if ((o->cur->file) && (file) && (!strcmp(o->cur->file, file)))
{
if ((!o->cur->key) && (!key))
return;
if ((o->cur->key) && (key) && (!strcmp(o->cur->key, key)))
return;
}
/*
* WTF? why cancel a null image preload? this is just silly (tm)
if (!o->engine_data)
obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
o->engine_data,
eo_obj);
*/
if (o->cur->source) _proxy_unset(eo_obj, obj, o);
EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
{
if (o->cur->file) eina_stringshare_del(state_write->file);
if (o->cur->key) eina_stringshare_del(o->cur->key);
if (file) state_write->file = eina_stringshare_add(file);
else state_write->file = NULL;
if (key) state_write->key = eina_stringshare_add(key);
else state_write->key = NULL;
eina_stringshare_replace(&state_write->file, file);
eina_stringshare_replace(&state_write->key, key);
state_write->f = f;
}
EINA_COW_IMAGE_STATE_WRITE_END(o, state_write);
@ -535,9 +503,10 @@ _image_file_set(Eo *eo_obj, void *_pd, va_list *list)
{
state_write->file = NULL;
state_write->key = NULL;
state_write->f = NULL;
}
EINA_COW_WRITE_END(evas_object_image_state_cow, o->prev, state_write);
if (o->engine_data)
{
if (o->preloading)
@ -548,28 +517,30 @@ _image_file_set(Eo *eo_obj, void *_pd, va_list *list)
obj->layer->evas->engine.func->image_free(obj->layer->evas->engine.data.output, o->engine_data);
}
o->load_error = EVAS_LOAD_ERROR_NONE;
lo.scale_down_by = o->load_opts->scale_down_by;
lo.dpi = o->load_opts->dpi;
lo.w = o->load_opts->w;
lo.h = o->load_opts->h;
lo.region.x = o->load_opts->region.x;
lo.region.y = o->load_opts->region.y;
lo.region.w = o->load_opts->region.w;
lo.region.h = o->load_opts->region.h;
lo.scale_load.src_x = o->load_opts->scale_load.src_x;
lo.scale_load.src_y = o->load_opts->scale_load.src_y;
lo.scale_load.src_w = o->load_opts->scale_load.src_w;
lo.scale_load.src_h = o->load_opts->scale_load.src_h;
lo.scale_load.dst_w = o->load_opts->scale_load.dst_w;
lo.scale_load.dst_h = o->load_opts->scale_load.dst_h;
lo.scale_load.smooth = o->load_opts->scale_load.smooth;
lo.scale_load.scale_hint = o->load_opts->scale_load.scale_hint;
lo.orientation = o->load_opts->orientation;
o->engine_data = obj->layer->evas->engine.func->image_load(obj->layer->evas->engine.data.output,
o->cur->file,
o->cur->key,
&o->load_error,
&lo);
lo->scale_down_by = o->load_opts->scale_down_by;
lo->dpi = o->load_opts->dpi;
lo->w = o->load_opts->w;
lo->h = o->load_opts->h;
lo->region.x = o->load_opts->region.x;
lo->region.y = o->load_opts->region.y;
lo->region.w = o->load_opts->region.w;
lo->region.h = o->load_opts->region.h;
lo->scale_load.src_x = o->load_opts->scale_load.src_x;
lo->scale_load.src_y = o->load_opts->scale_load.src_y;
lo->scale_load.src_w = o->load_opts->scale_load.src_w;
lo->scale_load.src_h = o->load_opts->scale_load.src_h;
lo->scale_load.dst_w = o->load_opts->scale_load.dst_w;
lo->scale_load.dst_h = o->load_opts->scale_load.dst_h;
lo->scale_load.smooth = o->load_opts->scale_load.smooth;
lo->scale_load.scale_hint = o->load_opts->scale_load.scale_hint;
lo->orientation = o->load_opts->orientation;
}
static void
_image_done_set(Eo *eo_obj, Evas_Object_Protected_Data *obj, Evas_Object_Image *o)
{
Eina_Bool resize_call = EINA_FALSE;
if (o->engine_data)
{
int w, h;
@ -619,6 +590,83 @@ _image_file_set(Eo *eo_obj, void *_pd, va_list *list)
evas_object_change(eo_obj, obj);
}
EAPI void
evas_object_image_mmap_set(Evas_Object *eo_obj, Eina_File *f, const char *key)
{
eo_do(eo_obj, evas_obj_image_mmap_set(f, key));
}
static void
_image_mmap_set(Eo *eo_obj, void *_pd, va_list *list)
{
Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJ_CLASS);
Evas_Object_Image *o = _pd;
Evas_Image_Load_Opts lo;
Eina_File *f = va_arg(*list, Eina_File *);
const char *key = va_arg(*list, const char*);
if (o->pixels->tmpf) _cleanup_tmpf(eo_obj);
if (o->cur->f == f)
{
if ((!o->cur->key) && (!key))
return;
if ((o->cur->key) && (key) && (!strcmp(o->cur->key, key)))
return;
}
_image_init_set(f, NULL, key, eo_obj, obj, o, &lo);
o->engine_data = obj->layer->evas->engine.func->image_mmap(obj->layer->evas->engine.data.output,
o->cur->f,
o->cur->key,
&o->load_error,
&lo);
_image_done_set(eo_obj, obj, o);
}
EAPI void
evas_object_image_file_set(Evas_Object *eo_obj, const char *file, const char *key)
{
MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
return;
MAGIC_CHECK_END();
eo_do(eo_obj, evas_obj_image_file_set(file, key));
}
static void
_image_file_set(Eo *eo_obj, void *_pd, va_list *list)
{
Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJ_CLASS);
Evas_Object_Image *o = _pd;
Evas_Image_Load_Opts lo;
const char *file = va_arg(*list, const char*);
const char *key = va_arg(*list, const char*);
if ((o->pixels->tmpf) && (file != o->pixels->tmpf)) _cleanup_tmpf(eo_obj);
if ((o->cur->file) && (file) && (!strcmp(o->cur->file, file)))
{
if ((!o->cur->key) && (!key))
return;
if ((o->cur->key) && (key) && (!strcmp(o->cur->key, key)))
return;
}
/*
* WTF? why cancel a null image preload? this is just silly (tm)
if (!o->engine_data)
obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
o->engine_data,
eo_obj);
*/
_image_init_set(NULL, file, key, eo_obj, obj, o, &lo);
o->engine_data = obj->layer->evas->engine.func->image_load(obj->layer->evas->engine.data.output,
o->cur->file,
o->cur->key,
&o->load_error,
&lo);
_image_done_set(eo_obj, obj, o);
}
EAPI void
evas_object_image_file_get(const Evas_Object *eo_obj, const char **file, const char **key)
{
@ -5146,6 +5194,7 @@ _class_constructor(Eo_Class *klass)
EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_DBG_INFO_GET), _dbg_info_get),
EO_OP_FUNC(EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_MEMFILE_SET), _image_memfile_set),
EO_OP_FUNC(EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_FILE_SET), _image_file_set),
EO_OP_FUNC(EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_MMAP_SET), _image_mmap_set),
EO_OP_FUNC(EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_FILE_GET), _image_file_get),
EO_OP_FUNC(EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_SOURCE_SET), _image_source_set),
EO_OP_FUNC(EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_SOURCE_GET), _image_source_get),
@ -5224,6 +5273,7 @@ _class_constructor(Eo_Class *klass)
static const Eo_Op_Description op_desc[] = {
EO_OP_DESCRIPTION(EVAS_OBJ_IMAGE_SUB_ID_MEMFILE_SET, "Sets the data for an image from memory to be loaded"),
EO_OP_DESCRIPTION(EVAS_OBJ_IMAGE_SUB_ID_FILE_SET, "Set the source file from where an image object must fetch the real"),
EO_OP_DESCRIPTION(EVAS_OBJ_IMAGE_SUB_ID_MMAP_SET, "Set the source mmaped file from where an image object must fetch the real"),
EO_OP_DESCRIPTION(EVAS_OBJ_IMAGE_SUB_ID_FILE_GET, "Retrieve the source file from where an image object is to fetch the"),
EO_OP_DESCRIPTION(EVAS_OBJ_IMAGE_SUB_ID_SOURCE_SET, "Set the source object on an image object to used as a @b proxy."),
EO_OP_DESCRIPTION(EVAS_OBJ_IMAGE_SUB_ID_SOURCE_GET, "Get the current source object of an image object."),

View File

@ -33,6 +33,7 @@ EAPI void evas_common_image_alpha_line_buffer_release (RGBA_Image *
EAPI void evas_common_image_alpha_line_buffer_free (RGBA_Image *im);
EAPI RGBA_Image *evas_common_load_image_from_file (const char *file, const char *key, Evas_Image_Load_Opts *lo, int *error);
EAPI RGBA_Image *evas_common_load_image_from_mmap (Eina_File *f, const char *key, Evas_Image_Load_Opts *lo, int *error);
EAPI int evas_common_save_image_to_file (RGBA_Image *im, const char *file, const char *key, int quality, int compress);
EAPI void evas_common_rgba_image_scalecache_init(Image_Entry *ie);

View File

@ -150,8 +150,17 @@ _evas_image_file_header(Evas_Module *em, Image_Entry *ie, int *error)
if (evas_image_load_func)
{
Evas_Image_Property property;
const char *file;
if (!ie->f) ie->f = eina_file_open(ie->file, EINA_FALSE);
if (!ie->f)
{
ie->f = eina_file_open(ie->file, EINA_FALSE);
file = ie->file;
}
else
{
file = eina_file_filename_get(ie->f);
}
if (!ie->f)
{
*error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
@ -173,7 +182,7 @@ _evas_image_file_header(Evas_Module *em, Image_Entry *ie, int *error)
(*error == EVAS_LOAD_ERROR_NONE))
{
DBG("loaded file head using module '%s' (%p): %s",
em->definition->name, em, ie->file);
em->definition->name, em, file);
ie->w = property.w;
ie->h = property.h;
@ -189,7 +198,7 @@ _evas_image_file_header(Evas_Module *em, Image_Entry *ie, int *error)
evas_module_unload(em);
INF("failed to load file head using module '%s' (%p): "
"%s (%s)",
em->definition->name, em, ie->file, evas_load_error_str(*error));
em->definition->name, em, file, evas_load_error_str(*error));
}
}
else
@ -221,8 +230,8 @@ EAPI int
evas_common_load_rgba_image_module_from_file(Image_Entry *ie)
{
const char *loader = NULL, *end;
const char *file;
Evas_Module *em;
struct stat st;
unsigned int i;
int len, ret = EVAS_LOAD_ERROR_NONE;
struct evas_image_foreach_loader_data fdata;
@ -240,14 +249,27 @@ evas_common_load_rgba_image_module_from_file(Image_Entry *ie)
// }
}
#endif
if (stat(ie->file, &st) != 0 || S_ISDIR(st.st_mode))
if (ie->f)
{
DBG("trying to open directory '%s' !", ie->file);
return EVAS_LOAD_ERROR_DOES_NOT_EXIST;
len = strlen(eina_file_filename_get(ie->f));
end = eina_file_filename_get(ie->f) + len;
file = eina_file_filename_get(ie->f);
}
else
{
struct stat st;
if (stat(ie->file, &st) != 0 || S_ISDIR(st.st_mode))
{
DBG("trying to open directory '%s' !", ie->file);
return EVAS_LOAD_ERROR_DOES_NOT_EXIST;
}
len = strlen(ie->file);
end = ie->file + len;
file = ie->file;
}
len = strlen(ie->file);
end = ie->file + len;
for (i = 0; i < (sizeof (loaders) / sizeof(struct ext_loader_s)); i++)
{
int len2 = strlen(loaders[i].extension);
@ -256,7 +278,7 @@ evas_common_load_rgba_image_module_from_file(Image_Entry *ie)
{
loader = loaders[i].loader;
DBG("known loader '%s' handles extension '%s' of file '%s'",
loader, end - len2, ie->file);
loader, end - len2, file);
break;
}
}
@ -296,10 +318,10 @@ evas_common_load_rgba_image_module_from_file(Image_Entry *ie)
DBG("could not find module '%s'", loaders_name[i]);
}
INF("exhausted all means to load image '%s'", ie->file);
INF("exhausted all means to load image '%s'", file);
return EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
end:
end:
if (ret != EVAS_LOAD_ERROR_NONE)
{
@ -313,7 +335,7 @@ evas_common_load_rgba_image_module_from_file(Image_Entry *ie)
WRN("loader '%s' (version %d) "
"handled file '%s', key '%s' with errors: %s",
modname ? modname : "<UNKNOWN>", modversion,
ie->file, ie->key ? ie->key : "",
file, ie->key ? ie->key : "",
evas_load_error_str(ret));
goto end;
}
@ -321,7 +343,7 @@ evas_common_load_rgba_image_module_from_file(Image_Entry *ie)
DBG("loader '%s' used for file %s",
(em && em->definition && em->definition->name) ?
em->definition->name : "<UNKNOWN>",
ie->file);
file);
ie->info.module = (void*) em;
ie->info.loader = (void*) em ? em->functions : NULL;

View File

@ -187,6 +187,15 @@ _evas_common_rgba_image_delete(Image_Entry *ie)
#ifdef BUILD_PIPE_RENDER
evas_common_pipe_free(im);
#endif
if (ie->loader_data)
{
Evas_Image_Load_Func *evas_image_load_func = NULL;
evas_image_load_func = ie->info.loader;
if (evas_image_load_func)
evas_image_load_func->file_close(ie->loader_data);
ie->loader_data = NULL;
}
evas_common_rgba_image_scalecache_shutdown(&im->cache_entry);
if (ie->info.module) evas_module_unref((Evas_Module *)ie->info.module);
/* memset the image to 0x99 because i recently saw a segv where an
@ -217,15 +226,7 @@ _evas_common_rgba_image_delete(Image_Entry *ie)
}
}
}
if (ie->loader_data)
{
Evas_Image_Load_Func *evas_image_load_func = NULL;
evas_image_load_func = ie->info.loader;
if (evas_image_load_func)
evas_image_load_func->file_close(ie->loader_data);
}
if (ie->f) eina_file_close(ie->f);
if (ie->f && !ie->flags.given_mmap) eina_file_close(ie->f);
free(im);
}
@ -269,7 +270,7 @@ evas_common_rgba_image_unload(Image_Entry *ie)
if (!ie->flags.loaded) return;
if ((!ie->info.module) && (!ie->data1)) return;
if (!ie->file) return;
if (!ie->file && !ie->f) return;
if (ie->references > 0) return;
ie->flags.loaded = 0;
@ -765,6 +766,17 @@ evas_common_load_image_from_file(const char *file, const char *key, Evas_Image_L
return (RGBA_Image *) evas_cache_image_request(eci, file, key, lo, error);
}
EAPI RGBA_Image *
evas_common_load_image_from_mmap(Eina_File *f, const char *key, Evas_Image_Load_Opts *lo, int *error)
{
if (!f)
{
*error = EVAS_LOAD_ERROR_GENERIC;
return NULL;
}
return (RGBA_Image *) evas_cache_image_mmap_request(eci, f, key, lo, error);
}
EAPI void
evas_common_image_cache_free(void)
{

View File

@ -513,6 +513,7 @@ struct _Image_Entry_Flags
Eina_Bool pending : 1;
Eina_Bool rotated : 1;
Eina_Bool unload_cancel : 1;
Eina_Bool given_mmap : 1;
};
struct _Image_Entry_Frame

View File

@ -795,6 +795,7 @@ struct _Evas_Func
void (*polygon_draw) (void *data, void *context, void *surface, void *polygon, int x, int y, Eina_Bool do_async);
void *(*image_load) (void *data, const char *file, const char *key, int *error, Evas_Image_Load_Opts *lo);
void *(*image_mmap) (void *data, Eina_File *f, const char *key, int *error, Evas_Image_Load_Opts *lo);
void *(*image_new_from_data) (void *data, int w, int h, DATA32 *image_data, int alpha, int cspace);
void *(*image_new_from_copied_data) (void *data, int w, int h, DATA32 *image_data, int alpha, int cspace);
void (*image_free) (void *data, void *image);

View File

@ -584,6 +584,17 @@ eng_image_load(void *data, const char *file, const char *key, int *error, Evas_I
return evas_gl_common_image_load(re->win->gl_context, file, key, lo, error);
}
static void *
eng_image_mmap(void *data, Eina_File *f, const char *key, int *error, Evas_Image_Load_Opts *lo)
{
Render_Engine *re;
re = (Render_Engine *)data;
*error = EVAS_LOAD_ERROR_NONE;
eng_window_use(re->win);
return evas_gl_common_image_mmap(re->win->gl_context, f, key, lo, error);
}
static void *
eng_image_new_from_data(void *data, int w, int h, DATA32 *image_data, int alpha, int cspace)
{
@ -1372,6 +1383,7 @@ module_open(Evas_Module *em)
ORD(polygon_draw);
ORD(image_load);
ORD(image_mmap);
ORD(image_new_from_data);
ORD(image_new_from_copied_data);
ORD(image_free);

View File

@ -655,6 +655,7 @@ void evas_gl_common_image_all_unload(Evas_Engine_GL_Context *gc);
void evas_gl_common_image_ref(Evas_GL_Image *im);
void evas_gl_common_image_unref(Evas_GL_Image *im);
Evas_GL_Image *evas_gl_common_image_load(Evas_Engine_GL_Context *gc, const char *file, const char *key, Evas_Image_Load_Opts *lo, int *error);
Evas_GL_Image *evas_gl_common_image_mmap(Evas_Engine_GL_Context *gc, Eina_File *f, const char *key, Evas_Image_Load_Opts *lo, int *error);
Evas_GL_Image *evas_gl_common_image_new_from_data(Evas_Engine_GL_Context *gc, unsigned int w, unsigned int h, DATA32 *data, int alpha, int cspace);
Evas_GL_Image *evas_gl_common_image_new_from_copied_data(Evas_Engine_GL_Context *gc, unsigned int w, unsigned int h, DATA32 *data, int alpha, int cspace);
Evas_GL_Image *evas_gl_common_image_new(Evas_Engine_GL_Context *gc, unsigned int w, unsigned int h, int alpha, int cspace);

View File

@ -96,15 +96,11 @@ evas_gl_common_image_unref(Evas_GL_Image *im)
}
}
Evas_GL_Image *
evas_gl_common_image_load(Evas_Engine_GL_Context *gc, const char *file, const char *key, Evas_Image_Load_Opts *lo, int *error)
static Evas_GL_Image *
_evas_gl_common_image(Evas_Engine_GL_Context *gc, RGBA_Image *im_im, Evas_Image_Load_Opts *lo, int *error)
{
Evas_GL_Image *im;
RGBA_Image *im_im;
Eina_List *l;
im_im = evas_common_load_image_from_file(file, key, lo, error);
if (!im_im) return NULL;
Evas_GL_Image *im;
Eina_List *l;
/* i'd LOVe to do this, but we can't because we load to load header
* to get image size to know if its too big or not! so this disallows
@ -151,7 +147,29 @@ evas_gl_common_image_load(Evas_Engine_GL_Context *gc, const char *file, const ch
im->h = im->im->cache_entry.h;
if (lo) im->load_opts = *lo;
gc->shared->images = eina_list_prepend(gc->shared->images, im);
return im;
return im;
}
Evas_GL_Image *
evas_gl_common_image_load(Evas_Engine_GL_Context *gc, const char *file, const char *key, Evas_Image_Load_Opts *lo, int *error)
{
RGBA_Image *im_im;
im_im = evas_common_load_image_from_file(file, key, lo, error);
if (!im_im) return NULL;
return _evas_gl_common_image(gc, im_im, lo, error);
}
Evas_GL_Image *
evas_gl_common_image_mmap(Evas_Engine_GL_Context *gc, Eina_File *f, const char *key, Evas_Image_Load_Opts *lo, int *error)
{
RGBA_Image *im_im;
im_im = evas_common_load_image_from_mmap(f, key, lo, error);
if (!im_im) return NULL;
return _evas_gl_common_image(gc, im_im, lo, error);
}
Evas_GL_Image *

View File

@ -485,6 +485,15 @@ eng_image_load(void *data, const char *file, const char *key, int *error, Evas_I
return evas_gl_common_image_load(re->gl_context, file, key, lo, error);
}
static void *
eng_image_mmap(void *data, Eina_File *f, const char *key, int *error, Evas_Image_Load_Opts *lo)
{
Render_Engine *re = data;
*error = EVAS_LOAD_ERROR_NONE;
return evas_gl_common_image_mmap(re->gl_context, f, key, lo, error);
}
static void *
eng_image_new_from_data(void *data, int w, int h, DATA32 *image_data, int alpha, int cspace)
{
@ -916,6 +925,7 @@ module_open(Evas_Module *em)
ORD(polygon_draw);
ORD(image_load);
ORD(image_mmap);
ORD(image_new_from_data);
ORD(image_new_from_copied_data);
ORD(image_free);

View File

@ -2437,6 +2437,17 @@ eng_image_load(void *data, const char *file, const char *key, int *error, Evas_I
return evas_gl_common_image_load(re->win->gl_context, file, key, lo, error);
}
static void *
eng_image_mmap(void *data, Eina_File *f, const char *key, int *error, Evas_Image_Load_Opts *lo)
{
Render_Engine *re;
re = (Render_Engine *)data;
*error = EVAS_LOAD_ERROR_NONE;
eng_window_use(re->win);
return evas_gl_common_image_mmap(re->win->gl_context, f, key, lo, error);
}
static void *
eng_image_new_from_data(void *data, int w, int h, DATA32 *image_data, int alpha, int cspace)
{
@ -3335,6 +3346,7 @@ module_open(Evas_Module *em)
ORD(polygon_draw);
ORD(image_load);
ORD(image_mmap);
ORD(image_new_from_data);
ORD(image_new_from_copied_data);
ORD(image_free);

View File

@ -957,6 +957,26 @@ eng_image_load(void *data EINA_UNUSED, const char *file, const char *key, int *e
return evas_common_load_image_from_file(file, key, lo, error);
}
static void *
eng_image_mmap(void *data EINA_UNUSED, Eina_File *f, const char *key, int *error, Evas_Image_Load_Opts *lo)
{
*error = EVAS_LOAD_ERROR_NONE;
#ifdef EVAS_CSERVE2
// FIXME: Need to pass fd to make that useful, so just get the filename for now.
if (evas_cserve2_use_get())
{
Image_Entry *ie;
ie = evas_cache2_image_open(evas_common_image_cache2_get(),
eina_file_filename_get(f), key, lo, error);
if (ie)
evas_cache2_image_open_wait(ie);
return ie;
}
#endif
return evas_common_load_image_from_mmap(f, key, lo, error);
}
static void *
eng_image_new_from_data(void *data EINA_UNUSED, int w, int h, DATA32 *image_data, int alpha, int cspace)
{
@ -2568,6 +2588,7 @@ static Evas_Func func =
eng_polygon_draw,
/* image draw funcs */
eng_image_load,
eng_image_mmap,
eng_image_new_from_data,
eng_image_new_from_copied_data,
eng_image_free,