From 0e1f0cf1c5f7766f5228e74bbbc718a4e898660c Mon Sep 17 00:00:00 2001 From: Daniel Zaoui Date: Mon, 4 Jun 2018 23:59:02 +0300 Subject: [PATCH] Exactness: add fonts support One of the biggest issue in Exactness is related to the system configuration differences. Among them, the fonts can for example impact on the height of the widgets. The solution to not be dependent on the fonts consist in using embedded fonts and to force their usage when playing the applications. The -f option has been added to the player and the recorder so the user can provide the path to a fonts directory. This option must be set in order to force the fonts replacement. Since tests shots can use different fonts, the exu file stores the version of fonts that have been used. This is why it is needed to have in the provided directory different directories, each pointing to a different version of the fonts. For example, some old tests can use fonts of 2017 (e.g directory 20170101) while new tests will use new fonts (20180601). Check the exactness-elm-data repository (fonts branch) for a better understanding. During recording, the -f option will apply the indicated fonts on the launched application and will record the mouse events accordingly. The fonts datestamp is stored in the exu output. During playing, the fonts will be loaded by reading the exu fonts path, and then the application is launched. If no information is provided in the exu but -f is used, the tool will load the most recent fonts (by comparing the datestamp directories). --- src/bin/exactness.c | 7 ++- src/bin/inspect.c | 38 ++++++++++++++++ src/bin/player.c | 104 ++++++++++++++++++++++++++++++++------------ src/bin/recorder.c | 38 +++++++++++++--- src/lib/Exactness.h | 1 + src/lib/unit.c | 1 + 6 files changed, 153 insertions(+), 36 deletions(-) diff --git a/src/bin/exactness.c b/src/bin/exactness.c index 6a31336..5323046 100644 --- a/src/bin/exactness.c +++ b/src/bin/exactness.c @@ -36,7 +36,7 @@ typedef enum static unsigned short _running_jobs = 0, _max_jobs = 1; static Eina_List *_base_dirs = NULL; static char *_dest_dir; -static char *_wrap_command = NULL; +static char *_wrap_command = NULL, *_fonts_dir = NULL; static int _verbose = 0; static Eina_Bool _scan_objs = EINA_FALSE; @@ -226,9 +226,10 @@ _run_command_prepare(const List_Entry *ent, char *buf) ok: sbuf = eina_strbuf_new(); eina_strbuf_append_printf(sbuf, - "%s %s exactness_play %s %s%.*s %s-t '%s' ", + "%s %s exactness_play %s %s%s %s%.*s %s-t '%s' ", CONFIG, _wrap_command ? _wrap_command : "", _mode == RUN_SIMULATION ? "-s" : "", + _fonts_dir ? "-f " : "", _fonts_dir ? _fonts_dir : "", _verbose ? "-" : "", _verbose, "vvvvvvvvvv", _scan_objs ? "--scan-objects " : "", scn_path @@ -458,6 +459,7 @@ static const Ecore_Getopt optdesc = { ECORE_GETOPT_STORE_TRUE('i', "init", "Run in init mode."), ECORE_GETOPT_STORE_TRUE('s', "simulation", "Run in simulation mode."), ECORE_GETOPT_STORE_TRUE(0, "scan-objects", "Extract information of all the objects at every shot."), + ECORE_GETOPT_STORE_STR('f', "fonts-dir", "Specify a directory of the fonts that should be used."), ECORE_GETOPT_COUNT('v', "verbose", "Turn verbose messages on."), ECORE_GETOPT_LICENSE('L', "license"), @@ -489,6 +491,7 @@ main(int argc, char *argv[]) ECORE_GETOPT_VALUE_BOOL(mode_init), ECORE_GETOPT_VALUE_BOOL(mode_simulation), ECORE_GETOPT_VALUE_BOOL(scan_objs), + ECORE_GETOPT_VALUE_STR(_fonts_dir), ECORE_GETOPT_VALUE_INT(_verbose), ECORE_GETOPT_VALUE_BOOL(want_quit), diff --git a/src/bin/inspect.c b/src/bin/inspect.c index 42f3a0d..1b3e953 100644 --- a/src/bin/inspect.c +++ b/src/bin/inspect.c @@ -21,6 +21,7 @@ typedef enum { + EX_FONTS_DIR, EX_SCENARIO, EX_IMAGE, EX_OBJ_INFO @@ -296,12 +297,37 @@ _grp_text_get(void *data, Evas_Object *gl, const char *part EINA_UNUSED) _Data_Type dt = (_Data_Type) data; switch (dt) { + case EX_FONTS_DIR: + { + char buf2[256]; + if (!compare) + { + Exactness_Unit *unit = efl_key_data_get(gl, "unit"); + sprintf(buf2, "Fonts directory: %s", unit->fonts_path?unit->fonts_path:"None"); + } + else + { + Eo *gl1 = eina_list_nth(_gls, 0); + Eo *gl2 = eina_list_nth(_gls, 1); + Exactness_Unit *unit1 = efl_key_data_get(gl1, "unit"); + Exactness_Unit *unit2 = efl_key_data_get(gl2, "unit"); + if (!!unit1->fonts_path ^ !!unit2->fonts_path) + sprintf(buf2, "Fonts directory comparison: XXXXX"); + else if (!strcmp(unit1->fonts_path, unit2->fonts_path)) + sprintf(buf2, "Fonts directory comparison: %s", unit1->fonts_path); + else + sprintf(buf2, "Fonts directory comparison: "LDIFF(%s)"/"RDIFF(%s), + unit1->fonts_path, unit2->fonts_path); + } + return strdup(buf2); + } case EX_SCENARIO: { str = "Scenario"; break; } case EX_IMAGE: { str = "Images"; break; } case EX_OBJ_INFO: { str = "Objects"; break; } default: { str = "Unknown"; break; } } sprintf(buf, "%s%s", str, compare ? " comparison" : ""); + if (dt == EX_FONTS_DIR) eina_stringshare_del(str); return strdup(buf); } @@ -916,6 +942,17 @@ _gui_unit_display(Exactness_Unit *unit1, Exactness_Unit *unit2) } _itc_init(); + if (unit1->fonts_path || (unit2 && unit2->fonts_path)) + { + if (!_show_only_diffs || !unit1 || !unit2 || + !unit1->fonts_path || !unit2->fonts_path || + strcmp(unit1->fonts_path, unit2->fonts_path)) + { + elm_genlist_item_append(gl1, _grp_itc, (void *)EX_FONTS_DIR, NULL, ELM_GENLIST_ITEM_GROUP, NULL, NULL); + elm_genlist_item_append(gl2, _grp_itc, (void *)EX_FONTS_DIR, NULL, ELM_GENLIST_ITEM_GROUP, NULL, NULL); + elm_genlist_item_append(glc, _grp_itc, (void *)EX_FONTS_DIR, NULL, ELM_GENLIST_ITEM_GROUP, NULL, NULL); + } + } itr1 = unit1 ? unit1->actions : NULL; itr2 = unit2 ? unit2->actions : NULL; @@ -1283,6 +1320,7 @@ main(int argc, char *argv[]) { Exactness_Action *act; Eina_List *itr; + if (unit->fonts_path) printf("Fonts dir: %s\n", unit->fonts_path); EINA_LIST_FOREACH(unit->actions, itr, act) { char specific_output[1024]; diff --git a/src/bin/player.c b/src/bin/player.c index 632af49..0fd10b9 100644 --- a/src/bin/player.c +++ b/src/bin/player.c @@ -819,36 +819,32 @@ _prg_invoke(const char *full_path, int argc, char **argv) return 1; } - if (_src_open()) + if (efl_main) { - if (efl_main) - { - elm_init(argc, argv); - elm_theme_overlay_add(NULL, DATA_DIR"/exactness_play.edj"); - efl_event_callback_add(efl_main_loop_get(), EFL_LOOP_EVENT_ARGUMENTS, efl_main, NULL); - ret__ = efl_loop_begin(efl_main_loop_get()); - real__ = efl_loop_exit_code_process(ret__); - elm_shutdown(); - } - else if (elm_main) - { - elm_init(argc, argv); - elm_theme_overlay_add(NULL, DATA_DIR"/exactness_play.edj"); - real__ = elm_main(argc, argv); - elm_shutdown(); - } - else if (c_main) - { - real__ = c_main(argc, argv); - } - else - { - fprintf(stderr, "Failed loading symbol 'efl_main', 'elm_main' or 'main' from %s.\n", full_path); - eina_module_free(h); - real__ = 1; - } + elm_init(argc, argv); + elm_theme_overlay_add(NULL, DATA_DIR"/exactness_play.edj"); + efl_event_callback_add(efl_main_loop_get(), EFL_LOOP_EVENT_ARGUMENTS, efl_main, NULL); + ret__ = efl_loop_begin(efl_main_loop_get()); + real__ = efl_loop_exit_code_process(ret__); + elm_shutdown(); + } + else if (elm_main) + { + elm_init(argc, argv); + elm_theme_overlay_add(NULL, DATA_DIR"/exactness_play.edj"); + real__ = elm_main(argc, argv); + elm_shutdown(); + } + else if (c_main) + { + real__ = c_main(argc, argv); + } + else + { + fprintf(stderr, "Failed loading symbol 'efl_main', 'elm_main' or 'main' from %s.\n", full_path); + eina_module_free(h); + real__ = 1; } - else real__ = 1; return real__; } @@ -938,6 +934,7 @@ static const Ecore_Getopt optdesc = { ECORE_GETOPT_STORE_TRUE(0, "scan-objects", "Extract information of all the objects at every shot."), ECORE_GETOPT_STORE_TRUE(0, "external-injection", "Expect events injection via Eina debug channel."), ECORE_GETOPT_STORE_TRUE(0, "disable-screenshots", "Disable screenshots."), + ECORE_GETOPT_STORE_STR('f', "fonts-dir", "Specify a directory of the fonts that should be used."), ECORE_GETOPT_COUNT('v', "verbose", "Turn verbose messages on."), ECORE_GETOPT_LICENSE('L', "license"), @@ -952,6 +949,8 @@ int main(int argc, char **argv) { int pret = 1, opt_args = 0; char *src = NULL, *dest = NULL, *eq; + char *fonts_dir = NULL; + const char *chosen_fonts = NULL; Eina_Bool show_on_screen = EINA_FALSE; Eina_Bool want_quit = EINA_FALSE, external_injection = EINA_FALSE; @@ -962,6 +961,7 @@ int main(int argc, char **argv) ECORE_GETOPT_VALUE_BOOL(_scan_objects), ECORE_GETOPT_VALUE_BOOL(external_injection), ECORE_GETOPT_VALUE_BOOL(_disable_shots), + ECORE_GETOPT_VALUE_STR(fonts_dir), ECORE_GETOPT_VALUE_INT(_verbose), ECORE_GETOPT_VALUE_BOOL(want_quit), @@ -1067,7 +1067,6 @@ int main(int argc, char **argv) goto end; } - if (!show_on_screen) setenv("ELM_ENGINE", "buffer", 1); if (!argv[opt_args]) { fprintf(stderr, "no program specified\nUse -h for more information\n"); @@ -1076,6 +1075,53 @@ int main(int argc, char **argv) if (_dest_type == FTYPE_EXU) _dest_unit = calloc(1, sizeof(*_dest_unit)); + if (!_src_open()) + { + fprintf(stderr, "Unable to read source file\n"); + goto end; + } + + if (!show_on_screen) setenv("ELM_ENGINE", "buffer", 1); + if (_src_unit && _src_unit->fonts_path) + { + char buf[PATH_]; + if (!fonts_dir) fonts_dir = "./fonts"; + sprintf(buf, "%s/%s", fonts_dir, _src_unit->fonts_path); + if (!ecore_file_exists(buf)) + { + fprintf(stderr, "Unable to use the fonts path '%s' provided in %s\n", + _src_unit->fonts_path, _src_filename); + goto end; + } + chosen_fonts = _src_unit->fonts_path; + } + if (fonts_dir) + { + Eina_Tmpstr *fonts_conf_name = NULL; + if (!ecore_file_exists(fonts_dir)) + { + fprintf(stderr, "Unable to find fonts directory %s\n", fonts_dir); + goto end; + } + if (!chosen_fonts) + { + Eina_List *dated_fonts = ecore_file_ls(fonts_dir); + char *date_dir; + chosen_fonts = eina_stringshare_add(eina_list_last_data_get(dated_fonts)); + EINA_LIST_FREE(dated_fonts, date_dir) free(date_dir); + } + if (chosen_fonts) + { + int tmp_fd = eina_file_mkstemp("/tmp/fonts_XXXXXX.conf", &fonts_conf_name); + dprintf(tmp_fd, + "\n\n\n" + "%s/%s\n\n", + fonts_dir, chosen_fonts); + close(tmp_fd); + + setenv("FONTCONFIG_FILE", fonts_conf_name, 1); + } + } efl_object_init(); evas_init(); diff --git a/src/bin/recorder.c b/src/bin/recorder.c index f6a1c99..d3a875e 100644 --- a/src/bin/recorder.c +++ b/src/bin/recorder.c @@ -362,6 +362,7 @@ static const Ecore_Getopt optdesc = { 1, { ECORE_GETOPT_STORE_STR('t', "test", "Name of the filename where to store the test."), + ECORE_GETOPT_STORE_STR('f', "fonts-dir", "Specify a directory of the fonts that should be used."), ECORE_GETOPT_COUNT('v', "verbose", "Turn verbose messages on."), ECORE_GETOPT_LICENSE('L', "license"), @@ -375,11 +376,13 @@ static const Ecore_Getopt optdesc = { int main(int argc, char **argv) { char *dest = NULL, *eq; + char *fonts_dir = NULL; int pret = 1, opt_args = 0; Eina_Bool want_quit = EINA_FALSE; Ecore_Getopt_Value values[] = { ECORE_GETOPT_VALUE_STR(dest), + ECORE_GETOPT_VALUE_STR(fonts_dir), ECORE_GETOPT_VALUE_INT(_verbose), ECORE_GETOPT_VALUE_BOOL(want_quit), @@ -462,6 +465,36 @@ int main(int argc, char **argv) efl_object_init(); evas_init(); + if (!_unit) + { + _unit = calloc(1, sizeof(*_unit)); + } + + if (fonts_dir) + { + Eina_Tmpstr *fonts_conf_name = NULL; + if (!ecore_file_exists(fonts_dir)) + { + fprintf(stderr, "Unable to find fonts directory %s\n", fonts_dir); + goto end; + } + Eina_List *dated_fonts = ecore_file_ls(fonts_dir); + char *date_dir; + _unit->fonts_path = strdup(eina_list_last_data_get(dated_fonts)); + EINA_LIST_FREE(dated_fonts, date_dir) free(date_dir); + if (_unit->fonts_path) + { + int tmp_fd = eina_file_mkstemp("/tmp/fonts_XXXXXX.conf", &fonts_conf_name); + dprintf(tmp_fd, + "\n\n\n" + "%s/%s\n\n", + fonts_dir, _unit->fonts_path); + close(tmp_fd); + + setenv("FONTCONFIG_FILE", fonts_conf_name, 1); + } + } + /* Replace the current command line to hide the Exactness part */ int len = argv[argc - 1] + strlen(argv[argc - 1]) - argv[opt_args]; memcpy(argv[0], argv[opt_args], len); @@ -481,11 +514,6 @@ int main(int argc, char **argv) if (!_shot_key) _shot_key = getenv("SHOT_KEY"); if (!_shot_key) _shot_key = SHOT_KEY_STR; - if (!_unit) - { - _unit = calloc(1, sizeof(*_unit)); - } - ecore_evas_callback_new_set(_my_evas_new); _last_timestamp = ecore_time_get() * 1000; pret = _prg_invoke(_prg_full_path_guess(argv[0]), argc - opt_args, argv); diff --git a/src/lib/Exactness.h b/src/lib/Exactness.h index 84c04b0..5392d04 100644 --- a/src/lib/Exactness.h +++ b/src/lib/Exactness.h @@ -192,6 +192,7 @@ typedef struct /* imgs not in EET */ Eina_List *imgs; /**< List of Exactness_Image */ Eina_List *objs; /**< List of Exactness_Objects */ + const char *fonts_path; /**< Path to the fonts to use, relative to the fonts dir given in parameter to the player/recorder */ int nb_shots; /**< The number of shots present in the unit */ } Exactness_Unit; diff --git a/src/lib/unit.c b/src/lib/unit.c index 8ef4d32..0977d86 100644 --- a/src/lib/unit.c +++ b/src/lib/unit.c @@ -243,6 +243,7 @@ _unit_desc_make(void) unit_d = eet_data_descriptor_stream_new(&eddc); EET_DATA_DESCRIPTOR_ADD_LIST(unit_d, Exactness_Unit, "actions", actions, action_d); EET_DATA_DESCRIPTOR_ADD_LIST(unit_d, Exactness_Unit, "objs", objs, objs_d); + EET_DATA_DESCRIPTOR_ADD_BASIC(unit_d, Exactness_Unit, "fonts_path", fonts_path, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC(unit_d, Exactness_Unit, "nb_shots", nb_shots, EET_T_UINT); }