forked from enlightenment/efl
Edje: Directly embed TGV files inside EDJ when possible
This checks that the ETC format is the same, and then proceeds to simply stuff in the TGV file inside the EDJ as an "edje/image/n" This will save a huge amount of time since now you just need to encode an image once to TGV (ETC1 or ETC2) and you can reuse it directly without re-encoding. To use this, convert images with ecore_evas_convert and then add them to EDC with the ".tgv" extension and the proper LOSSY format. The quality argument will then be ignored. @feature
This commit is contained in:
parent
64de2f6ce5
commit
a5d0284820
|
@ -151,6 +151,9 @@ struct _Image_Write
|
|||
Eet_File *ef;
|
||||
Edje_Image_Directory_Entry *img;
|
||||
Evas_Object *im;
|
||||
Emile_Image_Property prop;
|
||||
Eina_File *f;
|
||||
Emile_Image *emi;
|
||||
int w, h;
|
||||
int alpha;
|
||||
unsigned int *data;
|
||||
|
@ -1061,7 +1064,7 @@ data_thread_image_end(void *data, Ecore_Thread *thread EINA_UNUSED)
|
|||
error_and_abort(iw->ef, iw->errstr);
|
||||
free(iw->errstr);
|
||||
}
|
||||
if (iw->path) free(iw->path);
|
||||
free(iw->path);
|
||||
evas_object_del(iw->im);
|
||||
free(iw);
|
||||
}
|
||||
|
@ -1083,6 +1086,127 @@ data_image_preload_done(void *data, Evas *e EINA_UNUSED, Evas_Object *o, void *e
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tgv_file_thread(void *data, Ecore_Thread *thread EINA_UNUSED)
|
||||
{
|
||||
Image_Write *iw = data;
|
||||
char buf[256];
|
||||
size_t len;
|
||||
|
||||
snprintf(buf, sizeof(buf), "edje/images/%i", iw->img->id);
|
||||
|
||||
len = eina_file_size_get(iw->f);
|
||||
eet_write_cipher(iw->ef, buf, iw->data, len, EINA_FALSE /*!no_comp*/, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
tgv_file_thread_end(void *data, Ecore_Thread *thread EINA_UNUSED)
|
||||
{
|
||||
Image_Write *iw = data;
|
||||
|
||||
pending_threads--;
|
||||
if (pending_threads <= 0) ecore_main_loop_quit();
|
||||
if (iw->errstr)
|
||||
{
|
||||
error_and_abort(iw->ef, iw->errstr);
|
||||
free(iw->errstr);
|
||||
}
|
||||
free(iw->path);
|
||||
emile_image_close(iw->emi);
|
||||
eina_file_map_free(iw->f, iw->data);
|
||||
eina_file_close(iw->f);
|
||||
free(iw);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
tgv_file_check_and_add(Eet_File *ef, Edje_Image_Directory_Entry *img, int *image_num)
|
||||
{
|
||||
Emile_Image_Load_Error err;
|
||||
Emile_Image *emi = NULL;
|
||||
Image_Write *iw = NULL;
|
||||
Eina_List *li;
|
||||
const char *s;
|
||||
Eina_File *f;
|
||||
void *data;
|
||||
|
||||
EINA_LIST_FOREACH(img_dirs, li, s)
|
||||
{
|
||||
char buf[PATH_MAX];
|
||||
snprintf(buf, sizeof(buf), "%s/%s", s, img->entry);
|
||||
f = eina_file_open(buf, EINA_FALSE);
|
||||
if (f) break;
|
||||
}
|
||||
if (!f) return EINA_FALSE;
|
||||
|
||||
data = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
|
||||
if (!data) goto on_error;
|
||||
|
||||
using_file(img->entry, 'I');
|
||||
|
||||
emi = emile_image_tgv_file_open(f, NULL, NULL, &err);
|
||||
if (!emi || (err != EMILE_IMAGE_LOAD_ERROR_NONE)) goto on_error;
|
||||
|
||||
iw = calloc(1, sizeof(*iw));
|
||||
|
||||
if (!emile_image_head(emi, &iw->prop, sizeof(iw->prop), &err) ||
|
||||
(err != EMILE_IMAGE_LOAD_ERROR_NONE))
|
||||
goto on_error;
|
||||
|
||||
if (!iw->prop.cspaces || !iw->prop.w || !iw->prop.h)
|
||||
goto on_error;
|
||||
|
||||
iw->f = f;
|
||||
iw->ef = ef;
|
||||
iw->img = img;
|
||||
iw->emi = emi;
|
||||
iw->data = (unsigned int *) data;
|
||||
iw->w = iw->prop.w;
|
||||
iw->h = iw->prop.h;
|
||||
|
||||
iw->prop.cspace = iw->prop.cspaces[0];
|
||||
if (img->source_type == EDJE_IMAGE_SOURCE_TYPE_INLINE_LOSSY_ETC1)
|
||||
{
|
||||
if (no_etc1) goto on_error;
|
||||
if (iw->prop.cspace == EMILE_COLORSPACE_ETC1)
|
||||
iw->alpha = 0;
|
||||
else if (iw->prop.cspace == EMILE_COLORSPACE_ETC1_ALPHA)
|
||||
iw->alpha = 1;
|
||||
else
|
||||
goto on_error;
|
||||
}
|
||||
else if (img->source_type == EDJE_IMAGE_SOURCE_TYPE_INLINE_LOSSY_ETC2)
|
||||
{
|
||||
if (no_etc2) goto on_error;
|
||||
if (iw->prop.cspace == EMILE_COLORSPACE_RGB8_ETC2)
|
||||
iw->alpha = 0;
|
||||
else if (iw->prop.cspace == EMILE_COLORSPACE_RGBA8_ETC2_EAC)
|
||||
iw->alpha = 1;
|
||||
else
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
*image_num += 1;
|
||||
iw->path = strdup(img->entry);
|
||||
|
||||
pending_threads++;
|
||||
if (threads)
|
||||
ecore_thread_run(tgv_file_thread, tgv_file_thread_end, NULL, iw);
|
||||
else
|
||||
{
|
||||
tgv_file_thread(iw, NULL);
|
||||
tgv_file_thread_end(iw, NULL);
|
||||
}
|
||||
|
||||
return EINA_TRUE;
|
||||
|
||||
on_error:
|
||||
free(iw);
|
||||
emile_image_close(emi);
|
||||
if (data) eina_file_map_free(f, data);
|
||||
eina_file_close(f);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
data_write_images(Eet_File *ef, int *image_num)
|
||||
{
|
||||
|
@ -1101,73 +1225,83 @@ data_write_images(Eet_File *ef, int *image_num)
|
|||
for (i = 0; i < (int)edje_file->image_dir->entries_count; i++)
|
||||
{
|
||||
Edje_Image_Directory_Entry *img;
|
||||
Evas_Object *im;
|
||||
Eina_List *ll;
|
||||
char *s;
|
||||
int load_err = EVAS_LOAD_ERROR_NONE;
|
||||
Image_Write *iw;
|
||||
|
||||
img = &edje_file->image_dir->entries[i];
|
||||
if ((img->source_type == EDJE_IMAGE_SOURCE_TYPE_EXTERNAL) ||
|
||||
(img->entry == NULL))
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
Evas_Object *im;
|
||||
Eina_List *ll;
|
||||
char *s;
|
||||
int load_err = EVAS_LOAD_ERROR_NONE;
|
||||
Image_Write *iw;
|
||||
if ((img->source_type == EDJE_IMAGE_SOURCE_TYPE_EXTERNAL) || !img->entry)
|
||||
continue;
|
||||
|
||||
iw = calloc(1, sizeof(Image_Write));
|
||||
iw->ef = ef;
|
||||
iw->img = img;
|
||||
iw->im = im = evas_object_image_add(evas);
|
||||
if (threads)
|
||||
evas_object_event_callback_add(im,
|
||||
EVAS_CALLBACK_IMAGE_PRELOADED,
|
||||
data_image_preload_done,
|
||||
iw);
|
||||
EINA_LIST_FOREACH(img_dirs, ll, s)
|
||||
if (img->source_type == EDJE_IMAGE_SOURCE_TYPE_INLINE_LOSSY_ETC1 ||
|
||||
img->source_type == EDJE_IMAGE_SOURCE_TYPE_INLINE_LOSSY_ETC2)
|
||||
{
|
||||
const char *ext = strrchr(img->entry, '.');
|
||||
if (ext && !strcasecmp(ext, ".tgv"))
|
||||
{
|
||||
char buf[PATH_MAX];
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s/%s", s, img->entry);
|
||||
evas_object_image_file_set(im, buf, NULL);
|
||||
load_err = evas_object_image_load_error_get(im);
|
||||
if (load_err == EVAS_LOAD_ERROR_NONE)
|
||||
if (tgv_file_check_and_add(ef, img, image_num))
|
||||
{
|
||||
*image_num += 1;
|
||||
iw->path = strdup(buf);
|
||||
pending_threads++;
|
||||
if (threads)
|
||||
evas_object_image_preload(im, 0);
|
||||
using_file(buf, 'I');
|
||||
if (!threads)
|
||||
data_image_preload_done(iw, evas, im, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (load_err != EVAS_LOAD_ERROR_NONE)
|
||||
{
|
||||
evas_object_image_file_set(im, img->entry, NULL);
|
||||
load_err = evas_object_image_load_error_get(im);
|
||||
if (load_err == EVAS_LOAD_ERROR_NONE)
|
||||
{
|
||||
*image_num += 1;
|
||||
iw->path = strdup(img->entry);
|
||||
pending_threads++;
|
||||
if (threads)
|
||||
evas_object_image_preload(im, 0);
|
||||
using_file(img->entry, 'I');
|
||||
if (!threads)
|
||||
data_image_preload_done(iw, evas, im, NULL);
|
||||
DBG("Directly copying data from TGV file into EDJ");
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(iw);
|
||||
error_and_abort_image_load_error
|
||||
(ef, img->entry, load_err);
|
||||
exit(1); // ensure static analysis tools know we exit
|
||||
}
|
||||
ERR("Source '%s' has incompatible ETC format.", img->entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iw = calloc(1, sizeof(Image_Write));
|
||||
iw->ef = ef;
|
||||
iw->img = img;
|
||||
iw->im = im = evas_object_image_add(evas);
|
||||
if (threads)
|
||||
evas_object_event_callback_add(im,
|
||||
EVAS_CALLBACK_IMAGE_PRELOADED,
|
||||
data_image_preload_done,
|
||||
iw);
|
||||
EINA_LIST_FOREACH(img_dirs, ll, s)
|
||||
{
|
||||
char buf[PATH_MAX];
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s/%s", s, img->entry);
|
||||
evas_object_image_file_set(im, buf, NULL);
|
||||
load_err = evas_object_image_load_error_get(im);
|
||||
if (load_err == EVAS_LOAD_ERROR_NONE)
|
||||
{
|
||||
*image_num += 1;
|
||||
iw->path = strdup(buf);
|
||||
pending_threads++;
|
||||
if (threads)
|
||||
evas_object_image_preload(im, 0);
|
||||
using_file(buf, 'I');
|
||||
if (!threads)
|
||||
data_image_preload_done(iw, evas, im, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (load_err != EVAS_LOAD_ERROR_NONE)
|
||||
{
|
||||
evas_object_image_file_set(im, img->entry, NULL);
|
||||
load_err = evas_object_image_load_error_get(im);
|
||||
if (load_err == EVAS_LOAD_ERROR_NONE)
|
||||
{
|
||||
*image_num += 1;
|
||||
iw->path = strdup(img->entry);
|
||||
pending_threads++;
|
||||
if (threads)
|
||||
evas_object_image_preload(im, 0);
|
||||
using_file(img->entry, 'I');
|
||||
if (!threads)
|
||||
data_image_preload_done(iw, evas, im, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
free(iw);
|
||||
error_and_abort_image_load_error(ef, img->entry, load_err);
|
||||
exit(1); // ensure static analysis tools know we exit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue