From 73d2800637106b5f2913a789df2b45799793a492 Mon Sep 17 00:00:00 2001 From: raster Date: Tue, 15 May 2012 12:29:22 +0000 Subject: [PATCH] optimize edje_cc - now betwene 3.5 x and 4x as fast. new options (-fastcomp and -fastdecomp) -fastcomp makes for faster decompressing AND faster compressing of edj files, -fastdecomp is a bit slower on compression but also as fast as -fastcomp in decompression. note that edje files built with these optiosn will not work on older edje installations, thus they are options. git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/edje@71112 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- ChangeLog | 9 + src/bin/edje_cc.c | 11 + src/bin/edje_cc.h | 2 +- src/bin/edje_cc_out.c | 1676 +++++++++++++++++++++++++++------------------ src/bin/edje_cc_parse.c | 98 +-- src/bin/edje_cc_sources.c | 6 +- src/bin/edje_decc.c | 1 + 7 files changed, 1094 insertions(+), 709 deletions(-) diff --git a/ChangeLog b/ChangeLog index 927365b..cdf52b2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -448,3 +448,12 @@ 2012-05-14 Cedric Bail * Preserve drag informations during call of edje_object_file_set. + +2012-05-15 Carsten Haitzler (The Rasterman) + + * Optimize edje_cc to be multi-threaded and compress in parallel + * Remove O(n2) algorithms for O(1) in the parser in edje_cc + * Add options for the new compression modes in Eet. (fastcomp + and fastdecomp - LZ4 and LZ4HC). + * Overall sped up edje_cc by 4x faster (if you use fastcomp) + and about 4.5x faster with old zlib compression. diff --git a/src/bin/edje_cc.c b/src/bin/edje_cc.c index ff2708c..f2663be 100644 --- a/src/bin/edje_cc.c +++ b/src/bin/edje_cc.c @@ -29,6 +29,7 @@ int no_raw = 0; int no_save = 0; int min_quality = 0; int max_quality = 100; +int compress_mode = EET_COMPRESSION_DEFAULT; static void main_help(void) @@ -52,6 +53,8 @@ main_help(void) "-min-quality VAL Do NOT allow lossy images with quality < VAL (0-100)\n" "-max-quality VAL Do NOT allow lossy images with quality > VAL (0-100)\n" "-Ddefine_val=to CPP style define to define input macro definitions to the .edc source\n" + "-fastcomp Use a faster compression algorithm (LZ4) (mutually exclusive with -fastdecomp)\n" + "-fastdecomp Use a faster decompression algorithm (LZ4HC) (mutually exclusive with -fastcomp)\n" ,progname); } @@ -144,6 +147,14 @@ main(int argc, char **argv) if (max_quality < 0) max_quality = 0; if (max_quality > 100) max_quality = 100; } + else if ((!strcmp(argv[i], "-fastcomp")) && (i < (argc - 1))) + { + compress_mode = EET_COMPRESSION_SUPERFAST; + } + else if ((!strcmp(argv[i], "-fastdecomp")) && (i < (argc - 1))) + { + compress_mode = EET_COMPRESSION_VERYFAST; + } else if (!strncmp(argv[i], "-D", 2)) { defines = eina_list_append(defines, mem_strdup(argv[i])); diff --git a/src/bin/edje_cc.h b/src/bin/edje_cc.h index 56b5449..35fcf5d 100644 --- a/src/bin/edje_cc.h +++ b/src/bin/edje_cc.h @@ -227,6 +227,6 @@ extern Eina_List *defines; extern Eina_List *aliases; extern New_Object_Handler object_handlers[]; extern New_Statement_Handler statement_handlers[]; - +extern int compress_mode; #endif diff --git a/src/bin/edje_cc_out.c b/src/bin/edje_cc_out.c index fe72c5e..3d92348 100644 --- a/src/bin/edje_cc_out.c +++ b/src/bin/edje_cc_out.c @@ -111,6 +111,20 @@ struct _Code_Lookup Eina_Bool set; }; +typedef struct _Script_Compile +{ + Eet_File *ef; + Code *cd; + int i; + Ecore_Exe *exe; + int tmpn_fd, tmpo_fd; + char tmpn[PATH_MAX]; + char tmpo[PATH_MAX]; + char *errstr; +} Script_Compile; + +static int pending_threads = 0; + static void data_process_string(Edje_Part_Collection *pc, const char *prefix, char *s, void (*func)(Edje_Part_Collection *pc, char *name, char* ptr, int len)); Edje_File *edje_file = NULL; @@ -157,11 +171,11 @@ data_setup(void) } static void -check_image_part_desc (Edje_Part_Collection *pc, Edje_Part *ep, - Edje_Part_Description_Image *epd, Eet_File *ef) +check_image_part_desc(Edje_Part_Collection *pc, Edje_Part *ep, + Edje_Part_Description_Image *epd, Eet_File *ef) { unsigned int i; - + #if 0 /* FIXME: This check sounds like not a useful one */ if (epd->image.id == -1) ERR(ef, "Collection %s(%i): image attributes missing for " @@ -205,7 +219,7 @@ check_nameless_state(Edje_Part_Collection *pc, Edje_Part *ep, Edje_Part_Descript } static void -check_part (Edje_Part_Collection *pc, Edje_Part *ep, Eet_File *ef) +check_part(Edje_Part_Collection *pc, Edje_Part *ep, Eet_File *ef) { unsigned int i; /* FIXME: check image set and sort them. */ @@ -229,7 +243,7 @@ check_part (Edje_Part_Collection *pc, Edje_Part *ep, Eet_File *ef) } static void -check_program (Edje_Part_Collection *pc, Edje_Program *ep, Eet_File *ef) +check_program(Edje_Part_Collection *pc, Edje_Program *ep, Eet_File *ef) { switch (ep->action) { @@ -247,10 +261,18 @@ check_program (Edje_Part_Collection *pc, Edje_Program *ep, Eet_File *ef) } } -static int -data_write_header(Eet_File *ef) +typedef struct _Head_Write +{ + Eet_File *ef; + char *errstr; +} Head_Write; + +static void +data_thread_head(void *data, Ecore_Thread *thread __UNUSED__) { + Head_Write *hw = data; int bytes = 0; + char buf[PATH_MAX]; if (edje_file) { @@ -258,149 +280,228 @@ data_write_header(Eet_File *ef) { Edje_Part_Collection_Directory_Entry *ce; - /* copy aliases into collection directory */ EINA_LIST_FREE(aliases, ce) { Edje_Part_Collection_Directory_Entry *sce; Eina_Iterator *it; if (!ce->entry) - error_and_abort(ef, "Collection %i: name missing.\n", ce->id); + { + snprintf(buf, sizeof(buf), + "Collection %i: name missing.\n", ce->id); + hw->errstr = strdup(buf); + return; + } it = eina_hash_iterator_data_new(edje_file->collection); EINA_ITERATOR_FOREACH(it, sce) - if (ce->id == sce->id) - { - memcpy(&ce->count, &sce->count, sizeof (ce->count)); - break; - } + { + if (ce->id == sce->id) + { + memcpy(&ce->count, &sce->count, sizeof (ce->count)); + break; + } + } if (!sce) - error_and_abort(ef, "Collection %s (%i) can't find an correct alias.\n", ce->entry, ce->id); - + { + snprintf(buf, sizeof(buf), + "Collection %s (%i) can't find an correct alias.\n", + ce->entry, ce->id); + hw->errstr = strdup(buf); + return; + } eina_iterator_free(it); - eina_hash_direct_add(edje_file->collection, ce->entry, ce); } } - bytes = eet_data_write(ef, edd_edje_file, "edje/file", edje_file, 1); + bytes = eet_data_write(hw->ef, edd_edje_file, "edje/file", edje_file, + compress_mode); if (bytes <= 0) - error_and_abort(ef, "Unable to write \"edje_file\" entry to \"%s\" \n", - file_out); + { + snprintf(buf, sizeof(buf), + "Unable to write \"edje_file\" entry to \"%s\" \n", + file_out); + hw->errstr = strdup(buf); + return; + } } if (verbose) + printf("%s: Wrote %9i bytes (%4iKb) for \"edje_file\" header\n", + progname, bytes, (bytes + 512) / 1024); +} + +static void +data_thread_head_end(void *data, Ecore_Thread *thread __UNUSED__) +{ + Head_Write *hw = data; + + pending_threads--; + if (pending_threads <= 0) ecore_main_loop_quit(); + if (hw->errstr) { - printf("%s: Wrote %9i bytes (%4iKb) for \"edje_file\" header\n", - progname, bytes, (bytes + 512) / 1024); + error_and_abort(hw->ef, hw->errstr); + free(hw->errstr); } + free(hw); +} - return bytes; +static void +data_write_header(Eet_File *ef) +{ + Head_Write *hw; + + hw = calloc(1, sizeof(Head_Write)); + hw->ef = ef; + pending_threads++; + ecore_thread_run(data_thread_head, data_thread_head_end, + NULL, hw); } -static int -data_write_fonts(Eet_File *ef, int *font_num, int *input_bytes, int *input_raw_bytes) +typedef struct _Fonts_Compile { - Eina_Iterator *it; - int bytes = 0; - int total_bytes = 0; + Eet_File *ef; Font *fn; + char *errstr; +} Fonts_Compile; - if (!edje_file->fonts) - return 0; - - it = eina_hash_iterator_data_new(edje_file->fonts); - EINA_ITERATOR_FOREACH(it, fn) +static void +data_thread_fonts(void *data, Ecore_Thread *thread __UNUSED__) +{ + Fonts_Compile *fc = data; + void *fdata = NULL; + int fsize = 0; + Eina_List *ll; + FILE *f; + int bytes = 0; + char buf[PATH_MAX]; + char buf2[PATH_MAX]; + + f = fopen(fc->fn->file, "rb"); + if (f) { - void *fdata = NULL; - int fsize = 0; - Eina_List *ll; - FILE *f; - - f = fopen(fn->file, "rb"); - if (f) - { - long pos; - - using_file(fn->file); - fseek(f, 0, SEEK_END); - pos = ftell(f); - rewind(f); - fdata = malloc(pos); - if (fdata) - { - if (fread(fdata, pos, 1, f) != 1) - error_and_abort(ef, "Unable to read all of font " - "file \"%s\"\n", fn->file); - fsize = pos; - } - fclose(f); - } - else - { - char *data; - - EINA_LIST_FOREACH(fnt_dirs, ll, data) - { - char buf[4096]; + long pos; + + using_file(fc->fn->file); + fseek(f, 0, SEEK_END); + pos = ftell(f); + rewind(f); + fdata = malloc(pos); + if (fdata) + { + if (fread(fdata, pos, 1, f) != 1) + { + snprintf(buf, sizeof(buf), + "Unable to read all of font file \"%s\"\n", + fc->fn->file); + fc->errstr = strdup(buf); + return; + } + fsize = pos; + } + fclose(f); + } + else + { + char *dat; + + EINA_LIST_FOREACH(fnt_dirs, ll, dat) + { + snprintf(buf, sizeof(buf), "%s/%s", dat, fc->fn->file); + f = fopen(buf, "rb"); + if (f) + { + long pos; + + using_file(buf); + fseek(f, 0, SEEK_END); + pos = ftell(f); + rewind(f); + fdata = malloc(pos); + if (fdata) + { + if (fread(fdata, pos, 1, f) != 1) + { + snprintf(buf2, sizeof(buf2), + "Unable to read all of font file \"%s\"\n", + buf); + fc->errstr = strdup(buf2); + return; + } + fsize = pos; + } + fclose(f); + if (fdata) break; + } + } + } + if (!fdata) + { + snprintf(buf, sizeof(buf), + "Unable to load font part \"%s\" entry to %s \n", + fc->fn->file, file_out); + fc->errstr = strdup(buf); + return; + } + else + { + snprintf(buf, sizeof(buf), "edje/fonts/%s", fc->fn->name); + bytes = eet_write(fc->ef, buf, fdata, fsize, compress_mode); + if (bytes <= 0) + { + snprintf(buf2, sizeof(buf2), + "Unable to write font part \"%s\" as \"%s\" " + "part entry to %s \n", fc->fn->file, buf, file_out); + fc->errstr = strdup(buf2); + return; + } + if (verbose) + printf("%s: Wrote %9i bytes (%4iKb) for \"%s\" font entry \"%s\" compress: [real: %2.1f%%]\n", + progname, bytes, (bytes + 512) / 1024, buf, fc->fn->file, + 100 - (100 * (double)bytes) / ((double)(fsize)) + ); + free(fdata); + } +} - snprintf(buf, sizeof(buf), "%s/%s", data, fn->file); - f = fopen(buf, "rb"); - if (f) - { - long pos; - - using_file(buf); - fseek(f, 0, SEEK_END); - pos = ftell(f); - rewind(f); - fdata = malloc(pos); - if (fdata) - { - if (fread(fdata, pos, 1, f) != 1) - error_and_abort(ef, "Unable to read all of font " - "file \"%s\"\n", buf); - fsize = pos; - } - fclose(f); - if (fdata) break; - } - } - } - if (!fdata) - { - error_and_abort(ef, "Unable to load font part \"%s\" entry " - "to %s \n", fn->file, file_out); - } - else - { - char buf[4096]; +static void +data_thread_fonts_end(void *data, Ecore_Thread *thread __UNUSED__) +{ + Fonts_Compile *fc = data; + pending_threads--; + if (pending_threads <= 0) ecore_main_loop_quit(); + if (fc->errstr) + { + error_and_abort(fc->ef, fc->errstr); + free(fc->errstr); + } + free(fc); +} - snprintf(buf, sizeof(buf), "edje/fonts/%s", fn->name); - bytes = eet_write(ef, buf, fdata, fsize, 1); - if (bytes <= 0) - error_and_abort(ef, "Unable to write font part \"%s\" as \"%s\" " - "part entry to %s \n", fn->file, buf, file_out); +static void +data_write_fonts(Eet_File *ef, int *font_num) +{ + Eina_Iterator *it; + Font *fn; - *font_num += 1; - total_bytes += bytes; - *input_bytes += fsize; - *input_raw_bytes += fsize; + if (!edje_file->fonts) return; - if (verbose) - { - printf("%s: Wrote %9i bytes (%4iKb) for \"%s\" font entry \"%s\" compress: [real: %2.1f%%]\n", - progname, bytes, (bytes + 512) / 1024, buf, fn->file, - 100 - (100 * (double)bytes) / ((double)(fsize)) - ); - } - free(fdata); - } + it = eina_hash_iterator_data_new(edje_file->fonts); + EINA_ITERATOR_FOREACH(it, fn) + { + Fonts_Compile *fc; + + fc = calloc(1, sizeof(Fonts_Compile)); + if (!fc) continue; + fc->ef = ef; + fc->fn = fn; + ecore_thread_run(data_thread_fonts, data_thread_fonts_end, + NULL, fc); + *font_num += 1; } eina_iterator_free(it); - - return total_bytes; } static void @@ -485,314 +586,370 @@ error_and_abort_image_load_error(Eet_File *ef, const char *file, int error) file, file_out, errmsg, hint); } -static int -data_write_images(Eet_File *ef, int *image_num, int *input_bytes, int *input_raw_bytes) +typedef struct _Image_Write { - unsigned int i; + Eet_File *ef; + Edje_Image_Directory_Entry *img; + Evas_Object *im; + int w, h; + int alpha; + unsigned int *data; + char *errstr; +} Image_Write; + +static void +data_thread_image(void *data, Ecore_Thread *thread __UNUSED__) +{ + Image_Write *iw = data; + char buf[PATH_MAX]; + unsigned int *start, *end; + Eina_Bool opaque = EINA_TRUE; int bytes = 0; - int total_bytes = 0; - if ((edje_file) && (edje_file->image_dir)) + if ((iw->data) && (iw->w > 0) && (iw->h > 0)) { - Ecore_Evas *ee; - Evas *evas; - Edje_Image_Directory_Entry *img; - - ecore_init(); - ecore_evas_init(); - - ee = ecore_evas_buffer_new(1, 1); - if (!ee) - error_and_abort(ef, "Cannot create buffer engine canvas for image " - "load.\n"); - - evas = ecore_evas_get(ee); - for (i = 0; i < edje_file->image_dir->entries_count; i++) - { - 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 *data; - int load_err = EVAS_LOAD_ERROR_NONE; - - im = NULL; - EINA_LIST_FOREACH(img_dirs, ll, data) - { - char buf[4096]; - - snprintf(buf, sizeof(buf), "%s/%s", - data, img->entry); - im = evas_object_image_add(evas); - if (im) - { - evas_object_image_file_set(im, buf, NULL); - load_err = evas_object_image_load_error_get(im); - if (load_err == EVAS_LOAD_ERROR_NONE) - { - using_file(buf); - break; - } - evas_object_del(im); - im = NULL; - if (load_err != EVAS_LOAD_ERROR_DOES_NOT_EXIST) - break; - } - } - if ((!im) && (load_err == EVAS_LOAD_ERROR_DOES_NOT_EXIST)) - { - im = evas_object_image_add(evas); - if (im) - { - 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) - { - evas_object_del(im); - im = NULL; - } - if (im) using_file(img->entry); - } - } - if (im) - { - void *im_data; - int im_w, im_h; - int im_alpha; - char buf[256]; - unsigned int *start, *end; - Eina_Bool opaque = EINA_TRUE; - - evas_object_image_size_get(im, &im_w, &im_h); - im_alpha = evas_object_image_alpha_get(im); - im_data = evas_object_image_data_get(im, 0); - if ((im_data) && (im_w > 0) && (im_h > 0)) - { - int mode, qual; - - snprintf(buf, sizeof(buf), "edje/images/%i", img->id); - qual = 80; - if ((img->source_type == EDJE_IMAGE_SOURCE_TYPE_INLINE_PERFECT) && - (img->source_param == 0)) - mode = 0; /* RAW */ - else if ((img->source_type == EDJE_IMAGE_SOURCE_TYPE_INLINE_PERFECT) && - (img->source_param == 1)) - mode = 1; /* COMPRESS */ - else - mode = 2; /* LOSSY */ - if ((mode == 0) && (no_raw)) - { - mode = 1; /* promote compression */ - img->source_param = 95; - } - if ((mode == 2) && (no_lossy)) mode = 1; /* demote compression */ - if ((mode == 1) && (no_comp)) - { - if (no_lossy) mode = 0; /* demote compression */ - else if (no_raw) - { - img->source_param = 90; - mode = 2; /* no choice. lossy */ - } - } - if (mode == 2) - { - qual = img->source_param; - if (qual < min_quality) qual = min_quality; - if (qual > max_quality) qual = max_quality; - } - if (im_alpha) - { - start = (unsigned int *) im_data; - end = start + (im_w * im_h); - while (start < end) - { - if ((*start & 0xff000000) != 0xff000000) - { - opaque = EINA_FALSE; - break; - } - start++; - } - if (opaque) im_alpha = 0; - } - if (mode == 0) - bytes = eet_data_image_write(ef, buf, - im_data, im_w, im_h, - im_alpha, - 0, 0, 0); - else if (mode == 1) - bytes = eet_data_image_write(ef, buf, - im_data, im_w, im_h, - im_alpha, - 1, 0, 0); - else if (mode == 2) - bytes = eet_data_image_write(ef, buf, - im_data, im_w, im_h, - im_alpha, - 0, qual, 1); - if (bytes <= 0) - error_and_abort(ef, "Unable to write image part " - "\"%s\" as \"%s\" part entry to " - "%s\n", img->entry, buf, - file_out); - - *image_num += 1; - total_bytes += bytes; - } - else - { - error_and_abort_image_load_error - (ef, img->entry, load_err); - } + int mode, qual; + + snprintf(buf, sizeof(buf), "edje/images/%i", iw->img->id); + qual = 80; + if ((iw->img->source_type == EDJE_IMAGE_SOURCE_TYPE_INLINE_PERFECT) && + (iw->img->source_param == 0)) + mode = 0; /* RAW */ + else if ((iw->img->source_type == EDJE_IMAGE_SOURCE_TYPE_INLINE_PERFECT) && + (iw->img->source_param == 1)) + mode = 1; /* COMPRESS */ + else + mode = 2; /* LOSSY */ + if ((mode == 0) && (no_raw)) + { + mode = 1; /* promote compression */ + iw->img->source_param = 95; + } + if ((mode == 2) && (no_lossy)) mode = 1; /* demote compression */ + if ((mode == 1) && (no_comp)) + { + if (no_lossy) mode = 0; /* demote compression */ + else if (no_raw) + { + iw->img->source_param = 90; + mode = 2; /* no choice. lossy */ + } + } + if (mode == 2) + { + qual = iw->img->source_param; + if (qual < min_quality) qual = min_quality; + if (qual > max_quality) qual = max_quality; + } + if (iw->alpha) + { + start = (unsigned int *) iw->data; + end = start + (iw->w * iw->h); + while (start < end) + { + if ((*start & 0xff000000) != 0xff000000) + { + opaque = EINA_FALSE; + break; + } + start++; + } + if (opaque) iw->alpha = 0; + } + if (mode == 0) + bytes = eet_data_image_write(iw->ef, buf, + iw->data, iw->w, iw->h, + iw->alpha, + 0, 0, 0); + else if (mode == 1) + bytes = eet_data_image_write(iw->ef, buf, + iw->data, iw->w, iw->h, + iw->alpha, + compress_mode, + 0, 0); + else if (mode == 2) + bytes = eet_data_image_write(iw->ef, buf, + iw->data, iw->w, iw->h, + iw->alpha, + 0, qual, 1); + if (bytes <= 0) + { + snprintf(buf, sizeof(buf), + "Unable to write image part " + "\"%s\" as \"%s\" part entry to " + "%s\n", iw->img->entry, buf, + file_out); + iw->errstr = strdup(buf); + return; + } + + } + else + { + snprintf(buf, sizeof(buf), + "Unable to load image part " + "\"%s\" as \"%s\" part entry to " + "%s\n", iw->img->entry, buf, + file_out); + iw->errstr = strdup(buf); + return; + } + + if (verbose) + { + struct stat st; + const char *file = NULL; +/* + evas_object_image_file_get(im, &file, NULL); + if (!file || (stat(file, &st) != 0)) + st.st_size = 0; + printf("%s: Wrote %9i bytes (%4iKb) for \"%s\" image entry \"%s\" compress: [raw: %2.1f%%] [real: %2.1f%%]\n", + progname, bytes, (bytes + 512) / 1024, buf, img->entry, + 100 - (100 * (double)bytes) / ((double)(im_w * im_h * 4)), + 100 - (100 * (double)bytes) / ((double)(st.st_size)) + ); + */ + } +} - if (verbose) - { - struct stat st; - const char *file = NULL; - - evas_object_image_file_get(im, &file, NULL); - if (!file || (stat(file, &st) != 0)) - st.st_size = 0; - *input_bytes += st.st_size; - *input_raw_bytes += im_w * im_h * 4; - printf("%s: Wrote %9i bytes (%4iKb) for \"%s\" image entry \"%s\" compress: [raw: %2.1f%%] [real: %2.1f%%]\n", - progname, bytes, (bytes + 512) / 1024, buf, img->entry, - 100 - (100 * (double)bytes) / ((double)(im_w * im_h * 4)), - 100 - (100 * (double)bytes) / ((double)(st.st_size)) - ); - } - evas_object_del(im); - } - else - { - error_and_abort_image_load_error - (ef, img->entry, load_err); - } - } - } - ecore_evas_free(ee); - ecore_evas_shutdown(); - ecore_shutdown(); +static void +data_thread_image_end(void *data, Ecore_Thread *thread __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); } + evas_object_del(iw->im); + free(iw); +} - return total_bytes; +static void +data_image_preload_done(void *data, Evas *e __UNUSED__, Evas_Object *o, void *event_info __UNUSED__) +{ + Image_Write *iw = data; + + evas_object_image_size_get(o, &iw->w, &iw->h); + iw->alpha = evas_object_image_alpha_get(o); + iw->data = evas_object_image_data_get(o, 0); + ecore_thread_run(data_thread_image, data_thread_image_end, NULL, iw); } -static int -data_write_sounds(Eet_File * ef, int *sound_num, int *input_bytes, int *input_raw_bytes) +// WARNING - uses evas to LOAD image... this can't be done in threads! :( +static void +data_write_images(Eet_File *ef, int *image_num) { - int bytes = 0; - int total_bytes = 0; + int i; + Ecore_Evas *ee; + Evas *evas; - if ((edje_file) && (edje_file->sound_dir)) + if (!((edje_file) && (edje_file->image_dir))) return; + + ecore_evas_init(); + ee = ecore_evas_buffer_new(1, 1); + if (!ee) + error_and_abort(ef, "Cannot create buffer engine canvas for image " + "load.\n"); + evas = ecore_evas_get(ee); + + for (i = 0; i < edje_file->image_dir->entries_count; i++) { - Eina_List *ll; - Edje_Sound_Sample *sample; -#ifdef HAVE_LIBSNDFILE - Edje_Sound_Encode *enc_info; -#endif - char *dir_path = NULL; - char snd_path[PATH_MAX]; - char sndid_str[15]; - void *fdata; - FILE *fp = NULL; - struct stat st; - int size = 0; - int i; - - for (i = 0; i < (int)edje_file->sound_dir->samples_count; i++) + Edje_Image_Directory_Entry *img; + + img = &edje_file->image_dir->entries[i]; + if ((img->source_type == EDJE_IMAGE_SOURCE_TYPE_EXTERNAL) || + (img->entry == NULL)) { - sample = &edje_file->sound_dir->samples[i]; - memset(&st, 0, sizeof(struct stat)); + } + else + { + Evas_Object *im; + Eina_List *ll; + char *s; + int load_err = EVAS_LOAD_ERROR_NONE; + Image_Write *iw; - // Search the Sound file in all the -sd ( sound directory ) - EINA_LIST_FOREACH(snd_dirs, ll, dir_path) - { - snprintf((char *)snd_path, sizeof(snd_path), "%s/%s", dir_path, - sample->snd_src); - stat(snd_path, &st); - if (st.st_size) break; - } - if (!st.st_size) + iw = calloc(1, sizeof(Image_Write)); + iw->ef = ef; + iw->img = img; + iw->im = im = evas_object_image_add(evas); + evas_object_event_callback_add(im, + EVAS_CALLBACK_IMAGE_PRELOADED, + data_image_preload_done, + iw); + EINA_LIST_FOREACH(img_dirs, ll, s) { - snprintf((char *)snd_path, sizeof(snd_path), "%s", - sample->snd_src); - stat(snd_path, &st); + 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) + { + pending_threads++; + evas_object_image_preload(im, 0); + using_file(buf); + break; + } } - size = st.st_size; - if (!size) + if (load_err != EVAS_LOAD_ERROR_NONE) { - ERR("%s: Error. Unable to load sound source file : %s", - progname, sample->snd_src); - exit(-1); + 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) + { + pending_threads++; + evas_object_image_preload(im, 0); + using_file(img->entry); + } + else + error_and_abort_image_load_error + (ef, img->entry, load_err); } + } + } +} + +typedef struct _Sound_Write +{ + Eet_File *ef; + Edje_Sound_Sample *sample; + int i; +} Sound_Write; + +static void +data_thread_sounds(void *data, Ecore_Thread *thread __UNUSED__) +{ + Sound_Write *sw = data; + Eina_List *ll; #ifdef HAVE_LIBSNDFILE - enc_info = _edje_multisense_encode(snd_path, sample, sample->quality); - - stat(enc_info->file, &st); - size = st.st_size; - fp = fopen(enc_info->file, "rb"); - if (fp) using_file(enc_info->file); + Edje_Sound_Encode *enc_info; +#endif + char *dir_path = NULL; + char snd_path[PATH_MAX]; + char sndid_str[15]; + void *fdata; + FILE *fp = NULL; + struct stat st; + int size = 0; + int bytes = 0; + + memset(&st, 0, sizeof(struct stat)); + // Search the Sound file in all the -sd ( sound directory ) + EINA_LIST_FOREACH(snd_dirs, ll, dir_path) + { + snprintf((char *)snd_path, sizeof(snd_path), "%s/%s", dir_path, + sw->sample->snd_src); + stat(snd_path, &st); + if (st.st_size) break; + } + if (!st.st_size) + { + snprintf((char *)snd_path, sizeof(snd_path), "%s", + sw->sample->snd_src); + stat(snd_path, &st); + } + size = st.st_size; + if (!size) + { + ERR("%s: Error. Unable to load sound source file : %s", + progname, sw->sample->snd_src); + exit(-1); + } +#ifdef HAVE_LIBSNDFILE + enc_info = _edje_multisense_encode(snd_path, sw->sample, + sw->sample->quality); + stat(enc_info->file, &st); + size = st.st_size; + fp = fopen(enc_info->file, "rb"); + if (fp) using_file(enc_info->file); #else - fp = fopen(snd_path, "rb"); - if (fp) using_file(snd_path); + fp = fopen(snd_path, "rb"); + if (fp) using_file(snd_path); #endif - if (!fp) - { - ERR("%s: Error: Unable to load sound data of: %s", - progname, sample->name); - exit(-1); - } - - snprintf(sndid_str, sizeof(sndid_str), "edje/sounds/%i", sample->id); - fdata = malloc(size); - if (!fdata) - { - ERR("%s: Error. %s:%i while allocating memory to load file \"%s\"", - progname, file_in, line, snd_path); - exit(-1); - } - if (fread(fdata, size, 1, fp)) - bytes = eet_write(ef, sndid_str, fdata, size, EINA_FALSE); - free(fdata); - fclose(fp); - + if (!fp) + { + ERR("%s: Error: Unable to load sound data of: %s", + progname, sw->sample->name); + exit(-1); + } + + snprintf(sndid_str, sizeof(sndid_str), "edje/sounds/%i", sw->sample->id); + fdata = malloc(size); + if (!fdata) + { + ERR("%s: Error. %s:%i while allocating memory to load file \"%s\"", + progname, file_in, line, snd_path); + exit(-1); + } + if (fread(fdata, size, 1, fp)) + bytes = eet_write(sw->ef, sndid_str, fdata, size, + EET_COMPRESSION_NONE); + free(fdata); + fclose(fp); + #ifdef HAVE_LIBSNDFILE - //If encoded temporary file, delete it. - if (enc_info->encoded) unlink(enc_info->file); + //If encoded temporary file, delete it. + if (enc_info->encoded) unlink(enc_info->file); #endif - *sound_num += 1; - total_bytes += bytes; - *input_bytes += size; - *input_raw_bytes += size; - - if (verbose) - { + if (verbose) + { #ifdef HAVE_LIBSNDFILE - printf ("%s: Wrote %9i bytes (%4iKb) for \"%s\" %s sound entry" - "\"%s\" \n", progname, bytes, (bytes + 512) / 1024, - sndid_str, enc_info->comp_type, sample->name); + printf ("%s: Wrote %9i bytes (%4iKb) for \"%s\" %s sound entry" + "\"%s\" \n", progname, bytes, (bytes + 512) / 1024, + sndid_str, enc_info->comp_type, sw->sample->name); #else - printf ("%s: Wrote %9i bytes (%4iKb) for \"%s\" %s sound entry" - "\"%s\" \n", progname, bytes, (bytes + 512) / 1024, - sndid_str, "RAW PCM", sample->name); + printf ("%s: Wrote %9i bytes (%4iKb) for \"%s\" %s sound entry" + "\"%s\" \n", progname, bytes, (bytes + 512) / 1024, + sndid_str, "RAW PCM", sw->sample->name); #endif - } + } #ifdef HAVE_LIBSNDFILE - if ((enc_info->file) && (!enc_info->encoded)) eina_stringshare_del(enc_info->file); - if (enc_info) free(enc_info); - enc_info = NULL; + if ((enc_info->file) && (!enc_info->encoded)) + eina_stringshare_del(enc_info->file); + if (enc_info) free(enc_info); + enc_info = NULL; #endif +} + +static void +data_thread_sounds_end(void *data, Ecore_Thread *thread __UNUSED__) +{ + Sound_Write *sw = data; + pending_threads--; + if (pending_threads <= 0) ecore_main_loop_quit(); + free(sw); +} + +static void +data_write_sounds(Eet_File *ef, int *sound_num) +{ + int bytes = 0; + int total_bytes = 0; + + if ((edje_file) && (edje_file->sound_dir)) + { + int i; + + for (i = 0; i < (int)edje_file->sound_dir->samples_count; i++) + { + Sound_Write *sw; + + sw = calloc(1, sizeof(Sound_Write)); + if (!sw) continue; + sw->ef = ef; + sw->sample = &edje_file->sound_dir->samples[i]; + sw->i = i; + *sound_num += 1; + pending_threads++; + ecore_thread_run(data_thread_sounds, data_thread_sounds_end, + NULL, sw); } } - return total_bytes; } static void @@ -821,35 +978,77 @@ check_groups(Eet_File *ef) } } -static int +typedef struct _Group_Write +{ + Eet_File *ef; + Edje_Part_Collection *pc; + char *errstr; +} Group_Write; + +static void +data_thread_group(void *data, Ecore_Thread *thread __UNUSED__) +{ + Group_Write *gw = data; + int bytes; + char buf[PATH_MAX]; + char buf2[PATH_MAX]; + + snprintf(buf, sizeof(buf), "edje/collections/%i", gw->pc->id); + bytes = eet_data_write(gw->ef, edd_edje_part_collection, buf, gw->pc, + compress_mode); + return; + if (bytes <= 0) + { + snprintf(buf2, sizeof(buf2), + "Error. Unable to write \"%s\" part entry to %s\n", + buf, file_out); + gw->errstr = strdup(buf2); + return; + } + + if (verbose) + printf("%s: Wrote %9i bytes (%4iKb) for \"%s\" aka \"%s\" collection entry\n", + progname, bytes, (bytes + 512) / 1024, buf, gw->pc->part); +} + +static void +data_thread_group_end(void *data, Ecore_Thread *thread __UNUSED__) +{ + Group_Write *gw = data; + pending_threads--; + if (pending_threads <= 0) ecore_main_loop_quit(); + if (gw->errstr) + { + error_and_abort(gw->ef, gw->errstr); + free(gw->errstr); + } + free(gw); +} + +static void data_write_groups(Eet_File *ef, int *collection_num) { Eina_List *l; Edje_Part_Collection *pc; - int bytes = 0; - int total_bytes = 0; EINA_LIST_FOREACH(edje_collections, l, pc) { - char buf[4096]; - - snprintf(buf, sizeof(buf), "edje/collections/%i", pc->id); - bytes = eet_data_write(ef, edd_edje_part_collection, buf, pc, 1); - if (bytes <= 0) - error_and_abort(ef, "Error. Unable to write \"%s\" part entry " - "to %s\n", buf, file_out); + Group_Write *gw; - *collection_num += 1; - total_bytes += bytes; - - if (verbose) - { - printf("%s: Wrote %9i bytes (%4iKb) for \"%s\" aka \"%s\" collection entry\n", - progname, bytes, (bytes + 512) / 1024, buf, pc->part); - } + gw = calloc(1, sizeof(Group_Write)); + if (!gw) + { + error_and_abort(ef, + "Error. Cannot allocate memory for group writer\n"); + return; + } + gw->ef = ef; + gw->pc = pc; + pending_threads++; + ecore_thread_run(data_thread_group, data_thread_group_end, + NULL, gw); + *collection_num += 1; } - - return total_bytes; } static void @@ -931,48 +1130,114 @@ create_script_file(Eet_File *ef, const char *filename, const Code *cd, int fd) } static void -compile_script_file(Eet_File *ef, const char *source, const char *output, - int script_num, int fd) +data_thread_script(void *data, Ecore_Thread *thread __UNUSED__) { + Script_Compile *sc = data; FILE *f; - char buf[4096]; - int ret; - - snprintf(buf, sizeof(buf), - "embryo_cc -i %s/include -o %s %s", - eina_prefix_data_get(pfx), output, source); - ret = system(buf); - - /* accept warnings in the embryo code */ - if (ret < 0 || ret > 1) - error_and_abort(ef, "Compiling script code not clean.\n"); + int size; + char buf[PATH_MAX]; - f = fdopen(fd, "rb"); + f = fdopen(sc->tmpo_fd, "rb"); if (!f) - error_and_abort(ef, "Unable to open script object \"%s\" for reading.\n", - output); + { + snprintf(buf, sizeof(buf), + "Unable to open script object \"%s\" for reading.\n", + sc->tmpo); + sc->errstr = strdup(buf); + return; + } fseek(f, 0, SEEK_END); - int size = ftell(f); + size = ftell(f); rewind(f); if (size > 0) { - void *data = malloc(size); + void *dat = malloc(size); - if (data) + if (dat) { - if (fread(data, size, 1, f) != 1) - error_and_abort(ef, "Unable to read all of script object " - "\"%s\"\n", output); - - snprintf(buf, sizeof(buf), "edje/scripts/embryo/compiled/%i", script_num); - eet_write(ef, buf, data, size, 1); - free(data); + if (fread(dat, size, 1, f) != 1) + { + snprintf(buf, sizeof(buf), + "Unable to read all of script object \"%s\"\n", + sc->tmpo); + sc->errstr = strdup(buf); + return; + } + snprintf(buf, sizeof(buf), "edje/scripts/embryo/compiled/%i", + sc->i); + eet_write(sc->ef, buf, dat, size, compress_mode); + free(dat); } + else + { + snprintf(buf, sizeof(buf), + "Alloc failed for %lu bytes\n", (unsigned long)size); + sc->errstr = strdup(buf); + return; + } } - fclose(f); + + if (!no_save) + { + Eina_List *ll; + Code_Program *cp; + + if (sc->cd->original) + { + snprintf(buf, PATH_MAX, "edje/scripts/embryo/source/%i", sc->i); + eet_write(sc->ef, buf, sc->cd->original, + strlen(sc->cd->original) + 1, compress_mode); + } + EINA_LIST_FOREACH(sc->cd->programs, ll, cp) + { + if (!cp->original) continue; + snprintf(buf, PATH_MAX, "edje/scripts/embryo/source/%i/%i", + sc->i, cp->id); + eet_write(sc->ef, buf, cp->original, + strlen(cp->original) + 1, compress_mode); + } + } + + unlink(sc->tmpn); + unlink(sc->tmpo); + close(sc->tmpn_fd); + close(sc->tmpo_fd); +} + +static void +data_thread_script_end(void *data, Ecore_Thread *thread __UNUSED__) +{ + Script_Compile *sc = data; + pending_threads--; + if (pending_threads <= 0) ecore_main_loop_quit(); + if (sc->errstr) + { + error_and_abort(sc->ef, sc->errstr); + free(sc->errstr); + } + free(sc); +} + +static Eina_Bool +data_scripts_exe_del_cb(void *data __UNUSED__, int evtype __UNUSED__, void *evinfo) +{ + Script_Compile *sc = data; + Ecore_Exe_Event_Del *ev = evinfo; + + if (!ev->exe) return ECORE_CALLBACK_RENEW; + if (ecore_exe_data_get(ev->exe) != sc) return ECORE_CALLBACK_RENEW; + if (ev->exit_code != 0) + { + error_and_abort(sc->ef, "Compiling script code not clean.\n"); + return ECORE_CALLBACK_CANCEL; + } + pending_threads++; + ecore_thread_run(data_thread_script, data_thread_script_end, + NULL, sc); + return ECORE_CALLBACK_CANCEL; } static void @@ -990,57 +1255,41 @@ data_write_scripts(Eet_File *ef) for (i = 0, l = codes; l; l = eina_list_next(l), i++) { - char tmpn[PATH_MAX]; - char tmpo[PATH_MAX]; - int fd; Code *cd = eina_list_data_get(l); + Script_Compile *sc; + char buf[PATH_MAX]; if (cd->is_lua) continue; if ((!cd->shared) && (!cd->programs)) continue; - - snprintf(tmpn, PATH_MAX, "%s/edje_cc.sma-tmp-XXXXXX", tmp_dir); - fd = mkstemp(tmpn); - if (fd < 0) - error_and_abort(ef, "Unable to open temp file \"%s\" for script " - "compilation.\n", tmpn); - - create_script_file(ef, tmpn, cd, fd); - - snprintf(tmpo, PATH_MAX, "%s/edje_cc.amx-tmp-XXXXXX", tmp_dir); - fd = mkstemp(tmpo); - if (fd < 0) - { - unlink(tmpn); - error_and_abort(ef, "Unable to open temp file \"%s\" for script " - "compilation.\n", tmpn); - } - compile_script_file(ef, tmpn, tmpo, i, fd); - - unlink(tmpn); - unlink(tmpo); - - if (!no_save) + sc = calloc(1, sizeof(Script_Compile)); + sc->ef = ef; + sc->cd = cd; + sc->i = i; + // XXX: from here + snprintf(sc->tmpn, PATH_MAX, "%s/edje_cc.sma-tmp-XXXXXX", tmp_dir); + sc->tmpn_fd = mkstemp(sc->tmpn); + if (sc->tmpn_fd < 0) + error_and_abort(ef, "Unable to open temp file \"%s\" for script " + "compilation.\n", sc->tmpn); + snprintf(sc->tmpo, PATH_MAX, "%s/edje_cc.amx-tmp-XXXXXX", tmp_dir); + sc->tmpo_fd = mkstemp(sc->tmpo); + if (sc->tmpo_fd < 0) { - char buf[PATH_MAX]; - Eina_List *ll; - Code_Program *cp; - - if (cd->original) - { - snprintf(buf, PATH_MAX, "edje/scripts/embryo/source/%i", i); - eet_write(ef, buf, cd->original, strlen(cd->original) + 1, 1); - } - EINA_LIST_FOREACH(cd->programs, ll, cp) - { - if (!cp->original) - continue; - snprintf(buf, PATH_MAX, "edje/scripts/embryo/source/%i/%i", i, - cp->id); - eet_write(ef, buf, cp->original, strlen(cp->original) + 1, 1); - } + unlink(sc->tmpn); + error_and_abort(ef, "Unable to open temp file \"%s\" for script " + "compilation.\n", sc->tmpn); } + create_script_file(ef, sc->tmpn, cd, sc->tmpn_fd); + // XXX; to here -> can make set of threads that report back and then + // spawn + snprintf(buf, sizeof(buf), + "embryo_cc -i %s/include -o %s %s", + eina_prefix_data_get(pfx), sc->tmpo, sc->tmpn); + sc->exe = ecore_exe_run(buf, sc); + ecore_event_handler_add(ECORE_EXE_EVENT_DEL, + data_scripts_exe_del_cb, sc); } } @@ -1061,11 +1310,10 @@ _edje_lua_script_writer(lua_State *L __UNUSED__, const void *chunk_buf, size_t c data = (Edje_Lua_Script_Writer_Struct *)_data; old = data->buf; - data->buf = malloc (data->size + chunk_size); - memcpy (data->buf, old, data->size); - memcpy (&((data->buf)[data->size]), chunk_buf, chunk_size); - if (old) - free (old); + data->buf = malloc(data->size + chunk_size); + memcpy(data->buf, old, data->size); + memcpy(&((data->buf)[data->size]), chunk_buf, chunk_size); + if (old) free(old); data->size += chunk_size; return 0; @@ -1073,140 +1321,209 @@ _edje_lua_script_writer(lua_State *L __UNUSED__, const void *chunk_buf, size_t c #endif void -_edje_lua_error_and_abort(lua_State * L, int err_code, Eet_File *ef) +_edje_lua_error_and_abort(lua_State *L, int err_code, Script_Compile *sc) { + char buf[PATH_MAX]; char *err_type; - + switch (err_code) { - case LUA_ERRRUN: + case LUA_ERRRUN: err_type = "runtime"; break; - case LUA_ERRSYNTAX: + case LUA_ERRSYNTAX: err_type = "syntax"; break; - case LUA_ERRMEM: + case LUA_ERRMEM: err_type = "memory allocation"; break; - case LUA_ERRERR: + case LUA_ERRERR: err_type = "error handler"; break; - default: + default: err_type = "unknown"; break; } - error_and_abort(ef, "Lua %s error: %s\n", err_type, lua_tostring(L, -1)); + snprintf(buf, sizeof(buf), + "Lua %s error: %s\n", err_type, lua_tostring(L, -1)); + sc->errstr = strdup(buf); } +static void +data_thread_lua_script(void *data, Ecore_Thread *thread __UNUSED__) +{ + Script_Compile *sc = data; + char buf[PATH_MAX]; + lua_State *L; + int ln = 1; + luaL_Buffer b; + Edje_Lua_Script_Writer_Struct dat; + Eina_List *ll; + Code_Program *cp; +#ifdef LUA_BINARY + int err_code; +#endif + + L = luaL_newstate(); + if (!L) + { + snprintf(buf, sizeof(buf), + "Lua error: Lua state could not be initialized\n"); + sc->errstr = strdup(buf); + return; + } + + luaL_buffinit(L, &b); + + dat.buf = NULL; + dat.size = 0; + if (sc->cd->shared) + { + while (ln < (sc->cd->l1 - 1)) + { + luaL_addchar(&b, '\n'); + ln++; + } + luaL_addstring(&b, sc->cd->shared); + ln += sc->cd->l2 - sc->cd->l1; + } + + EINA_LIST_FOREACH(sc->cd->programs, ll, cp) + { + if (cp->script) + { + while (ln < (cp->l1 - 1)) + { + luaL_addchar(&b, '\n'); + ln++; + } + luaL_addstring(&b, "_G["); + lua_pushnumber(L, cp->id); + luaL_addvalue(&b); + luaL_addstring(&b, "] = function (ed, signal, source)"); + luaL_addstring(&b, cp->script); + luaL_addstring(&b, "end\n"); + ln += cp->l2 - cp->l1 + 1; + } + } + luaL_pushresult(&b); +#ifdef LUA_BINARY + if (err_code = luaL_loadstring(L, lua_tostring (L, -1))) + { + _edje_lua_error_and_abort(L, err_code, sc); + return; + } + lua_dump(L, _edje_lua_script_writer, &dat); +#else // LUA_PLAIN_TEXT + dat.buf = (char *)lua_tostring(L, -1); + dat.size = strlen(dat.buf); +#endif + //printf("lua chunk size: %d\n", dat.size); + + /* + * TODO load and test Lua chunk + */ + + /* + if (luaL_loadbuffer(L, globbuf, globbufsize, "edje_lua_script")) + printf("lua load error: %s\n", lua_tostring (L, -1)); + if (lua_pcall(L, 0, 0, 0)) + printf("lua call error: %s\n", lua_tostring (L, -1)); + */ + + snprintf(buf, sizeof(buf), "edje/scripts/lua/%i", sc->i); + if (eet_write(sc->ef, buf, dat.buf, dat.size, compress_mode) <= 0) + { + snprintf(buf, sizeof(buf), + "Unable to write script %i\n", sc->i); + sc->errstr = strdup(buf); + return; + } +#ifdef LUA_BINARY + free(dat.buf); +#endif + lua_close(L); +} + +static void +data_thread_lua_script_end(void *data, Ecore_Thread *thread __UNUSED__) +{ + Script_Compile *sc = data; + pending_threads--; + if (pending_threads <= 0) ecore_main_loop_quit(); + if (sc->errstr) + { + error_and_abort(sc->ef, sc->errstr); + free(sc->errstr); + } + free(sc); +} static void data_write_lua_scripts(Eet_File *ef) { Eina_List *l; - Eina_List *ll; - Code_Program *cp; int i; for (i = 0, l = codes; l; l = eina_list_next(l), i++) { - char buf[4096]; - Code *cd; - lua_State *L; - int ln = 1; - luaL_Buffer b; - Edje_Lua_Script_Writer_Struct data; -#ifdef LUA_BINARY - int err_code; -#endif + Code *cd; + Script_Compile *sc; + + cd = (Code *)eina_list_data_get(l); + if (!cd->is_lua) + continue; + if ((!cd->shared) && (!cd->programs)) + continue; + + sc = calloc(1, sizeof(Script_Compile)); + sc->ef = ef; + sc->cd = cd; + sc->i = i; + pending_threads++; + ecore_thread_run(data_thread_lua_script, data_thread_lua_script_end, + NULL, sc); + } +} - cd = (Code *)eina_list_data_get(l); - if (!cd->is_lua) - continue; - if ((!cd->shared) && (!cd->programs)) - continue; - - L = luaL_newstate(); - if (!L) - error_and_abort(ef, "Lua error: Lua state could not be initialized\n"); +static void +data_thread_source(void *data, Ecore_Thread *thread __UNUSED__) +{ + Eet_File *ef = data; + source_append(ef); +} - luaL_buffinit(L, &b); +static void +data_thread_source_end(void *data __UNUSED__, Ecore_Thread *thread __UNUSED__) +{ + pending_threads--; + if (pending_threads <= 0) ecore_main_loop_quit(); +} - data.buf = NULL; - data.size = 0; - if (cd->shared) - { - while (ln < (cd->l1 - 1)) - { - luaL_addchar(&b, '\n'); - ln++; - } - luaL_addstring(&b, cd->shared); - ln += cd->l2 - cd->l1; - } +static void +data_thread_fontmap(void *data, Ecore_Thread *thread __UNUSED__) +{ + Eet_File *ef = data; + source_fontmap_save(ef, fonts); +} - EINA_LIST_FOREACH(cd->programs, ll, cp) - { - if (cp->script) - { - while (ln < (cp->l1 - 1)) - { - luaL_addchar(&b, '\n'); - ln++; - } - luaL_addstring(&b, "_G["); - lua_pushnumber(L, cp->id); - luaL_addvalue(&b); - luaL_addstring(&b, "] = function (ed, signal, source)"); - luaL_addstring(&b, cp->script); - luaL_addstring(&b, "end\n"); - ln += cp->l2 - cp->l1 + 1; - } - } - luaL_pushresult(&b); -#ifdef LUA_BINARY - if (err_code = luaL_loadstring(L, lua_tostring (L, -1))) - _edje_lua_error_and_abort(L, err_code, ef); - lua_dump(L, _edje_lua_script_writer, &data); -#else // LUA_PLAIN_TEXT - data.buf = (char *)lua_tostring(L, -1); - data.size = strlen(data.buf); -#endif - //printf("lua chunk size: %d\n", data.size); - - /* - * TODO load and test Lua chunk - */ - - /* - if (luaL_loadbuffer(L, globbuf, globbufsize, "edje_lua_script")) - printf("lua load error: %s\n", lua_tostring (L, -1)); - if (lua_pcall(L, 0, 0, 0)) - printf("lua call error: %s\n", lua_tostring (L, -1)); - */ - - snprintf(buf, sizeof(buf), "edje/scripts/lua/%i", i); - eet_write(ef, buf, data.buf, data.size, 1); -#ifdef LUA_BINARY - free(data.buf); -#endif - lua_close(L); - } +static void +data_thread_fontmap_end(void *data __UNUSED__, Ecore_Thread *thread __UNUSED__) +{ + pending_threads--; + if (pending_threads <= 0) ecore_main_loop_quit(); } void data_write(void) { Eet_File *ef; - int input_bytes = 0; - int total_bytes = 0; - int src_bytes = 0; - int fmap_bytes = 0; - int input_raw_bytes = 0; int image_num = 0; int sound_num = 0; int font_num = 0; int collection_num = 0; - + double t; + if (!edje_file) { ERR("%s: Error. No data to put in \"%s\"", @@ -1224,66 +1541,76 @@ data_write(void) check_groups(ef); - total_bytes += data_write_header(ef); - total_bytes += data_write_fonts(ef, &font_num, &input_bytes, - &input_raw_bytes); - total_bytes += data_write_images(ef, &image_num, &input_bytes, - &input_raw_bytes); - total_bytes += data_write_sounds(ef, &sound_num, &input_bytes, - &input_raw_bytes); - - total_bytes += data_write_groups(ef, &collection_num); + ecore_thread_max_set(ecore_thread_max_get() * 2); + + t = ecore_time_get(); + data_write_header(ef); + if (verbose) + { + printf("header: %3.5f\n", ecore_time_get() - t); t = ecore_time_get(); + } + data_write_groups(ef, &collection_num); + if (verbose) + { + printf("groups: %3.5f\n", ecore_time_get() - t); t = ecore_time_get(); + } data_write_scripts(ef); + if (verbose) + { + printf("scripts: %3.5f\n", ecore_time_get() - t); t = ecore_time_get(); + } data_write_lua_scripts(ef); + if (verbose) + { + printf("lua scripts: %3.5f\n", ecore_time_get() - t); t = ecore_time_get(); + } + pending_threads++; + ecore_thread_run(data_thread_source, data_thread_source_end, NULL, ef); + if (verbose) + { + printf("source: %3.5f\n", ecore_time_get() - t); t = ecore_time_get(); + } + pending_threads++; + ecore_thread_run(data_thread_fontmap, data_thread_fontmap_end, NULL, ef); + if (verbose) + { + printf("fontmap: %3.5f\n", ecore_time_get() - t); t = ecore_time_get(); + } + data_write_images(ef, &image_num); + if (verbose) + { + printf("images: %3.5f\n", ecore_time_get() - t); t = ecore_time_get(); + } + data_write_fonts(ef, &font_num); + if (verbose) + { + printf("fonts: %3.5f\n", ecore_time_get() - t); t = ecore_time_get(); + } + data_write_sounds(ef, &sound_num); + if (verbose) + { + printf("sounds: %3.5f\n", ecore_time_get() - t); t = ecore_time_get(); + } - src_bytes = source_append(ef); - total_bytes += src_bytes; - fmap_bytes = source_fontmap_save(ef, fonts); - total_bytes += fmap_bytes; - - eet_close(ef); - + ecore_main_loop_begin(); if (verbose) { - struct stat st; - - if (stat(file_in, &st) != 0) - st.st_size = 0; - input_bytes += st.st_size; - input_raw_bytes += st.st_size; - printf("Summary:\n" - " Wrote %i collections\n" - " Wrote %i images\n" - " Wrote %i sounds\n" - " Wrote %i fonts\n" - " Wrote %i bytes (%iKb) of original source data\n" - " Wrote %i bytes (%iKb) of original source font map\n" - "Conservative compression summary:\n" - " Wrote total %i bytes (%iKb) from %i (%iKb) input data\n" - " Output file is %3.1f%% the size of the input data\n" - " Saved %i bytes (%iKb)\n" - "Raw compression summary:\n" - " Wrote total %i bytes (%iKb) from %i (%iKb) raw input data\n" - " Output file is %3.1f%% the size of the raw input data\n" - " Saved %i bytes (%iKb)\n" - , - collection_num, - image_num, - sound_num, - font_num, - src_bytes, (src_bytes + 512) / 1024, - fmap_bytes, (fmap_bytes + 512) / 1024, - total_bytes, (total_bytes + 512) / 1024, - input_bytes, (input_bytes + 512) / 1024, - (100.0 * (double)total_bytes) / (double)input_bytes, - input_bytes - total_bytes, - (input_bytes - total_bytes + 512) / 1024, - total_bytes, (total_bytes + 512) / 1024, - input_raw_bytes, (input_raw_bytes + 512) / 1024, - (100.0 * (double)total_bytes) / (double)input_raw_bytes, - input_raw_bytes - total_bytes, - (input_raw_bytes - total_bytes + 512) / 1024); + printf("THREADS: %3.5f\n", ecore_time_get() - t); t = ecore_time_get(); } + + eet_close(ef); + + if (verbose) + printf("Summary:\n" + " Wrote %i collections\n" + " Wrote %i images\n" + " Wrote %i sounds\n" + " Wrote %i fonts\n" + , + collection_num, + image_num, + sound_num, + font_num); } void @@ -1419,46 +1746,74 @@ data_queue_group_lookup(const char *name, Edje_Part *part) gl->part = part; } +static Eina_Hash *_part_lookups_hash = NULL; +static Eina_Hash *_part_lookups_dest_hash = NULL; + void data_queue_part_lookup(Edje_Part_Collection *pc, const char *name, int *dest) { + Part_Lookup *pl = NULL; + char buf[256]; Eina_List *l; - Part_Lookup *pl; - - EINA_LIST_FOREACH(part_lookups, l, pl) + + snprintf(buf, sizeof(buf), "%lu-%lu", + (unsigned long)name, (unsigned long)dest); + if (_part_lookups_hash) pl = eina_hash_find(_part_lookups_hash, buf); + if (pl) { - if ((pl->pc == pc) && (pl->dest == dest)) + free(pl->name); + if (name[0]) + pl->name = mem_strdup(name); + else { - free(pl->name); - if (name[0]) - pl->name = mem_strdup(name); - else - { - part_lookups = eina_list_remove(part_lookups, pl); - free(pl); - } - return; + eina_hash_del(_part_lookups_hash, buf, pl); + snprintf(buf, sizeof(buf), "%lu", (unsigned long)dest); + eina_hash_del(_part_lookups_dest_hash, buf, pl); + part_lookups = eina_list_remove(part_lookups, pl); + free(pl); } + return; } if (!name[0]) return; pl = mem_alloc(SZ(Part_Lookup)); - part_lookups = eina_list_append(part_lookups, pl); + part_lookups = eina_list_prepend(part_lookups, pl); pl->pc = pc; pl->name = mem_strdup(name); pl->dest = dest; + if (!_part_lookups_hash) + _part_lookups_hash = eina_hash_string_superfast_new(NULL); + eina_hash_add(_part_lookups_hash, buf, pl); + + snprintf(buf, sizeof(buf), "%lu", (unsigned long)dest); + if (!_part_lookups_dest_hash) + _part_lookups_dest_hash = eina_hash_string_superfast_new(NULL); + l = eina_hash_find(_part_lookups_dest_hash, buf); + if (l) + { + l = eina_list_append(l, pl); + eina_hash_modify(_part_lookups_dest_hash, buf, l); + } + else + { + l = eina_list_append(l, pl); + eina_hash_add(_part_lookups_dest_hash, buf, l); + } } void data_queue_copied_part_lookup(Edje_Part_Collection *pc, int *src, int *dest) { - Eina_List *l; + Eina_List *l, *list; Part_Lookup *pl; + char buf[256]; - EINA_LIST_FOREACH(part_lookups, l, pl) + if (!_part_lookups_dest_hash) return; + snprintf(buf, sizeof(buf), "%lu", (unsigned long)src); + list = eina_hash_find(_part_lookups_dest_hash, buf); + EINA_LIST_FOREACH(list, l, pl) { - if (pl->dest == src) - data_queue_part_lookup(pc, pl->name, dest); + data_queue_part_lookup(pc, pl->name, dest); } } @@ -2196,11 +2551,12 @@ data_process_script_lookups(void) void using_file(const char *filename) { - FILE *f; + FILE *f; - f = fopen(watchfile, "a"); - if (!f) return ; - fputs(filename, f); - fputc('\n', f); - fclose(f); + if (!watchfile) return; + f = fopen(watchfile, "a"); + if (!f) return ; + fputs(filename, f); + fputc('\n', f); + fclose(f); } diff --git a/src/bin/edje_cc_parse.c b/src/bin/edje_cc_parse.c index 8161977..ed70877 100644 --- a/src/bin/edje_cc_parse.c +++ b/src/bin/edje_cc_parse.c @@ -119,44 +119,57 @@ err_show(void) err_show_params(); } +static Eina_Hash *_new_object_hash = NULL; +static Eina_Hash *_new_statement_hash = NULL; +static void +fill_object_statement_hashes(void) +{ + int i, n; + + if (_new_object_hash) return; + + _new_object_hash = eina_hash_string_superfast_new(NULL); + _new_statement_hash = eina_hash_string_superfast_new(NULL); + + n = object_handler_num(); + for (i = 0; i < n; i++) + { + eina_hash_add(_new_object_hash, object_handlers[i].type, + &(object_handlers[i])); + } + n = statement_handler_num(); + for (i = 0; i < n; i++) + { + eina_hash_add(_new_statement_hash, statement_handlers[i].type, + &(statement_handlers[i])); + } +} + static void new_object(void) { char *id; - int i; - int handled = 0; + New_Object_Handler *oh; + New_Statement_Handler *sh; + fill_object_statement_hashes(); id = stack_id(); - for (i = 0; i < object_handler_num(); i++) - { - if (!strcmp(object_handlers[i].type, id)) - { - handled = 1; - if (object_handlers[i].func) - { - object_handlers[i].func(); - } - break; - } - } - if (!handled) + oh = eina_hash_find(_new_object_hash, id); + if (oh) { - for (i = 0; i < statement_handler_num(); i++) - { - if (!strcmp(statement_handlers[i].type, id)) - { - free(id); - return; - } - } + if (oh->func) oh->func(); } - if (!handled) + else { - ERR("%s: Error. %s:%i unhandled keyword %s", - progname, file_in, line - 1, - (char *)eina_list_data_get(eina_list_last(stack))); - err_show(); - exit(-1); + sh = eina_hash_find(_new_statement_hash, id); + if (!sh) + { + ERR("%s: Error. %s:%i unhandled keyword %s", + progname, file_in, line - 1, + (char *)eina_list_data_get(eina_list_last(stack))); + err_show(); + exit(-1); + } } free(id); } @@ -165,29 +178,22 @@ static void new_statement(void) { char *id; - int i; - int handled = 0; + New_Statement_Handler *sh; + fill_object_statement_hashes(); id = stack_id(); - for (i = 0; i < statement_handler_num(); i++) + sh = eina_hash_find(_new_statement_hash, id); + if (sh) { - if (!strcmp(statement_handlers[i].type, id)) - { - handled = 1; - if (statement_handlers[i].func) - { - statement_handlers[i].func(); - } - break; - } + if (sh->func) sh->func(); } - if (!handled) + else { - ERR("%s: Error. %s:%i unhandled keyword %s", - progname, file_in, line - 1, - (char *)eina_list_data_get(eina_list_last(stack))); + ERR("%s: Error. %s:%i unhandled keyword %s", + progname, file_in, line - 1, + (char *)eina_list_data_get(eina_list_last(stack))); err_show(); - exit(-1); + exit(-1); } free(id); } diff --git a/src/bin/edje_cc_sources.c b/src/bin/edje_cc_sources.c index d9cd0c1..ab2f5d9 100644 --- a/src/bin/edje_cc_sources.c +++ b/src/bin/edje_cc_sources.c @@ -228,7 +228,8 @@ source_fetch(void) int source_append(Eet_File *ef) { - return eet_data_write(ef, _srcfile_list_edd, "edje_sources", &srcfiles, 1); + return eet_data_write(ef, _srcfile_list_edd, "edje_sources", &srcfiles, + compress_mode); } SrcFile_List * @@ -246,7 +247,8 @@ source_fontmap_save(Eet_File *ef, Eina_List *font_list) Font_List fl; fl.list = font_list; - return eet_data_write(ef, _font_list_edd, "edje_source_fontmap", &fl, 1); + return eet_data_write(ef, _font_list_edd, "edje_source_fontmap", &fl, + compress_mode); } Font_List * diff --git a/src/bin/edje_decc.c b/src/bin/edje_decc.c index ac776e9..fd228d7 100644 --- a/src/bin/edje_decc.c +++ b/src/bin/edje_decc.c @@ -22,6 +22,7 @@ int _edje_cc_log_dom = -1; char *progname = NULL; char *file_in = NULL; char *file_out = NULL; +int compress_mode = EET_COMPRESSION_DEFAULT; Edje_File *edje_file = NULL; SrcFile_List *srcfiles = NULL; -- 2.7.4