evas/cserve2: use Evas loaders from slave

Use common loaders with evas, and ignore specific modules.

Signed-off-by: Cedric Bail <cedric.bail@samsung.com>
This commit is contained in:
Jean-Philippe Andre 2013-06-27 16:18:40 +09:00 committed by Cedric Bail
parent c39b714868
commit 48d97f7a90
3 changed files with 414 additions and 7 deletions

View File

@ -13,6 +13,10 @@
#include "evas_cserve2.h"
#include "evas_cserve2_slave.h"
#define LK(x) Eina_Lock x
#include "file/evas_module.h"
#include "Evas_Loader.h"
static Eina_Hash *loaders = NULL;
static Eina_List *modules = NULL;
static Eina_Prefix *pfx = NULL;
@ -27,6 +31,8 @@ struct ext_loader_s
#define MATCHING(Ext, Module) \
{ sizeof (Ext), Ext, Module }
#if !USE_EVAS_MODULE_API
static const struct ext_loader_s map_loaders[] =
{ /* map extensions to loaders to use for good first-guess tries */
MATCHING(".png", "png"),
@ -61,6 +67,118 @@ static const char *loaders_name[] =
"png", "jpeg", "eet", "xpm", "tiff", "gif", "svg", "webp", "pmaps", "bmp", "tga", "wbmp", "ico", "psd"
};
#else
static const struct ext_loader_s map_loaders[] =
{ /* map extensions to loaders to use for good first-guess tries */
MATCHING(".png", "png"),
MATCHING(".jpg", "jpeg"),
MATCHING(".jpeg", "jpeg"),
MATCHING(".jfif", "jpeg"),
MATCHING(".eet", "eet"),
MATCHING(".edj", "eet"),
MATCHING(".eap", "eet"),
MATCHING(".xpm", "xpm"),
MATCHING(".tiff", "tiff"),
MATCHING(".tif", "tiff"),
MATCHING(".svg", "svg"),
MATCHING(".svgz", "svg"),
MATCHING(".svg.gz", "svg"),
MATCHING(".gif", "gif"),
MATCHING(".pbm", "pmaps"),
MATCHING(".pgm", "pmaps"),
MATCHING(".ppm", "pmaps"),
MATCHING(".pnm", "pmaps"),
MATCHING(".bmp", "bmp"),
MATCHING(".tga", "tga"),
MATCHING(".wbmp", "wbmp"),
MATCHING(".webp", "webp"),
MATCHING(".ico", "ico"),
MATCHING(".cur", "ico"),
MATCHING(".psd", "psd"),
MATCHING(".pdf", "generic"),
MATCHING(".ps", "generic"),
MATCHING(".xcf", "generic"),
MATCHING(".xcf.gz", "generic"),
/* RAW */
MATCHING(".arw", "generic"),
MATCHING(".cr2", "generic"),
MATCHING(".crw", "generic"),
MATCHING(".dcr", "generic"),
MATCHING(".dng", "generic"),
MATCHING(".k25", "generic"),
MATCHING(".kdc", "generic"),
MATCHING(".erf", "generic"),
MATCHING(".mrw", "generic"),
MATCHING(".nef", "generic"),
MATCHING(".nrf", "generic"),
MATCHING(".nrw", "generic"),
MATCHING(".orf", "generic"),
MATCHING(".raw", "generic"),
MATCHING(".rw2", "generic"),
MATCHING(".pef", "generic"),
MATCHING(".raf", "generic"),
MATCHING(".sr2", "generic"),
MATCHING(".srf", "generic"),
MATCHING(".x3f", "generic"),
/* video */
MATCHING(".264", "generic"),
MATCHING(".3g2", "generic"),
MATCHING(".3gp", "generic"),
MATCHING(".3gp2", "generic"),
MATCHING(".3gpp", "generic"),
MATCHING(".3gpp2", "generic"),
MATCHING(".3p2", "generic"),
MATCHING(".asf", "generic"),
MATCHING(".avi", "generic"),
MATCHING(".bdm", "generic"),
MATCHING(".bdmv", "generic"),
MATCHING(".clpi", "generic"),
MATCHING(".clp", "generic"),
MATCHING(".fla", "generic"),
MATCHING(".flv", "generic"),
MATCHING(".m1v", "generic"),
MATCHING(".m2v", "generic"),
MATCHING(".m2t", "generic"),
MATCHING(".m4v", "generic"),
MATCHING(".mkv", "generic"),
MATCHING(".mov", "generic"),
MATCHING(".mp2", "generic"),
MATCHING(".mp2ts", "generic"),
MATCHING(".mp4", "generic"),
MATCHING(".mpe", "generic"),
MATCHING(".mpeg", "generic"),
MATCHING(".mpg", "generic"),
MATCHING(".mpl", "generic"),
MATCHING(".mpls", "generic"),
MATCHING(".mts", "generic"),
MATCHING(".mxf", "generic"),
MATCHING(".nut", "generic"),
MATCHING(".nuv", "generic"),
MATCHING(".ogg", "generic"),
MATCHING(".ogm", "generic"),
MATCHING(".ogv", "generic"),
MATCHING(".rm", "generic"),
MATCHING(".rmj", "generic"),
MATCHING(".rmm", "generic"),
MATCHING(".rms", "generic"),
MATCHING(".rmx", "generic"),
MATCHING(".rmvb", "generic"),
MATCHING(".swf", "generic"),
MATCHING(".ts", "generic"),
MATCHING(".weba", "generic"),
MATCHING(".webm", "generic"),
MATCHING(".wmv", "generic")
};
static const char *loaders_name[] =
{ /* in order of most likely needed */
"png", "jpeg", "eet", "xpm", "tiff", "gif", "svg", "webp", "pmaps", "bmp", "tga", "wbmp", "ico", "psd", "generic"
};
#endif
Eina_Bool
evas_cserve2_loader_register(Evas_Loader_Module_Api *api)
{
@ -76,6 +194,9 @@ evas_cserve2_loader_register(Evas_Loader_Module_Api *api)
# define EVAS_MODULE_NAME_IMAGE_LOADER "module.so"
#endif
#if !USE_EVAS_MODULE_API
static Evas_Loader_Module_Api *
loader_module_find(const char *type)
{
@ -112,6 +233,8 @@ loader_module_find(const char *type)
return NULL;
}
#endif // Old API
static Eina_Bool
command_read(int fd, Slave_Command *cmd, void **params)
{
@ -212,6 +335,263 @@ _cserve2_shm_unmap(void *map, size_t length)
munmap(map, length);
}
#if USE_EVAS_MODULE_API
static void *
_image_file_open(Eina_File *fd, const char *key, Image_Load_Opts *opts,
Evas_Module *module, Evas_Image_Property *property,
Evas_Image_Animated *animated, Evas_Image_Load_Func **pfuncs)
{
int error = EVAS_LOAD_ERROR_NONE;
Evas_Image_Load_Opts load_opts;
void *loader_data = NULL;
Evas_Image_Load_Func *funcs = NULL;
*pfuncs = NULL;
if (!evas_module_load(module))
goto unload;
funcs = module->functions;
if (!funcs)
goto unload;
evas_module_use(module);
memset(animated, 0, sizeof (*animated));
memset(&load_opts, 0, sizeof (load_opts));
if (opts)
{
load_opts.w = opts->w;
load_opts.h = opts->h;
load_opts.dpi = opts->dpi;
load_opts.region.x = opts->rx;
load_opts.region.y = opts->ry;
load_opts.region.w = opts->rw;
load_opts.region.h = opts->rh;
load_opts.orientation = opts->orientation;
load_opts.scale_down_by = opts->scale_down_by;
}
// Not set here: struct load_opts.scale_load
loader_data = funcs->file_open(fd, key, &load_opts, animated, &error);
if (!loader_data || (error != EVAS_LOAD_ERROR_NONE))
goto unload;
if (!funcs->file_head(loader_data, property, &error))
goto unload;
if (error != EVAS_LOAD_ERROR_NONE)
goto unload;
*pfuncs = funcs;
return loader_data;
unload:
if (funcs && loader_data)
funcs->file_close(loader_data);
evas_module_unload(module);
return NULL;
}
static Eina_Bool
_image_file_header(Eina_File *fd, const char *key, Image_Load_Opts *opts,
Slave_Msg_Image_Opened *result, Evas_Module *module)
{
Evas_Image_Property property;
Evas_Image_Animated animated;
Evas_Image_Load_Func *funcs;
void *loader_data;
memset(&property, 0, sizeof (property));
loader_data = _image_file_open(fd, key, opts, module, &property, &animated, &funcs);
if (!loader_data)
return EINA_FALSE;
memset(result, 0, sizeof (*result));
result->w = property.w;
result->h = property.h;
//result->degree = opts->
result->scale = property.scale;
result->alpha = property.alpha;
result->rotated = property.rotated;
result->animated = animated.animated;
if (result->animated)
{
result->frame_count = animated.frame_count;
result->loop_count = animated.loop_count;
result->loop_hint = animated.loop_hint;
}
result->has_loader_data = EINA_TRUE;
// Not set here: (Why?)
//property.premul;
//property.alpha_sparse;
// FIXME: We need to close as we this slave might not be used for data loading
funcs->file_close(loader_data);
return EINA_TRUE;
}
static Error_Type
image_open(const char *file, const char *key, Image_Load_Opts *opts,
Slave_Msg_Image_Opened *result, const char **use_loader)
{
Evas_Module *module;
Eina_File *fd;
const char *loader = NULL;
const int filelen = strlen(file);
unsigned int i;
Error_Type ret = CSERVE2_NONE;
fd = eina_file_open(file, EINA_FALSE);
if (!fd)
{
return CSERVE2_DOES_NOT_EXIST; // FIXME: maybe check errno
}
if (!*use_loader)
goto try_extension;
loader = *use_loader;
module = evas_module_find_type(EVAS_MODULE_TYPE_IMAGE_LOADER, loader);
if (module)
{
if (_image_file_header(fd, key, opts, result, module))
goto success;
}
try_extension:
loader = NULL;
for (i = 0; i < sizeof(map_loaders) / sizeof(map_loaders[0]); i++)
{
int extlen = strlen(map_loaders[i].extension);
if (extlen > filelen) continue;
if (!strcasecmp(map_loaders[i].extension, file + filelen - extlen))
{
loader = map_loaders[i].loader;
break;
}
}
if (loader)
{
module = evas_module_find_type(EVAS_MODULE_TYPE_IMAGE_LOADER, loader);
if (_image_file_header(fd, key, opts, result, module))
goto success;
loader = NULL;
module = NULL;
}
// Try all known modules
for (i = 0; i < sizeof(loaders_name) / sizeof(loaders_name[0]); i++)
{
loader = loaders_name[i];
module = evas_module_find_type(EVAS_MODULE_TYPE_IMAGE_LOADER, loader);
if (!module) continue;
if (_image_file_header(fd, key, opts, result, module))
goto success;
}
ret = CSERVE2_UNKNOWN_FORMAT;
goto end;
success:
ret = CSERVE2_NONE;
*use_loader = loader;
#warning FIXME: Do we need to unload the module now?
evas_module_unload(module);
end:
eina_file_close(fd);
return ret;
}
static Error_Type
image_load(const char *file, const char *key, const char *shmfile,
Slave_Msg_Image_Load *params, Slave_Msg_Image_Loaded *result,
const char *loader)
{
Evas_Module *module;
Eina_File *fd;
Evas_Image_Load_Func *funcs = NULL;
Image_Load_Opts *opts = &params->opts;
Evas_Image_Property property;
Evas_Image_Animated animated;
Error_Type ret = CSERVE2_GENERIC;
void *loader_data = NULL;
Eina_Bool ok;
int error;
fd = eina_file_open(file, EINA_FALSE);
if (!fd)
{
return CSERVE2_DOES_NOT_EXIST; // FIXME: maybe check errno
}
char *map = _cserve2_shm_map(shmfile, params->shm.mmap_size,
params->shm.mmap_offset);
if (map == MAP_FAILED)
{
eina_file_close(fd);
return CSERVE2_RESOURCE_ALLOCATION_FAILED;
}
module = evas_module_find_type(EVAS_MODULE_TYPE_IMAGE_LOADER, loader);
if (!module)
{
printf("LOAD failed at %s:%d: no module found for loader %s\n",
__FUNCTION__, __LINE__, loader);
goto done;
}
memset(&property, 0, sizeof (property));
property.w = params->w;
property.h = params->h;
loader_data = _image_file_open(fd, key, opts, module, &property, &animated, &funcs);
if (!loader_data)
{
printf("LOAD failed at %s:%d: could not open image %s:%s\n",
__FUNCTION__, __LINE__, file, key);
goto done;
}
ok = funcs->file_data(loader_data, &property, map, &error);
if (!ok || (error != EVAS_LOAD_ERROR_NONE))
{
printf("LOAD failed at %s:%d: file_data failed for loader %s: error %d\n",
__FUNCTION__, __LINE__, loader, error);
goto done;
}
result->w = property.w;
result->h = property.h;
if (property.alpha)
{
result->alpha_sparse = evas_cserve2_image_premul_data((unsigned int *) map,
result->w * result->h);
}
//printf("LOAD successful: %dx%d alpha_sparse %d\n",
// result->w, result->h, result->alpha_sparse);
ret = CSERVE2_NONE;
done:
eina_file_close(fd);
_cserve2_shm_unmap(map, params->shm.mmap_size);
if (funcs)
evas_module_unload(module);
return ret;
}
#else // Old cserve2 API
static Error_Type
image_open(const char *file, const char *key, Image_Load_Opts *opts, Slave_Msg_Image_Opened *result, const char **use_loader)
{
@ -355,11 +735,15 @@ image_load(const char *file, const char *key, const char *shmfile, Slave_Msg_Ima
result->h = params->h;
result->alpha_sparse = ilp.alpha_sparse;
//printf("LOAD successful: %dx%d alpha_sparse %d\n",
// result->w, result->h, result->alpha_sparse);
done:
_cserve2_shm_unmap(map, params->shm.mmap_size);
return ret;
}
#endif
static void
handle_image_open(int wfd, void *params)
@ -388,6 +772,7 @@ handle_image_open(int wfd, void *params)
if ((err = image_open(file, key, load_opts, &result, &loader))
!= CSERVE2_NONE)
{
printf("OPEN failed at %s:%d\n", __FUNCTION__, __LINE__);
error_send(wfd, err);
return;
}
@ -412,6 +797,7 @@ handle_image_load(int wfd, void *params)
if (!load_args->has_loader_data)
{
printf("LOAD failed at %s:%d: no loader data\n", __FUNCTION__, __LINE__);
error_send(wfd, CSERVE2_UNKNOWN_FORMAT);
return;
}
@ -425,6 +811,8 @@ handle_image_load(int wfd, void *params)
if ((err = image_load(file, key, shmfile, load_args, &resp, loader))
!= CSERVE2_NONE)
{
printf("LOAD failed at %s:%d: load failed with error %d\n",
__FUNCTION__, __LINE__, err);
error_send(wfd, err);
return;
}
@ -453,6 +841,10 @@ int main(int c, char **v)
loaders = eina_hash_string_superfast_new(NULL);
#if USE_EVAS_MODULE_API
evas_module_init();
#endif
wfd = atoi(v[1]);
rfd = atoi(v[2]);
@ -466,19 +858,23 @@ int main(int c, char **v)
switch (cmd)
{
case IMAGE_OPEN:
handle_image_open(wfd, params);
break;
handle_image_open(wfd, params);
break;
case IMAGE_LOAD:
handle_image_load(wfd, params);
break;
handle_image_load(wfd, params);
break;
case SLAVE_QUIT:
quit = EINA_TRUE;
break;
quit = EINA_TRUE;
break;
default:
error_send(wfd, CSERVE2_INVALID_COMMAND);
error_send(wfd, CSERVE2_INVALID_COMMAND);
}
}
#if USE_EVAS_MODULE_API
evas_module_shutdown();
#endif
eina_hash_free(loaders);
EINA_LIST_FREE(modules, m)

View File

@ -48,6 +48,7 @@ typedef unsigned char DATA8;
typedef struct _Evas_Loader_Module_Api Evas_Loader_Module_Api;
typedef struct _Evas_Img_Load_Params Evas_Img_Load_Params;
#define USE_EVAS_MODULE_API 1 ///< Use common evas loaders. TEMPORARY DEFINE.
#define EVAS_CSERVE2_MODULE_API_VERSION 1
struct _Evas_Loader_Module_Api {
int version;
@ -80,6 +81,7 @@ struct _Evas_Img_Load_Params {
EAPI Eina_Bool evas_cserve2_loader_register(Evas_Loader_Module_Api *api);
Eina_Bool evas_cserve2_image_premul_data(unsigned int *data, unsigned int len);
EAPI void evas_cserve2_image_premul(Evas_Img_Load_Params *ilp);
EAPI void evas_cserve2_image_alpha_sparse_set(Evas_Img_Load_Params *ilp);

View File

@ -22,6 +22,15 @@ evas_cserve2_convert_argb_premul(unsigned int *data, unsigned int len)
return nas;
}
Eina_Bool
evas_cserve2_image_premul_data(unsigned int *data, unsigned int len)
{
unsigned int nas;
nas = evas_cserve2_convert_argb_premul(data, len);
return ((ALPHA_SPARSE_INV_FRACTION * nas) >= len);
}
EAPI void
evas_cserve2_image_premul(Evas_Img_Load_Params *ilp)
{