From: Youngbok Shin Date: Fri, 21 Apr 2017 04:40:21 +0000 (+0900) Subject: edje: Add ellipsize feature and refactory fade_ellipsis, marquee features. X-Git-Tag: accepted/tizen/unified/20170711.181154~5 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F40%2F126340%2F42;p=platform%2Fupstream%2Fefl.git edje: Add ellipsize feature and refactory fade_ellipsis, marquee features. * example: description { text { ellipsize { mode: FADE_MARQUEE; // NONE(default), NORMAL, FADE, FADE_MARQUEE, MARQUEE align: END; // END(default), START, LEFT, RIGHT, LOCALE marquee { type: ROLL; // NORMAL(default), ROLL speed: 50; // pixel per sec. It is a scalable variable when its part is scalable. // duration: 4.0;// sec per loop. The speed will be changed according to text's length. loop: 3; loop_delay: 2.0; // sec. delay before starting each loop } } } } @tizen_fix Change-Id: Iaa1d5d29ed4c2ddfc071c407ca6b7425eb4da199 --- diff --git a/data/Makefile.am b/data/Makefile.am index c776c6f..b856e35 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -72,8 +72,7 @@ edjefiles_DATA = edje/include/edje.inc EXTRA_DIST += $(edjefiles_DATA) edjeimagesdir = $(datadir)/edje/images -edjeimages_DATA = edje/images/edje_default_left_fade_image.png \ - edje/images/edje_default_right_fade_image.png +edjeimages_DATA = edje/images/edje_default_fade_image.png EXTRA_DIST += $(edjeimages_DATA) mimedir = $(datadir)/mime/packages diff --git a/data/edje/images/edje_default_fade_image.png b/data/edje/images/edje_default_fade_image.png new file mode 100644 index 0000000..e2c889e Binary files /dev/null and b/data/edje/images/edje_default_fade_image.png differ diff --git a/data/edje/images/edje_default_left_fade_image.png b/data/edje/images/edje_default_left_fade_image.png deleted file mode 100644 index 4eea173..0000000 Binary files a/data/edje/images/edje_default_left_fade_image.png and /dev/null differ diff --git a/data/edje/images/edje_default_right_fade_image.png b/data/edje/images/edje_default_right_fade_image.png deleted file mode 100644 index a5a8ca9..0000000 Binary files a/data/edje/images/edje_default_right_fade_image.png and /dev/null differ diff --git a/src/bin/edje/edje_cc_handlers.c b/src/bin/edje/edje_cc_handlers.c index 510dc8e..1fc20d4 100644 --- a/src/bin/edje/edje_cc_handlers.c +++ b/src/bin/edje/edje_cc_handlers.c @@ -395,6 +395,14 @@ static void st_collections_group_parts_part_description_text_fade_ellipsis(void) static void st_collections_group_parts_part_description_text_ellipsize_mode(void); static void st_collections_group_parts_part_description_text_ellipsize_marquee_repeat_limit(void); // +/* TIZEN_ONLY(20170703): Add ellipsize feature and refactory fade_ellipsis, marquee features. */ +static void st_collections_group_parts_part_description_text_ellipsize_align(void); +static void st_collections_group_parts_part_description_text_ellipsize_marquee_type(void); +static void st_collections_group_parts_part_description_text_ellipsize_marquee_loop(void); +static void st_collections_group_parts_part_description_text_ellipsize_marquee_loop_delay(void); +static void st_collections_group_parts_part_description_text_ellipsize_marquee_speed(void); +static void st_collections_group_parts_part_description_text_ellipsize_marquee_duration(void); +/* END */ static void st_collections_group_parts_part_description_box_layout(void); static void st_collections_group_parts_part_description_box_align(void); static void st_collections_group_parts_part_description_box_padding(void); @@ -894,6 +902,14 @@ New_Statement_Handler statement_handlers[] = {"collections.group.parts.part.description.text.ellipsize.mode", st_collections_group_parts_part_description_text_ellipsize_mode}, {"collections.group.parts.part.description.text.ellipsize.marquee_repeat_limit", st_collections_group_parts_part_description_text_ellipsize_marquee_repeat_limit}, // + /* TIZEN_ONLY(20170703): Add ellipsize feature and refactory fade_ellipsis, marquee features. */ + {"collections.group.parts.part.description.text.ellipsize.align", st_collections_group_parts_part_description_text_ellipsize_align}, + {"collections.group.parts.part.description.text.ellipsize.marquee.type", st_collections_group_parts_part_description_text_ellipsize_marquee_type}, + {"collections.group.parts.part.description.text.ellipsize.marquee.loop", st_collections_group_parts_part_description_text_ellipsize_marquee_loop}, + {"collections.group.parts.part.description.text.ellipsize.marquee.loop_delay", st_collections_group_parts_part_description_text_ellipsize_marquee_loop_delay}, + {"collections.group.parts.part.description.text.ellipsize.marquee.speed", st_collections_group_parts_part_description_text_ellipsize_marquee_speed}, + {"collections.group.parts.part.description.text.ellipsize.marquee.duration", st_collections_group_parts_part_description_text_ellipsize_marquee_duration}, + /* END */ {"collections.group.parts.part.description.text.filter", st_collections_group_parts_part_description_filter_code}, /* dup */ /* TIZEN_ONLY(20160920): Add fade_ellipsis feature to TEXTBLOCK, TEXT part. */ {"collections.group.parts.part.description.text.fade_ellipsis", st_collections_group_parts_part_description_text_fade_ellipsis}, @@ -1301,6 +1317,9 @@ New_Object_Handler object_handlers[] = {"collections.group.parts.part.description.fill.size", NULL}, {"collections.group.parts.part.description.text", NULL}, {"collections.group.parts.part.description.text.ellipsize", NULL}, + /* TIZEN_ONLY(20170703): Add ellipsize feature and refactory fade_ellipsis, marquee features. */ + {"collections.group.parts.part.description.text.ellipsize.marquee", NULL}, + /* END */ {"collections.group.parts.part.description.text.fonts", NULL}, /* dup */ {"collections.group.parts.part.description.images", NULL}, /* dup */ {"collections.group.parts.part.description.images.set", ob_images_set}, /* dup */ @@ -10077,6 +10096,9 @@ st_collections_group_parts_part_description_text_ellipsize_mode(void) "FADE_START", EDJE_TEXT_ELLIPSIZE_MODE_FADE_START, "FADE_END", EDJE_TEXT_ELLIPSIZE_MODE_FADE_END, "MARQUEE", EDJE_TEXT_ELLIPSIZE_MODE_MARQUEE, + "NORMAL", EDJE_TEXT_ELLIPSIZE_MODE_NORMAL, + "FADE", EDJE_TEXT_ELLIPSIZE_MODE_FADE, + "FADE_MARQUEE", EDJE_TEXT_ELLIPSIZE_MODE_FADE_MARQUEE, NULL); } @@ -10099,6 +10121,140 @@ st_collections_group_parts_part_description_text_ellipsize_marquee_repeat_limit( ed->text.ellipsize.marquee_repeat_limit = parse_int_range(0, -1, 0x7fffffff); } + +/* TIZEN_ONLY(20170703): Add ellipsize feature and refactory fade_ellipsis, marquee features. */ +static void +st_collections_group_parts_part_description_text_ellipsize_align(void) +{ + Edje_Part_Description_Text *ed; + + check_arg_count(1); + + if ((current_part->type != EDJE_PART_TYPE_TEXT) && + (current_part->type != EDJE_PART_TYPE_TEXTBLOCK)) + { + ERR("parse error %s:%i. text attributes in non-TEXT part.", + file_in, line - 1); + exit(-1); + } + + ed = (Edje_Part_Description_Text*) current_desc; + + ed->text.ellipsize.align = parse_enum(0, + "END", EDJE_TEXT_ELLIPSIZE_ALIGN_END, + "START", EDJE_TEXT_ELLIPSIZE_ALIGN_START, + "RIGHT", EDJE_TEXT_ELLIPSIZE_ALIGN_RIGHT, + "LEFT", EDJE_TEXT_ELLIPSIZE_ALIGN_LEFT, + "LOCALE", EDJE_TEXT_ELLIPSIZE_ALIGN_LOCALE, + NULL); +} + +static void +st_collections_group_parts_part_description_text_ellipsize_marquee_type(void) +{ + Edje_Part_Description_Text *ed; + + check_arg_count(1); + + if ((current_part->type != EDJE_PART_TYPE_TEXT) && + (current_part->type != EDJE_PART_TYPE_TEXTBLOCK)) + { + ERR("parse error %s:%i. text attributes in non-TEXT part.", + file_in, line - 1); + exit(-1); + } + + ed = (Edje_Part_Description_Text*) current_desc; + + ed->text.ellipsize.marquee.type = parse_enum(0, + "DEFAULT", EDJE_TEXT_ELLIPSIZE_MARQUEE_TYPE_DEFAULT, + "ROLL", EDJE_TEXT_ELLIPSIZE_MARQUEE_TYPE_ROLL, + NULL); +} + +static void +st_collections_group_parts_part_description_text_ellipsize_marquee_loop(void) +{ + Edje_Part_Description_Text *ed; + + check_arg_count(1); + + if ((current_part->type != EDJE_PART_TYPE_TEXT) && + (current_part->type != EDJE_PART_TYPE_TEXTBLOCK)) + { + ERR("parse error %s:%i. text attributes in non-TEXT part.", + file_in, line - 1); + exit(-1); + } + + ed = (Edje_Part_Description_Text*) current_desc; + + ed->text.ellipsize.marquee_repeat_limit = parse_int_range(0, -1, 0x7fffffff); +} + +static void +st_collections_group_parts_part_description_text_ellipsize_marquee_loop_delay(void) +{ + Edje_Part_Description_Text *ed; + + check_arg_count(1); + + if ((current_part->type != EDJE_PART_TYPE_TEXT) && + (current_part->type != EDJE_PART_TYPE_TEXTBLOCK)) + { + ERR("parse error %s:%i. text attributes in non-TEXT part.", + file_in, line - 1); + exit(-1); + } + + ed = (Edje_Part_Description_Text*) current_desc; + + ed->text.ellipsize.marquee.loop_delay = parse_float(0); +} + +static void +st_collections_group_parts_part_description_text_ellipsize_marquee_speed(void) +{ + Edje_Part_Description_Text *ed; + + check_arg_count(1); + + if ((current_part->type != EDJE_PART_TYPE_TEXT) && + (current_part->type != EDJE_PART_TYPE_TEXTBLOCK)) + { + ERR("parse error %s:%i. text attributes in non-TEXT part.", + file_in, line - 1); + exit(-1); + } + + ed = (Edje_Part_Description_Text*) current_desc; + + ed->text.ellipsize.marquee.speed = parse_float(0); + ed->text.ellipsize.marquee.duration = 0.0; +} + +static void +st_collections_group_parts_part_description_text_ellipsize_marquee_duration(void) +{ + Edje_Part_Description_Text *ed; + + check_arg_count(1); + + if ((current_part->type != EDJE_PART_TYPE_TEXT) && + (current_part->type != EDJE_PART_TYPE_TEXTBLOCK)) + { + ERR("parse error %s:%i. text attributes in non-TEXT part.", + file_in, line - 1); + exit(-1); + } + + ed = (Edje_Part_Description_Text*) current_desc; + + ed->text.ellipsize.marquee.duration = parse_float(0); + ed->text.ellipsize.marquee.speed = 0.0; +} +/* END */ + // /** @edcsubsection{collections_group_parts_description_box, * Group.Parts.Part.Description.Box} */ diff --git a/src/lib/edje/Edje_Common.h b/src/lib/edje/Edje_Common.h index 47da82c..76034a5 100644 --- a/src/lib/edje/Edje_Common.h +++ b/src/lib/edje/Edje_Common.h @@ -1468,17 +1468,39 @@ typedef enum _Edje_Text_Effect //TIZEN_ONLY(20160923): introduction of text marquee typedef enum _Edje_Text_Ellipsize_Mode { - EDJE_TEXT_ELLIPSIZE_MODE_NONE = 0, - EDJE_TEXT_ELLIPSIZE_MODE_START = 1, - EDJE_TEXT_ELLIPSIZE_MODE_MIDDLE = 2, - EDJE_TEXT_ELLIPSIZE_MODE_END = 3, - EDJE_TEXT_ELLIPSIZE_MODE_FADE_START = 4, - EDJE_TEXT_ELLIPSIZE_MODE_FADE_END = 5, - EDJE_TEXT_ELLIPSIZE_MODE_MARQUEE = 6, - EDJE_TEXT_ELLIPSIZE_MODE_LAST = 7 + EDJE_TEXT_ELLIPSIZE_MODE_NONE = 0, + EDJE_TEXT_ELLIPSIZE_MODE_START = 1, /* Deprecated */ + EDJE_TEXT_ELLIPSIZE_MODE_MIDDLE = 2, /* Deprecated */ + EDJE_TEXT_ELLIPSIZE_MODE_END = 3, /* Deprecated */ + EDJE_TEXT_ELLIPSIZE_MODE_FADE_START = 4, /* Deprecated */ + EDJE_TEXT_ELLIPSIZE_MODE_FADE_END = 5, /* Deprecated */ + EDJE_TEXT_ELLIPSIZE_MODE_MARQUEE = 6, + EDJE_TEXT_ELLIPSIZE_MODE_NORMAL = 7, + EDJE_TEXT_ELLIPSIZE_MODE_FADE = 8, + EDJE_TEXT_ELLIPSIZE_MODE_FADE_MARQUEE = 9, + EDJE_TEXT_ELLIPSIZE_MODE_LAST = 10 } Edje_Text_Ellipsize_Mode; // +/* TIZEN_ONLY(20170703): Add ellipsize feature and refactory fade_ellipsis, marquee features. */ +typedef enum _Edje_Text_Ellipsize_Align +{ + EDJE_TEXT_ELLIPSIZE_ALIGN_END = 0, + EDJE_TEXT_ELLIPSIZE_ALIGN_START = 1, + EDJE_TEXT_ELLIPSIZE_ALIGN_RIGHT = 2, + EDJE_TEXT_ELLIPSIZE_ALIGN_LEFT = 3, + EDJE_TEXT_ELLIPSIZE_ALIGN_LOCALE = 4, + EDJE_TEXT_ELLIPSIZE_ALIGN_LAST = 5 +} Edje_Text_Ellipsize_Align; + +typedef enum _Edje_Text_Ellipsize_Marquee_Type +{ + EDJE_TEXT_ELLIPSIZE_MARQUEE_TYPE_DEFAULT = 0, + EDJE_TEXT_ELLIPSIZE_MARQUEE_TYPE_ROLL = 1, + EDJE_TEXT_ELLIPSIZE_MARQUEE_TYPE_LAST = 2 +} Edje_Text_Ellipsize_Marquee_Type; +/* END */ + /** * @typedef (*Edje_Text_Change_Cb) * diff --git a/src/lib/edje/edje_calc.c b/src/lib/edje/edje_calc.c index 6837d13..0087ebd 100644 --- a/src/lib/edje/edje_calc.c +++ b/src/lib/edje/edje_calc.c @@ -15,6 +15,11 @@ static void _edje_part_recalc_single(Edje *ed, Edje_Rea Edje_Calc_Params *params, Evas_Coord mmw, Evas_Coord mmh, FLOAT_T pos); +/* TIZEN_ONLY(20170703): Add ellipsize.marquee, ellipsize.fade features */ +static void _edje_text_ellipsize_apply(Edje *ed, Edje_Real_Part *ep, + Edje_Calc_Params *pf, + Edje_Part_Description_Text *chosen_desc); +/* END */ #define EINA_COW_CALC_PHYSICS_BEGIN(Calc, Write) \ EINA_COW_WRITE_BEGIN(_edje_calc_params_physics_cow, Calc->physics, Edje_Calc_Params_Physics, Write) @@ -721,10 +726,6 @@ _edje_part_description_apply(Edje *ed, Edje_Real_Part *ep, const char *d1, doubl Edje_Part_Description_Common *last_desc; Eina_Bool change_w, change_h; Edje_Part_Description_Image *epdi; - //TIZEN_ONLY(20160923): introduction of text marquee - Edje_Part_Description_Text *last_desc_text; - Edje_Part_Description_Text *desc_text; - // if (!d1) d1 = "default"; @@ -836,49 +837,6 @@ _edje_part_description_apply(Edje *ed, Edje_Real_Part *ep, const char *d1, doubl edje_object_mirrored_set(ep->typedata.swallow->swallowed_object, edje_object_mirrored_get(ed->obj)); } - //TIZEN_ONLY(20160923): introduction of text marquee - /* reset margquee_repeat_count */ - else if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK || - ep->part->type == EDJE_PART_TYPE_TEXT) - { - if (last_desc) - { - last_desc_text = (Edje_Part_Description_Text *)last_desc; - last_desc_text->text.ellipsize.marquee_repeat_count = 0; - - desc_text = (Edje_Part_Description_Text *)ep->chosen_description; - if (ep->part->type == EDJE_PART_TYPE_TEXT) - { - if (desc_text->text.ellipsize.mode == EDJE_TEXT_ELLIPSIZE_MODE_MARQUEE) - { - desc_text->text.ellipsis = -1; - evas_object_text_ellipsis_set(ep->object, -1.0); - } - else if ((last_desc_text->text.ellipsize.mode == EDJE_TEXT_ELLIPSIZE_MODE_MARQUEE) && - (last_desc_text->text.ellipsize.mode != desc_text->text.ellipsize.mode)) - { - //FIXME: Need to enhancement using other ellipsize modes - evas_object_text_ellipsis_set(ep->object, desc_text->text.ellipsis); - evas_object_resize(ep->object, ep->w, ep->h); - } - } - else if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) - { - if (desc_text->text.ellipsize.mode == EDJE_TEXT_ELLIPSIZE_MODE_MARQUEE) - { - evas_object_textblock_ellipsis_disabled_set(ep->object, EINA_TRUE); - } - else if (last_desc_text->text.ellipsize.mode == EDJE_TEXT_ELLIPSIZE_MODE_MARQUEE && - last_desc_text->text.ellipsize.mode != desc_text->text.ellipsize.mode) - { - //FIXME: Need to enhancement using other ellipsize modes - Eina_Bool ellipsis = evas_object_textblock_ellipsis_disabled_get(ep->object); - evas_object_textblock_ellipsis_disabled_set(ep->object, ellipsis); - } - } - } - } - // } ed->recalc_hints = EINA_TRUE; @@ -4137,1861 +4095,2452 @@ _circular_dependency_find(Edje *ed, Edje_Real_Part *ep, Edje_Real_Part *cep, Ein return EINA_FALSE; } -/* - * TIZEN_ONLY(20160920): Add fade_ellipsis feature to TEXTBLOCK, TEXT part. - */ -#define EDJE_DEFAULT_LEFT_FADE_IMAGE "edje_default_left_fade_image.png" -#define EDJE_DEFAULT_RIGHT_FADE_IMAGE "edje_default_right_fade_image.png" - -static void -_edje_real_part_text_fade_image_set(Edje *ed EINA_UNUSED, Edje_Real_Part *ep, double align) +void +_edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int flags, Edje_Calc_Params *state) { - Evas_Object *fade_obj = fade_obj = ep->typedata.text->fade.object; - char buf[1024]; - - if (align == 1.0) - snprintf(buf, sizeof(buf), "/usr/share/edje/images/%s", EDJE_DEFAULT_RIGHT_FADE_IMAGE); - else - snprintf(buf, sizeof(buf), "/usr/share/edje/images/%s", EDJE_DEFAULT_LEFT_FADE_IMAGE); - - evas_object_image_file_set(fade_obj, buf, NULL); +#ifdef EDJE_CALC_CACHE + Eina_Bool proxy_invalidate = EINA_FALSE; + int state1 = -1; + int state2 = -1; + int statec = -1; + int statet = -1; +#else + Edje_Calc_Params lp1, lp2; +#endif + int statec1 = -1; + int statec2 = -1; + int statel1 = -1; + int statel2 = -1; + int statep1 = -1; + int statep2 = -1; + int statecl = -1; + Edje_Real_Part *center[2] = { NULL, NULL }; + Edje_Real_Part *light[2] = { NULL, NULL }; + Edje_Real_Part *persp[2] = { NULL, NULL }; + Edje_Real_Part *rp1[4] = { NULL, NULL, NULL, NULL }; + Edje_Real_Part *rp2[4] = { NULL, NULL, NULL, NULL }; + Edje_Real_Part *clip1 = NULL, *clip2 = NULL; + Edje_Calc_Params *p1, *pf; + Edje_Part_Description_Common *chosen_desc; + Edje_Real_Part *confine_to = NULL; + Edje_Real_Part *threshold = NULL; + FLOAT_T pos = ZERO, pos2; + Edje_Calc_Params lp3; + Evas_Coord mmw = 0, mmh = 0; + Eina_Bool map_colors_free = EINA_FALSE; - if (evas_object_image_load_error_get(fade_obj) != EVAS_LOAD_ERROR_NONE) + /* GRADIENT ARE GONE, WE MUST IGNORE IT FROM OLD FILE. */ + if (ep->part->type == EDJE_PART_TYPE_GRADIENT) { - ERR("Error loading fade image from file \"%s\".", buf); - - switch (evas_object_image_load_error_get(fade_obj)) - { - case EVAS_LOAD_ERROR_GENERIC: - ERR("Error type: EVAS_LOAD_ERROR_GENERIC"); - break; - case EVAS_LOAD_ERROR_DOES_NOT_EXIST: - ERR("Error type: EVAS_LOAD_ERROR_DOES_NOT_EXIST"); - break; - case EVAS_LOAD_ERROR_PERMISSION_DENIED: - ERR("Error type: EVAS_LOAD_ERROR_PERMISSION_DENIED"); - break; - case EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED: - ERR("Error type: EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED"); - break; - case EVAS_LOAD_ERROR_CORRUPT_FILE: - ERR("Error type: EVAS_LOAD_ERROR_CORRUPT_FILE"); - break; - case EVAS_LOAD_ERROR_UNKNOWN_FORMAT: - ERR("Error type: EVAS_LOAD_ERROR_UNKNOWN_FORMAT"); - break; - default: - ERR("Error type: ???"); - break; - } + ERR("GRADIENT spotted during recalc ! That should never happen ! Send your edje file to devel ml."); + return; } -} - -static void -_real_part_object_move_cb_for_fade_object(void *data, - Evas *e EINA_UNUSED, - Evas_Object *obj EINA_UNUSED, - void *event_info EINA_UNUSED) -{ - Edje_Real_Part *ep = (Edje_Real_Part *)data; - if (ep->typedata.text && ep->typedata.text->fade.object) + if ((ep->calculated & FLAG_XY) == FLAG_XY && !state) { - Evas_Coord x, y; - - evas_object_geometry_get(ep->object, &x, &y, NULL, NULL); - evas_object_move(ep->typedata.text->fade.object, x, y); + return; } -} - -/* TIZEN_ONLY(20170322): fix crash issue when Edje tries to clean up fade object */ -void -_edje_fade_ellipsis_remove(Edje_Real_Part *ep) -{ - if (!ep || !ep->typedata.text) return; - if (!ep->typedata.text->fade.object) return; - - if (ep->object) - evas_object_event_callback_del_full(ep->object, EVAS_CALLBACK_MOVE, _real_part_object_move_cb_for_fade_object, ep); - - evas_object_del(ep->typedata.text->fade.object); - ep->typedata.text->fade.object = NULL; -} -/* END */ - -static void -_edje_fade_ellipsis_apply(Edje *ed, Edje_Real_Part *ep, - Edje_Calc_Params *pf, - Edje_Part_Description_Text *chosen_desc) -{ - // DEBUGGING FLAG -#define FADE_CLIP 1 -#define FADE_IMAGE 1 -#define FADE_IMAGE_BORDER 1 - // - Evas_Coord tw, th; - Evas_Coord lx, ly, lw, lh; - Evas_Coord iw; - Evas_Coord clipper_h; - Evas_BiDi_Direction dir; - Evas_Object *clipper; - Evas_Object *fade_obj; - double align; - Eina_Bool ellipsis_status; + if (ep->calculating & flags) + { +#if 1 + const char *axes = "NONE", *faxes = "NONE"; - if ((ep->part->type != EDJE_PART_TYPE_TEXTBLOCK) && - (ep->part->type != EDJE_PART_TYPE_TEXT)) - return; + if ((ep->calculating & FLAG_X) && + (ep->calculating & FLAG_Y)) + axes = "XY"; + else if ((ep->calculating & FLAG_X)) + axes = "X"; + else if ((ep->calculating & FLAG_Y)) + axes = "Y"; - if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) - ellipsis_status = evas_object_textblock_ellipsis_status_get(ep->object); - else - ellipsis_status = evas_object_text_ellipsis_status_get(ep->object); + if ((flags & FLAG_X) && + (flags & FLAG_Y)) + faxes = "XY"; + else if ((flags & FLAG_X)) + faxes = "X"; + else if ((flags & FLAG_Y)) + faxes = "Y"; + ERR("Circular dependency when calculating part \"%s\". " + "Already calculating %s [%02x] axes. " + "Need to calculate %s [%02x] axes", + ep->part->name, + axes, ep->calculating, + faxes, flags); - // Hide fade image if fade_ellipsis option is off or object size is zero. - if ((chosen_desc->text.fade_ellipsis == 0.0) || - (pf->final.w == 0) || (pf->final.h == 0)) - { - if (ep->typedata.text->fade.object) + Eina_List *clist = NULL; + Eina_List *l = NULL; + char *part_name; + char depends_path[PATH_MAX] = ""; + _circular_dependency_find(ed, ep, NULL, &clist); + strncat(depends_path, ep->part->name, + sizeof(depends_path) - strlen(depends_path) - 1); + EINA_LIST_FOREACH(clist, l, part_name) { -#if FADE_CLIP - clipper = evas_object_clip_get(ep->typedata.text->fade.object); - - if (clipper) evas_object_clip_set(ep->object, clipper); -#endif - evas_object_hide(ep->typedata.text->fade.object); + strncat(depends_path, " -> ", + sizeof(depends_path) - strlen(depends_path) - 1); + strncat(depends_path, part_name, + sizeof(depends_path) - strlen(depends_path) - 1); } - + ERR("Circular dependency in the group '%s' : %s", ed->group, depends_path); + eina_list_free(clist); +#endif return; } - if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) - { - evas_object_textblock_size_formatted_get(ep->object, &tw, &th); - } - else + if (ep->part->type == EDJE_PART_TYPE_GROUP && + ((ep->type == EDJE_RP_TYPE_SWALLOW) && + (ep->typedata.swallow)) && + ep->typedata.swallow->swallowed_object) { - tw = evas_object_text_horiz_advance_get(ep->object), - th = evas_object_text_vert_advance_get(ep->object); - } + edje_object_scale_set(ep->typedata.swallow->swallowed_object, TO_DOUBLE(ed->scale)); - // Hide fade image if text is not exceed the given area. - if ((tw <= pf->final.w) && (th <= pf->final.h) && !ellipsis_status) - { - if (ep->typedata.text->fade.object) + if (ep->description_pos > FROM_DOUBLE(0.5) && ep->param2) { -#if FADE_CLIP - clipper = evas_object_clip_get(ep->typedata.text->fade.object); - - if (clipper) evas_object_clip_set(ep->object, clipper); -#endif - evas_object_hide(ep->typedata.text->fade.object); + edje_object_update_hints_set(ep->typedata.swallow->swallowed_object, ep->param2->description->min.limit); + } + else + { + edje_object_update_hints_set(ep->typedata.swallow->swallowed_object, ep->param1.description->min.limit); } + if (edje_object_update_hints_get(ep->typedata.swallow->swallowed_object)) + { + Edje *ted; - return; + ted = _edje_fetch(ep->typedata.swallow->swallowed_object); + _edje_recalc_do(ted); + } } - - // Make and show fade image. - if (!ep->typedata.text->fade.object) + if (ep->part->type == EDJE_PART_TYPE_GROUP && + ((ep->type == EDJE_RP_TYPE_SWALLOW) && + (ep->typedata.swallow)) && + ep->typedata.swallow->swallowed_object) { -#if FADE_IMAGE - ep->typedata.text->fade.object = evas_object_image_add(evas_object_evas_get(ep->object)); -#else - ep->typedata.text->fade.object = evas_object_rectangle_add(evas_object_evas_get(ep->object)); - evas_object_color_set(ep->typedata.text->fade.object, 200, 0, 0, 200); -#endif - evas_object_pass_events_set(ep->typedata.text->fade.object, 1); - evas_object_pointer_mode_set(ep->typedata.text->fade.object, EVAS_OBJECT_POINTER_MODE_NOGRAB); - evas_object_smart_member_add(ep->typedata.text->fade.object, ed->obj); - evas_object_event_callback_add(ep->object, EVAS_CALLBACK_MOVE, _real_part_object_move_cb_for_fade_object, ep); + Edje_Size *min = NULL, *max = NULL; - ep->typedata.text->fade.align = -1; + if (ep->chosen_description) + { + min = &ep->chosen_description->min; + max = &ep->chosen_description->max; + } + if (min && max && (min->w == max->w) && (min->h == max->h) && (min->w > 0) && (min->h > 0)) + mmw = min->w, mmh = min->h; + else + edje_object_size_min_calc(ep->typedata.swallow->swallowed_object, + &mmw, &mmh); } - fade_obj = ep->typedata.text->fade.object; +#ifdef EDJE_CALC_CACHE + if (ep->state == ed->state && !state) + return; +#endif - if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) + if (ep->param1.description) { - Evas_Textblock_Cursor *cur; - - cur = evas_object_textblock_cursor_new(ep->object); - evas_textblock_cursor_line_coord_set(cur, pf->final.h); - evas_textblock_cursor_line_geometry_get(cur, &lx, &ly, &lw, &lh); - evas_textblock_cursor_geometry_get(cur, - NULL, NULL, NULL, NULL, &dir, - EVAS_TEXTBLOCK_CURSOR_BEFORE); - - if (ly + lh > pf->final.h) + if (ep->param1.description->rel1.id_x >= 0) + rp1[Rel1X] = ed->table_parts[ep->param1.description->rel1.id_x]; + if (ep->param1.description->rel2.id_x >= 0) + rp1[Rel2X] = ed->table_parts[ep->param1.description->rel2.id_x]; + if (ep->param1.description->rel1.id_y >= 0) + rp1[Rel1Y] = ed->table_parts[ep->param1.description->rel1.id_y]; + if (ep->param1.description->rel2.id_y >= 0) + rp1[Rel2Y] = ed->table_parts[ep->param1.description->rel2.id_y]; + if (ep->param1.description->clip_to_id >= 0) { - evas_textblock_cursor_line_coord_set(cur, pf->final.h - lh); - evas_textblock_cursor_line_geometry_get(cur, &lx, &ly, &lw, &lh); - evas_textblock_cursor_geometry_get(cur, - NULL, NULL, NULL, NULL, &dir, - EVAS_TEXTBLOCK_CURSOR_BEFORE); + clip1 = ed->table_parts[ep->param1.description->clip_to_id % ed->table_parts_size]; + ed->has_state_clip = EINA_TRUE; } - - evas_textblock_cursor_free(cur); } - else + if (ep->param2) { - // FIXME: I don't know how should I handle this in evas text. - lx = ly = 0; - dir = evas_object_text_direction_get(ep->object); - evas_object_geometry_get(ep->object, NULL, NULL, &lw, &lh); + if (ep->param2->description->rel1.id_x >= 0) + rp2[Rel1X] = ed->table_parts[ep->param2->description->rel1.id_x]; + if (ep->param2->description->rel2.id_x >= 0) + rp2[Rel2X] = ed->table_parts[ep->param2->description->rel2.id_x]; + if (ep->param2->description->rel1.id_y >= 0) + rp2[Rel1Y] = ed->table_parts[ep->param2->description->rel1.id_y]; + if (ep->param2->description->rel2.id_y >= 0) + rp2[Rel2Y] = ed->table_parts[ep->param2->description->rel2.id_y]; + if (ep->param2->description->clip_to_id >= 0) + { + clip2 = ed->table_parts[ep->param2->description->clip_to_id % ed->table_parts_size]; + ed->has_state_clip = EINA_TRUE; + } } - if (dir != EVAS_BIDI_DIRECTION_RTL) - align = chosen_desc->text.fade_ellipsis - 1.0; - else - align = 1.0 - (chosen_desc->text.fade_ellipsis - 1.0); - -#if FADE_IMAGE - if (ep->typedata.text->fade.align != align) + if (flags & FLAG_X) { - // Load image from edje. - _edje_real_part_text_fade_image_set(ed, ep, align); - - // Default fade image is for LTR. - // Assume 10% of fadeout image's left side is opaque. (alpha = 255) - if (align == 1.0) + ep->calculating |= flags & FLAG_X; + if (rp1[Rel1X]) { -#if FADE_IMAGE_BORDER - evas_object_image_size_get(fade_obj, &iw, NULL); - evas_object_image_border_set(fade_obj, 0, iw - (iw * 0.1), 0, 0); - evas_object_image_border_scale_set(fade_obj, 1.0); - evas_object_image_border_center_fill_set(fade_obj, EVAS_BORDER_FILL_DEFAULT); + _edje_part_recalc(ed, rp1[Rel1X], FLAG_X, NULL); +#ifdef EDJE_CALC_CACHE + state1 = rp1[Rel1X]->state; #endif } - else + if (rp1[Rel2X]) { -#if FADE_IMAGE_BORDER - evas_object_image_size_get(fade_obj, &iw, NULL); - evas_object_image_border_set(fade_obj, iw - (iw * 0.1), 0, 0, 0); - evas_object_image_border_scale_set(fade_obj, 1.0); - evas_object_image_border_center_fill_set(fade_obj, EVAS_BORDER_FILL_DEFAULT); + _edje_part_recalc(ed, rp1[Rel2X], FLAG_X, NULL); +#ifdef EDJE_CALC_CACHE + if (state1 < rp1[Rel2X]->state) + state1 = rp1[Rel2X]->state; #endif } - - ep->typedata.text->fade.align = (float)align; - } -#endif - - // This will prevent to show horizontally cut off text in multiline textblock. - if (ly != 0) - clipper_h = ly + lh; - else - clipper_h = pf->final.h; - -#if FADE_IMAGE - evas_object_image_fill_set(fade_obj, 0, 0, pf->final.w, clipper_h); -#endif - evas_object_resize(fade_obj, pf->final.w, clipper_h); - evas_object_move(fade_obj, ed->x + pf->final.x, ed->y + pf->final.y); - -#if FADE_CLIP - clipper = evas_object_clip_get(ep->object); - - if (clipper != fade_obj) - { - evas_object_clip_set(fade_obj, clipper); - evas_object_clip_set(ep->object, fade_obj); - evas_object_show(fade_obj); - } + if (ep->param2) + { + if (rp2[Rel1X]) + { + _edje_part_recalc(ed, rp2[Rel1X], FLAG_X, NULL); +#ifdef EDJE_CALC_CACHE + state2 = rp2[Rel1X]->state; #endif -} -/* END */ -//TIZEN_ONLY(20160923): introduction of text marquee -#define MARQUEE_CLIP 1 -static void -_text_marquee_clipper_update(Edje_Real_Part *ep, int x, int y, int w, int h) -{ - Evas_Object *prev_clipper; - - if (!ep->text_marquee_clipper) - { - ep->text_marquee_clipper = evas_object_rectangle_add(evas_object_evas_get(ep->object)); - evas_object_show(ep->text_marquee_clipper); -#if MARQUEE_CLIP - evas_object_color_set(ep->text_marquee_clipper, 255, 255, 255, 255); - prev_clipper = evas_object_clip_get(ep->object); - if (prev_clipper) evas_object_clip_set(ep->text_marquee_clipper, prev_clipper); - evas_object_clip_set(ep->object, ep->text_marquee_clipper); -#else - /* ambient red color rectangle for debugging clipper object */ - evas_object_color_set(ep->text_marquee_clipper, 150, 0, 0, 150); + } + if (rp2[Rel2X]) + { + _edje_part_recalc(ed, rp2[Rel2X], FLAG_X, NULL); +#ifdef EDJE_CALC_CACHE + if (state2 < rp2[Rel2X]->state) + state2 = rp2[Rel2X]->state; #endif + } + } } - else + if (flags & FLAG_Y) { -#if MARQUEE_CLIP - prev_clipper = evas_object_clip_get(ep->object); - - /* reset marquee clipper changed in _edje_part_recalc */ - if (prev_clipper && prev_clipper != ep->text_marquee_clipper) + ep->calculating |= flags & FLAG_Y; + if (rp1[Rel1Y]) + { + _edje_part_recalc(ed, rp1[Rel1Y], FLAG_Y, NULL); +#ifdef EDJE_CALC_CACHE + if (state1 < rp1[Rel1Y]->state) + state1 = rp1[Rel1Y]->state; +#endif + } + if (rp1[Rel2Y]) { - evas_object_clip_set(ep->text_marquee_clipper, prev_clipper); - evas_object_clip_set(ep->object, ep->text_marquee_clipper); + _edje_part_recalc(ed, rp1[Rel2Y], FLAG_Y, NULL); +#ifdef EDJE_CALC_CACHE + if (state1 < rp1[Rel2Y]->state) + state1 = rp1[Rel2Y]->state; +#endif } + if (ep->param2) + { + if (rp2[Rel1Y]) + { + _edje_part_recalc(ed, rp2[Rel1Y], FLAG_Y, NULL); +#ifdef EDJE_CALC_CACHE + if (state2 < rp2[Rel1Y]->state) + state2 = rp2[Rel1Y]->state; +#endif + } + if (rp2[Rel2Y]) + { + _edje_part_recalc(ed, rp2[Rel2Y], FLAG_Y, NULL); +#ifdef EDJE_CALC_CACHE + if (state2 < rp2[Rel2Y]->state) + state2 = rp2[Rel2Y]->state; #endif + } + } } - - evas_object_move(ep->text_marquee_clipper, x, y); - evas_object_resize(ep->text_marquee_clipper, w, h); -} - -static void -_text_marquee_clipper_del(Edje_Real_Part *ep) -{ - Evas_Object *prev_clipper; - - if (!ep->text_marquee_clipper) return; - -#if MARQUEE_CLIP - prev_clipper = evas_object_clip_get(ep->object); - - /* reset marquee clipper changed in _edje_part_recalc */ - if (prev_clipper && prev_clipper != ep->text_marquee_clipper) + if (clip1) { - evas_object_clip_unset(ep->text_marquee_clipper); - evas_object_del(ep->text_marquee_clipper); - ep->text_marquee_clipper = NULL; - - evas_object_clip_set(ep->object, prev_clipper); + _edje_part_recalc(ed, clip1, flags, NULL); + statecl = clip1->state; } - else + if (clip2) { - prev_clipper = evas_object_clip_get(ep->text_marquee_clipper); - evas_object_clip_unset(ep->text_marquee_clipper); - evas_object_del(ep->text_marquee_clipper); - ep->text_marquee_clipper = NULL; - - if (prev_clipper) evas_object_clip_set(ep->object, prev_clipper); + _edje_part_recalc(ed, clip2, flags, NULL); + if (statecl < clip2->state) + statecl = clip2->state; } -#else - evas_object_del(ep->text_marquee_clipper); - ep->text_marquee_clipper = NULL; + if (ep->drag) + { + if (ep->drag->confine_to) + { + confine_to = ep->drag->confine_to; + _edje_part_recalc(ed, confine_to, flags, NULL); +#ifdef EDJE_CALC_CACHE + statec = confine_to->state; #endif -} - -static Eina_Bool -_text_object_marquee_animator(void *data) -{ - double cur_time; - double elapsed_time; - double default_time = 0.025; /* moving 1 px for 0.025 sec makes 40 px/sec */ - Evas_Coord move_length = 0; - Edje_Real_Part *ep; - Edje_Part_Description_Text *chosen_desc; - Evas_Coord_Rectangle text_cur_area; - Evas_Coord_Rectangle clipper_area; - - ep = data; - chosen_desc = (Edje_Part_Description_Text *)ep->chosen_description; - - evas_object_geometry_get(ep->object, &text_cur_area.x, &text_cur_area.y, - &text_cur_area.w, &text_cur_area.h); + } + if (ep->drag->threshold) + { + threshold = ep->drag->threshold; + // We shall not recalculate the threshold position as + // we use it's previous position to assert the threshold + // the one before moving take action. +#ifdef EDJE_CALC_CACHE + statet = threshold->state; +#endif + } + } + // if (ep->text.source) _edje_part_recalc(ed, ep->text.source, flags); + // if (ep->text.text_source) _edje_part_recalc(ed, ep->text.text_source, flags); - if (text_cur_area.w <= ep->w) + /* actually calculate now */ + chosen_desc = ep->chosen_description; + if (!chosen_desc) { - /* text marquee will not work */ - if (ep->text_marquee_clipper) - _text_marquee_clipper_del(ep); - - ep->text_marquee_animator = NULL; - return ECORE_CALLBACK_CANCEL; + ep->calculating = FLAG_NONE; + ep->calculated |= flags; + return; } - evas_object_geometry_get(ep->text_marquee_clipper, &clipper_area.x, &clipper_area.y, - &clipper_area.w, &clipper_area.h); - _text_marquee_clipper_update(ep, clipper_area.x, clipper_area.y, - clipper_area.w, clipper_area.h); + pos = ep->description_pos; - cur_time = ecore_time_get(); - elapsed_time = cur_time - ep->text_marquee_prev_time; - default_time = default_time / evas_object_scale_get(ep->object); - while (elapsed_time > default_time) - { - elapsed_time -= default_time; - move_length++; - } - ep->text_marquee_prev_time = cur_time - elapsed_time; - if (ep->text_marquee_to_left) + if ((ep->part->type == EDJE_PART_TYPE_PROXY) && chosen_desc->visible) { - if (text_cur_area.x + text_cur_area.w < clipper_area.x) - { - if (chosen_desc->text.ellipsize.marquee_repeat_limit != -1) - chosen_desc->text.ellipsize.marquee_repeat_count++; + int part_id = -1; - text_cur_area.x = clipper_area.x + clipper_area.w; - } + if (ep->param2 && (pos >= FROM_DOUBLE(0.5))) + part_id = ((Edje_Part_Description_Proxy *)ep->param2->description)->proxy.id; else - { - text_cur_area.x -= move_length; - } + part_id = ((Edje_Part_Description_Proxy *)chosen_desc)->proxy.id; + +#ifdef EDJE_CALC_CACHE + Edje_Real_Part *pp; + pp = _edje_real_part_state_get(ed, ep, flags, part_id, NULL); + if (pp && pp->invalidate) proxy_invalidate = EINA_TRUE; +#else + _edje_real_part_state_get(ed, ep, flags, part_id, NULL); +#endif } - else + + /* Recalc if needed the map center && light source */ + if (ep->param1.description->map.on) { - if (text_cur_area.x > clipper_area.x + clipper_area.w) - { - if (chosen_desc->text.ellipsize.marquee_repeat_limit != -1) - chosen_desc->text.ellipsize.marquee_repeat_count++; + center[0] = _edje_real_part_state_get(ed, ep, flags, ep->param1.description->map.rot.id_center, &statec1); + light[0] = _edje_real_part_state_get(ed, ep, flags, ep->param1.description->map.id_light, &statel1); - text_cur_area.x = clipper_area.x - text_cur_area.w; - } - else + if (chosen_desc->map.persp_on) { - text_cur_area.x += move_length; + persp[0] = _edje_real_part_state_get(ed, ep, flags, ep->param1.description->map.id_persp, &statep1); } } - /* check condition to stop marquee animator */ - if (chosen_desc->text.ellipsize.marquee_repeat_limit == - chosen_desc->text.ellipsize.marquee_repeat_count) - { - if ((ep->text_marquee_to_left && - text_cur_area.x <= chosen_desc->text.ellipsize.marquee_start_point.x) || - (!ep->text_marquee_to_left && - text_cur_area.x >= chosen_desc->text.ellipsize.marquee_start_point.x)) - { - evas_object_move(ep->object, - chosen_desc->text.ellipsize.marquee_start_point.x, - chosen_desc->text.ellipsize.marquee_start_point.y); - ep->text_marquee_animator = NULL; - return ECORE_CALLBACK_CANCEL; - } - } - - evas_object_move(ep->object, text_cur_area.x, text_cur_area.y); - return ECORE_CALLBACK_RENEW; -} - -static void -_text_object_del_cb(void *data, EINA_UNUSED Evas *e, EINA_UNUSED Evas_Object *obj, EINA_UNUSED void *event_info) -{ - Edje_Real_Part *ep; - - ep = data; - - if (ep->text_marquee_animator) + if (ep->param2 && ep->param2->description->map.on) { - ecore_animator_del(ep->text_marquee_animator); - ep->text_marquee_animator = NULL; - _text_marquee_clipper_del(ep); - } -} + center[1] = _edje_real_part_state_get(ed, ep, flags, ep->param2->description->map.rot.id_center, &statec2); + light[1] = _edje_real_part_state_get(ed, ep, flags, ep->param2->description->map.id_light, &statel2); -static void -_edje_text_marquee_apply(Edje *ed EINA_UNUSED, Edje_Real_Part *ep, - Edje_Calc_Params *pf, - Edje_Part_Description_Text *chosen_desc) -{ - Eina_Bool is_marquee_on; + if (chosen_desc->map.persp_on) + { + persp[1] = _edje_real_part_state_get(ed, ep, flags, ep->param2->description->map.id_persp, &statep2); + } + } - is_marquee_on = ((chosen_desc->text.ellipsize.mode == EDJE_TEXT_ELLIPSIZE_MODE_MARQUEE) && - (chosen_desc->text.ellipsize.marquee_repeat_count != - chosen_desc->text.ellipsize.marquee_repeat_limit)); +#ifndef EDJE_CALC_CACHE + p1 = &lp1; + p1.map = eina_cow_alloc(_edje_calc_params_map_cow); +#ifdef HAVE_EPHYSICS + p1.physics = eina_cow_alloc(_edje_calc_params_physics_cow); +#endif +#else + p1 = &ep->param1.p; +#endif - if (ep->text_marquee_animator) + if (ep->param1.description) { - ecore_animator_del(ep->text_marquee_animator); - ep->text_marquee_animator = NULL; +#ifdef EDJE_CALC_CACHE + if (ed->all_part_change || + ep->invalidate || + (state1 >= ep->param1.state) || + (statec >= ep->param1.state) || + (statet >= ep->param1.state) || + (statec1 >= ep->param1.state) || + (statel1 >= ep->param1.state) || + (statep1 >= ep->param1.state) || + (statecl >= ep->param1.state) || + proxy_invalidate || + state || + ed->need_map_update || + ((ep->part->type == EDJE_PART_TYPE_TEXT || + ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) && + ed->text_part_change)) +#endif + { + _edje_part_recalc_single(ed, ep, ep->param1.description, + chosen_desc, center[0], light[0], + persp[0], rp1[Rel1X], rp1[Rel1Y], + rp1[Rel2X], rp1[Rel2Y], clip1, confine_to, + threshold, p1, mmw, mmh, + pos); +#ifdef EDJE_CALC_CACHE + if (flags == FLAG_XY) ep->param1.state = ed->state; +#endif + } } - - /* in case of marquee mode, do not remove existing clipper */ - if (is_marquee_on) + if (ep->param2) { - Evas_BiDi_Direction dir; - int width, height; - int offset_x = 0, offset_y = 0; - - - ep->text_marquee_prev_time = ecore_time_get(); + int beginning_pos, part_type; + Edje_Calc_Params *p2, *p3; - /* check text direction */ - if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) - { - dir = evas_object_paragraph_direction_get(ep->object); - if (dir == EVAS_BIDI_DIRECTION_NEUTRAL) - { - Evas_Textblock_Cursor *cur; - cur = evas_object_textblock_cursor_new(ep->object); - evas_textblock_cursor_geometry_get(cur, - NULL, NULL, NULL, NULL, &dir, - EVAS_TEXTBLOCK_CURSOR_BEFORE); - evas_textblock_cursor_free(cur); - } - evas_object_textblock_size_formatted_get(ep->object, &width, NULL); - } - else + if (ep->current) { - dir = evas_object_text_direction_get(ep->object); + const Edje_Calc_Params_Map *map; +#ifdef HAVE_EPHYSICS + const Edje_Calc_Params_Physics *physics; +#endif - /* force recalc by calling resize */ - evas_object_resize(ep->object, pf->final.w, pf->final.h); - width = evas_object_text_horiz_advance_get(ep->object); - height = evas_object_text_vert_advance_get(ep->object); + map = p1->map; +#ifdef HAVE_EPHYSICS + physics = p1->physics; +#endif - /* Handle alignment */ - { - FLOAT_T align_x; - if (pf->type.text.align.x < FROM_INT(0)) - { - if (evas_object_text_direction_get(ep->object) == - EVAS_BIDI_DIRECTION_RTL) - { - align_x = FROM_INT(1); - } - else - { - align_x = FROM_INT(0); - } - } - else - { - align_x = pf->type.text.align.x; - } - if (width < pf->final.w) - offset_x = TO_INT(SCALE(align_x, (pf->final.w - width))); - if (height < pf->final.h) - offset_y = TO_INT(SCALE(pf->type.text.align.y, (pf->final.h - height))); - } + /* FIXME: except for text, we don't need in that case to recalc p1 at all*/ + memcpy(p1, ep->current, sizeof (Edje_Calc_Params)); + + p1->map = map; +#ifdef HAVE_EPHYSICS + p1->physics = physics; +#endif } - chosen_desc->text.ellipsize.marquee_start_point.x = ed->x + pf->final.x + offset_x; - chosen_desc->text.ellipsize.marquee_start_point.y = ed->y + pf->final.y + offset_y; + p3 = &lp3; + lp3.map = eina_cow_alloc(_edje_calc_params_map_cow); +#ifdef HAVE_EPHYSICS + lp3.physics = eina_cow_alloc(_edje_calc_params_physics_cow); +#endif - _text_marquee_clipper_update(ep, ed->x + pf->final.x, ed->y + pf->final.y, pf->final.w, pf->final.h); - - /* define marquee direction */ - ep->text_marquee_to_left = (dir != EVAS_BIDI_DIRECTION_RTL); +#ifndef EDJE_CALC_CACHE + p2 = &lp2; + lp2.map = eina_cow_alloc(_edje_calc_params_map_cow); +#ifdef HAVE_EPHYSICS + lp2.physics = eina_cow_alloc(_edje_calc_params_physics_cow); +#endif +#else + p2 = &ep->param2->p; - /* adjust start position for RTL text */ - if (!ep->text_marquee_to_left) - chosen_desc->text.ellipsize.marquee_start_point.x += pf->final.w - width; + if (ed->all_part_change || + ep->invalidate || + (state2 >= ep->param2->state) || + (statec >= ep->param2->state) || + (statet >= ep->param2->state) || + (statec2 >= ep->param2->state) || + (statel2 >= ep->param2->state) || + (statep2 >= ep->param2->state) || + (statecl >= ep->param2->state) || + proxy_invalidate || + state || + ed->need_map_update || + ((ep->part->type == EDJE_PART_TYPE_TEXT || + ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) && + ed->text_part_change)) +#endif + { + _edje_part_recalc_single(ed, ep, ep->param2->description, + chosen_desc, center[1], light[1], + persp[1], rp2[Rel1X], rp2[Rel1Y], + rp2[Rel2X], rp2[Rel2Y], clip2, confine_to, + threshold, p2, mmw, mmh, + pos); +#ifdef EDJE_CALC_CACHE + if (flags == FLAG_XY) ep->param2->state = ed->state; +#endif + } - /* move the object to the start point */ - evas_object_move(ep->object, - chosen_desc->text.ellipsize.marquee_start_point.x, - chosen_desc->text.ellipsize.marquee_start_point.y); + pos2 = pos; + if (pos2 < ZERO) pos2 = ZERO; + else if (pos2 > FROM_INT(1)) + pos2 = FROM_INT(1); + beginning_pos = (pos < FROM_DOUBLE(0.5)); + part_type = ep->part->type; - ep->text_marquee_animator = ecore_animator_add(_text_object_marquee_animator, ep); - evas_object_event_callback_add(ep->object, EVAS_CALLBACK_DEL, - _text_object_del_cb, ep); - } - else - { - _text_marquee_clipper_del(ep); - } -} -// + /* visible is special */ + if ((p1->visible) && (!p2->visible)) + p3->visible = (pos != FROM_INT(1)); + else if ((!p1->visible) && (p2->visible)) + p3->visible = (pos != ZERO); + else + p3->visible = p1->visible; -void -_edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int flags, Edje_Calc_Params *state) -{ -#ifdef EDJE_CALC_CACHE - Eina_Bool proxy_invalidate = EINA_FALSE; - int state1 = -1; - int state2 = -1; - int statec = -1; - int statet = -1; -#else - Edje_Calc_Params lp1, lp2; -#endif - int statec1 = -1; - int statec2 = -1; - int statel1 = -1; - int statel2 = -1; - int statep1 = -1; - int statep2 = -1; - int statecl = -1; - Edje_Real_Part *center[2] = { NULL, NULL }; - Edje_Real_Part *light[2] = { NULL, NULL }; - Edje_Real_Part *persp[2] = { NULL, NULL }; - Edje_Real_Part *rp1[4] = { NULL, NULL, NULL, NULL }; - Edje_Real_Part *rp2[4] = { NULL, NULL, NULL, NULL }; - Edje_Real_Part *clip1 = NULL, *clip2 = NULL; - Edje_Calc_Params *p1, *pf; - Edje_Part_Description_Common *chosen_desc; - Edje_Real_Part *confine_to = NULL; - Edje_Real_Part *threshold = NULL; - FLOAT_T pos = ZERO, pos2; - Edje_Calc_Params lp3; - Evas_Coord mmw = 0, mmh = 0; - Eina_Bool map_colors_free = EINA_FALSE; - //TIZEN_ONLY(20160923): introduction of text marquee - Evas_Coord tw, th; - Edje_Part_Description_Text *text_chosen_desc; - // + /* clip_to will behave a bit like visible */ + if (pos == ZERO) + p3->clip_to = p1->clip_to; + else if (pos == FROM_INT(1)) + p3->clip_to = p2->clip_to; + else if (!p1->clip_to) + p3->clip_to = p2->clip_to; + else + p3->clip_to = p1->clip_to; - /* GRADIENT ARE GONE, WE MUST IGNORE IT FROM OLD FILE. */ - if (ep->part->type == EDJE_PART_TYPE_GRADIENT) - { - ERR("GRADIENT spotted during recalc ! That should never happen ! Send your edje file to devel ml."); - return; - } + p3->smooth = (beginning_pos) ? p1->smooth : p2->smooth; - if ((ep->calculated & FLAG_XY) == FLAG_XY && !state) - { - return; - } - if (ep->calculating & flags) - { -#if 1 - const char *axes = "NONE", *faxes = "NONE"; + /* FIXME: do x and y separately base on flag */ - if ((ep->calculating & FLAG_X) && - (ep->calculating & FLAG_Y)) - axes = "XY"; - else if ((ep->calculating & FLAG_X)) - axes = "X"; - else if ((ep->calculating & FLAG_Y)) - axes = "Y"; + p3->final.x = INTP(p1->final.x, p2->final.x, pos); + p3->final.y = INTP(p1->final.y, p2->final.y, pos); + p3->final.w = INTP(p1->final.w, p2->final.w, pos); + p3->final.h = INTP(p1->final.h, p2->final.h, pos); - if ((flags & FLAG_X) && - (flags & FLAG_Y)) - faxes = "XY"; - else if ((flags & FLAG_X)) - faxes = "X"; - else if ((flags & FLAG_Y)) - faxes = "Y"; - ERR("Circular dependency when calculating part \"%s\". " - "Already calculating %s [%02x] axes. " - "Need to calculate %s [%02x] axes", - ep->part->name, - axes, ep->calculating, - faxes, flags); + p3->eval.x = FFP(p1->eval.x, p2->eval.x, pos); + p3->eval.y = FFP(p1->eval.y, p2->eval.y, pos); + p3->eval.w = FFP(p1->eval.w, p2->eval.w, pos); + p3->eval.h = FFP(p1->eval.h, p2->eval.h, pos); - Eina_List *clist = NULL; - Eina_List *l = NULL; - char *part_name; - char depends_path[PATH_MAX] = ""; - _circular_dependency_find(ed, ep, NULL, &clist); - strncat(depends_path, ep->part->name, - sizeof(depends_path) - strlen(depends_path) - 1); - EINA_LIST_FOREACH(clist, l, part_name) - { - strncat(depends_path, " -> ", - sizeof(depends_path) - strlen(depends_path) - 1); - strncat(depends_path, part_name, - sizeof(depends_path) - strlen(depends_path) - 1); - } - ERR("Circular dependency in the group '%s' : %s", ed->group, depends_path); - eina_list_free(clist); -#endif - return; - } + p3->req.x = INTP(p1->req.x, p2->req.x, pos); + p3->req.y = INTP(p1->req.y, p2->req.y, pos); + p3->req.w = INTP(p1->req.w, p2->req.w, pos); + p3->req.h = INTP(p1->req.h, p2->req.h, pos); - if (ep->part->type == EDJE_PART_TYPE_GROUP && - ((ep->type == EDJE_RP_TYPE_SWALLOW) && - (ep->typedata.swallow)) && - ep->typedata.swallow->swallowed_object) - { - edje_object_scale_set(ep->typedata.swallow->swallowed_object, TO_DOUBLE(ed->scale)); + _edje_part_pixel_adjust(ed, ep, p3); - if (ep->description_pos > FROM_DOUBLE(0.5) && ep->param2) + if (ep->part->dragable.x) { - edje_object_update_hints_set(ep->typedata.swallow->swallowed_object, ep->param2->description->min.limit); + p3->req_drag.x = INTP(p1->req_drag.x, p2->req_drag.x, pos); + p3->req_drag.w = INTP(p1->req_drag.w, p2->req_drag.w, pos); } - else + if (ep->part->dragable.y) { - edje_object_update_hints_set(ep->typedata.swallow->swallowed_object, ep->param1.description->min.limit); + p3->req_drag.y = INTP(p1->req_drag.y, p2->req_drag.y, pos); + p3->req_drag.h = INTP(p1->req_drag.h, p2->req_drag.h, pos); } - if (edje_object_update_hints_get(ep->typedata.swallow->swallowed_object)) - { - Edje *ted; - ted = _edje_fetch(ep->typedata.swallow->swallowed_object); - _edje_recalc_do(ted); - } - } - if (ep->part->type == EDJE_PART_TYPE_GROUP && - ((ep->type == EDJE_RP_TYPE_SWALLOW) && - (ep->typedata.swallow)) && - ep->typedata.swallow->swallowed_object) - { - Edje_Size *min = NULL, *max = NULL; + p3->color.r = INTP(p1->color.r, p2->color.r, pos2); + p3->color.g = INTP(p1->color.g, p2->color.g, pos2); + p3->color.b = INTP(p1->color.b, p2->color.b, pos2); + p3->color.a = INTP(p1->color.a, p2->color.a, pos2); - if (ep->chosen_description) +#ifdef HAVE_EPHYSICS + if (ep->part->physics_body || ep->body) { - min = &ep->chosen_description->min; - max = &ep->chosen_description->max; - } - if (min && max && (min->w == max->w) && (min->h == max->h) && (min->w > 0) && (min->h > 0)) - mmw = min->w, mmh = min->h; - else - edje_object_size_min_calc(ep->typedata.swallow->swallowed_object, - &mmw, &mmh); - } + EINA_COW_CALC_PHYSICS_BEGIN(p3, p3_write) + { + p3_write->mass = TO_DOUBLE(FINTP(p1->physics->mass, p2->physics->mass, + pos)); + p3_write->restitution = TO_DOUBLE(FINTP(p1->physics->restitution, + p2->physics->restitution, + pos)); + p3_write->friction = TO_DOUBLE(FINTP(p1->physics->friction, + p2->physics->friction, pos)); + p3_write->density = TO_DOUBLE(FINTP(p1->physics->density, + p2->physics->density, pos)); + p3_write->hardness = TO_DOUBLE(FINTP(p1->physics->hardness, + p2->physics->hardness, pos)); -#ifdef EDJE_CALC_CACHE - if (ep->state == ed->state && !state) - return; -#endif + p3_write->damping.linear = TO_DOUBLE(FINTP(p1->physics->damping.linear, + p2->physics->damping.linear, pos)); + p3_write->damping.angular = TO_DOUBLE(FINTP(p1->physics->damping.angular, + p2->physics->damping.angular, pos)); - if (ep->param1.description) - { - if (ep->param1.description->rel1.id_x >= 0) - rp1[Rel1X] = ed->table_parts[ep->param1.description->rel1.id_x]; - if (ep->param1.description->rel2.id_x >= 0) - rp1[Rel2X] = ed->table_parts[ep->param1.description->rel2.id_x]; - if (ep->param1.description->rel1.id_y >= 0) - rp1[Rel1Y] = ed->table_parts[ep->param1.description->rel1.id_y]; - if (ep->param1.description->rel2.id_y >= 0) - rp1[Rel2Y] = ed->table_parts[ep->param1.description->rel2.id_y]; - if (ep->param1.description->clip_to_id >= 0) - { - clip1 = ed->table_parts[ep->param1.description->clip_to_id % ed->table_parts_size]; - ed->has_state_clip = EINA_TRUE; - } - } - if (ep->param2) - { - if (ep->param2->description->rel1.id_x >= 0) - rp2[Rel1X] = ed->table_parts[ep->param2->description->rel1.id_x]; - if (ep->param2->description->rel2.id_x >= 0) - rp2[Rel2X] = ed->table_parts[ep->param2->description->rel2.id_x]; - if (ep->param2->description->rel1.id_y >= 0) - rp2[Rel1Y] = ed->table_parts[ep->param2->description->rel1.id_y]; - if (ep->param2->description->rel2.id_y >= 0) - rp2[Rel2Y] = ed->table_parts[ep->param2->description->rel2.id_y]; - if (ep->param2->description->clip_to_id >= 0) - { - clip2 = ed->table_parts[ep->param2->description->clip_to_id % ed->table_parts_size]; - ed->has_state_clip = EINA_TRUE; + p3_write->sleep.linear = TO_DOUBLE(FINTP(p1->physics->sleep.linear, + p2->physics->sleep.linear, pos)); + p3_write->sleep.angular = TO_DOUBLE(FINTP(p1->physics->sleep.angular, + p2->physics->sleep.angular, pos)); + + p3_write->z = INTP(p1->physics->z, p2->physics->z, pos); + p3_write->depth = INTP(p1->physics->depth, p2->physics->depth, pos); + + if ((p1->physics->ignore_part_pos) && (p2->physics->ignore_part_pos)) + p3_write->ignore_part_pos = 1; + else + p3_write->ignore_part_pos = 0; + + if ((p1->physics->material) && (p2->physics->material)) + p3_write->material = p1->physics->material; + else + p3_write->material = EPHYSICS_BODY_MATERIAL_CUSTOM; + + p3_write->light_on = p1->physics->light_on || p2->physics->light_on; + p3_write->backcull = p1->physics->backcull || p2->physics->backcull; + + p3_write->mov_freedom.lin.x = p1->physics->mov_freedom.lin.x || + p2->physics->mov_freedom.lin.x; + p3_write->mov_freedom.lin.y = p1->physics->mov_freedom.lin.y || + p2->physics->mov_freedom.lin.y; + p3_write->mov_freedom.lin.z = p1->physics->mov_freedom.lin.z || + p2->physics->mov_freedom.lin.z; + p3_write->mov_freedom.ang.x = p1->physics->mov_freedom.ang.x || + p2->physics->mov_freedom.ang.x; + p3_write->mov_freedom.ang.y = p1->physics->mov_freedom.ang.y || + p2->physics->mov_freedom.ang.y; + p3_write->mov_freedom.ang.z = p1->physics->mov_freedom.ang.z || + p2->physics->mov_freedom.ang.z; + } + EINA_COW_CALC_PHYSICS_END(p3, p3_write); } - } +#endif - if (flags & FLAG_X) - { - ep->calculating |= flags & FLAG_X; - if (rp1[Rel1X]) + switch (part_type) { - _edje_part_recalc(ed, rp1[Rel1X], FLAG_X, NULL); -#ifdef EDJE_CALC_CACHE - state1 = rp1[Rel1X]->state; -#endif + case EDJE_PART_TYPE_IMAGE: + p3->type.common.spec.image.l = INTP(p1->type.common.spec.image.l, p2->type.common.spec.image.l, pos); + p3->type.common.spec.image.r = INTP(p1->type.common.spec.image.r, p2->type.common.spec.image.r, pos); + p3->type.common.spec.image.t = INTP(p1->type.common.spec.image.t, p2->type.common.spec.image.t, pos); + p3->type.common.spec.image.b = INTP(p1->type.common.spec.image.b, p2->type.common.spec.image.b, pos); + p3->type.common.spec.image.border_scale_by = FFP(p1->type.common.spec.image.border_scale_by, p2->type.common.spec.image.border_scale_by, pos); + + case EDJE_PART_TYPE_PROXY: + p3->type.common.fill.x = INTP(p1->type.common.fill.x, p2->type.common.fill.x, pos); + p3->type.common.fill.y = INTP(p1->type.common.fill.y, p2->type.common.fill.y, pos); + p3->type.common.fill.w = INTP(p1->type.common.fill.w, p2->type.common.fill.w, pos); + p3->type.common.fill.h = INTP(p1->type.common.fill.h, p2->type.common.fill.h, pos); + break; + + case EDJE_PART_TYPE_TEXT: + p3->type.text.size = INTP(p1->type.text.size, p2->type.text.size, pos); + + /* no break as we share code with the TEXTBLOCK type here. Intended fall-through */ + case EDJE_PART_TYPE_TEXTBLOCK: + p3->type.text.color2.r = INTP(p1->type.text.color2.r, p2->type.text.color2.r, pos2); + p3->type.text.color2.g = INTP(p1->type.text.color2.g, p2->type.text.color2.g, pos2); + p3->type.text.color2.b = INTP(p1->type.text.color2.b, p2->type.text.color2.b, pos2); + p3->type.text.color2.a = INTP(p1->type.text.color2.a, p2->type.text.color2.a, pos2); + + p3->type.text.color3.r = INTP(p1->type.text.color3.r, p2->type.text.color3.r, pos2); + p3->type.text.color3.g = INTP(p1->type.text.color3.g, p2->type.text.color3.g, pos2); + p3->type.text.color3.b = INTP(p1->type.text.color3.b, p2->type.text.color3.b, pos2); + p3->type.text.color3.a = INTP(p1->type.text.color3.a, p2->type.text.color3.a, pos2); + + p3->type.text.align.x = FFP(p1->type.text.align.x, p2->type.text.align.x, pos); + p3->type.text.align.y = FFP(p1->type.text.align.y, p2->type.text.align.y, pos); + p3->type.text.ellipsis = TO_DOUBLE(FINTP(p1->type.text.ellipsis, p2->type.text.ellipsis, pos2)); + break; } - if (rp1[Rel2X]) + + /* mapped is a special case like visible */ + if ((p1->mapped) && (!p2->mapped)) + p3->mapped = (pos != FROM_INT(1)); + else if ((!p1->mapped) && (p2->mapped)) + p3->mapped = (pos != ZERO); + else + p3->mapped = p1->mapped; + + p3->persp_on = p3->mapped ? p1->persp_on | p2->persp_on : 0; + p3->lighted = p3->mapped ? p1->lighted | p2->lighted : 0; + if (p3->mapped) { - _edje_part_recalc(ed, rp1[Rel2X], FLAG_X, NULL); -#ifdef EDJE_CALC_CACHE - if (state1 < rp1[Rel2X]->state) - state1 = rp1[Rel2X]->state; -#endif + EINA_COW_CALC_MAP_BEGIN(p3, p3_write) + { + p3_write->center.x = INTP(p1->map->center.x, p2->map->center.x, pos); + p3_write->center.y = INTP(p1->map->center.y, p2->map->center.y, pos); + p3_write->center.z = INTP(p1->map->center.z, p2->map->center.z, pos); + p3_write->rotation.x = FFP(p1->map->rotation.x, p2->map->rotation.x, pos); + p3_write->rotation.y = FFP(p1->map->rotation.y, p2->map->rotation.y, pos); + p3_write->rotation.z = FFP(p1->map->rotation.z, p2->map->rotation.z, pos); + p3_write->zoom.x = FFP(p1->map->zoom.x, p2->map->zoom.x, pos); + p3_write->zoom.y = FFP(p1->map->zoom.y, p2->map->zoom.y, pos); + +#define MIX(P1, P2, P3, pos, info) \ + P3->info = P1->map->info + TO_INT(SCALE(pos, P2->map->info - P1->map->info)); + map_colors_free = _map_colors_interp(p1, p2, p3_write, pos); + + if (p1->lighted && p2->lighted) + { + MIX(p1, p2, p3_write, pos, light.x); + MIX(p1, p2, p3_write, pos, light.y); + MIX(p1, p2, p3_write, pos, light.z); + MIX(p1, p2, p3_write, pos, light.r); + MIX(p1, p2, p3_write, pos, light.g); + MIX(p1, p2, p3_write, pos, light.b); + MIX(p1, p2, p3_write, pos, light.ar); + MIX(p1, p2, p3_write, pos, light.ag); + MIX(p1, p2, p3_write, pos, light.ab); + } + else if (p1->lighted) + { + memcpy(&p3_write->light, &p1->map->light, sizeof (p1->map->light)); + } + else if (p2->lighted) + { + memcpy(&p3_write->light, &p2->map->light, sizeof (p2->map->light)); + } + + if (p1->persp_on && p2->persp_on) + { + MIX(p1, p2, p3_write, pos, persp.x); + MIX(p1, p2, p3_write, pos, persp.y); + MIX(p1, p2, p3_write, pos, persp.z); + MIX(p1, p2, p3_write, pos, persp.focal); + } + else if (p1->persp_on) + { + memcpy(&p3_write->persp, &p1->map->persp, sizeof (p1->map->persp)); + } + else if (p2->persp_on) + { + memcpy(&p3_write->persp, &p2->map->persp, sizeof (p2->map->persp)); + } + } + EINA_COW_CALC_MAP_END(p3, p3_write); } - if (ep->param2) - { - if (rp2[Rel1X]) - { - _edje_part_recalc(ed, rp2[Rel1X], FLAG_X, NULL); -#ifdef EDJE_CALC_CACHE - state2 = rp2[Rel1X]->state; + +#ifndef EDJE_CALC_CACHE + eina_cow_free(_edje_calc_params_map_cow, (const Eina_Cow_Data **)&lp2.map); +#ifdef HAVE_EPHYSICS + eina_cow_free(_edje_calc_params_physics_cow, (const Eina_Cow_Data **)&lp2.physics); #endif - } - if (rp2[Rel2X]) - { - _edje_part_recalc(ed, rp2[Rel2X], FLAG_X, NULL); -#ifdef EDJE_CALC_CACHE - if (state2 < rp2[Rel2X]->state) - state2 = rp2[Rel2X]->state; #endif - } - } + pf = p3; } - if (flags & FLAG_Y) + else { - ep->calculating |= flags & FLAG_Y; - if (rp1[Rel1Y]) + pf = p1; + } + + if (!pf->persp_on && chosen_desc->map.persp_on) + { + if (ed->persp) { - _edje_part_recalc(ed, rp1[Rel1Y], FLAG_Y, NULL); -#ifdef EDJE_CALC_CACHE - if (state1 < rp1[Rel1Y]->state) - state1 = rp1[Rel1Y]->state; -#endif + EINA_COW_CALC_MAP_BEGIN(pf, pf_write) + { + pf_write->persp.x = ed->persp->px; + pf_write->persp.y = ed->persp->py; + pf_write->persp.z = ed->persp->z0; + pf_write->persp.focal = ed->persp->foc; + } + EINA_COW_CALC_MAP_END(pf, pf_write); } - if (rp1[Rel2Y]) + else { - _edje_part_recalc(ed, rp1[Rel2Y], FLAG_Y, NULL); -#ifdef EDJE_CALC_CACHE - if (state1 < rp1[Rel2Y]->state) - state1 = rp1[Rel2Y]->state; -#endif + const Edje_Perspective *ps; + + // fixme: a tad inefficient as this is a has lookup + ps = edje_object_perspective_get(ed->obj); + if (!ps) + ps = edje_evas_global_perspective_get(evas_object_evas_get(ed->obj)); + EINA_COW_CALC_MAP_BEGIN(pf, pf_write) + { + if (ps) + { + pf_write->persp.x = ps->px; + pf_write->persp.y = ps->py; + pf_write->persp.z = ps->z0; + pf_write->persp.focal = ps->foc; + } + else + { + pf_write->persp.x = ed->x + (ed->w / 2); + pf_write->persp.y = ed->y + (ed->h / 2); + pf_write->persp.z = 0; + pf_write->persp.focal = 1000; + } + } + EINA_COW_CALC_MAP_END(pf, pf_write); } - if (ep->param2) - { - if (rp2[Rel1Y]) - { - _edje_part_recalc(ed, rp2[Rel1Y], FLAG_Y, NULL); -#ifdef EDJE_CALC_CACHE - if (state2 < rp2[Rel1Y]->state) - state2 = rp2[Rel1Y]->state; + } + + if (state) + { + const Edje_Calc_Params_Map *map; +#ifdef HAVE_EPHYSICS + const Edje_Calc_Params_Physics *physics; +#endif + + map = state->map; +#ifdef HAVE_EPHYSICS + physics = state->physics; +#endif + + memcpy(state, pf, sizeof (Edje_Calc_Params)); + + state->map = map; +#ifdef HAVE_EPHYSICS + state->physics = physics; +#endif + eina_cow_memcpy(_edje_calc_params_map_cow, (const Eina_Cow_Data **)&state->map, pf->map); +#ifdef HAVE_EPHYSICS + eina_cow_memcpy(_edje_calc_params_physics_cow, (const Eina_Cow_Data **)&state->physics, pf->physics); +#endif + } + + ep->req = pf->req; + + if (ep->drag && ep->drag->need_reset) + { + FLOAT_T dx, dy; + + dx = ZERO; + dy = ZERO; + _edje_part_dragable_calc(ed, ep, &dx, &dy); + ep->drag->x = dx; + ep->drag->y = dy; + ep->drag->tmp.x = 0; + ep->drag->tmp.y = 0; + ep->drag->need_reset = 0; + } + if (!ed->calc_only) + { + Evas_Object *mo; + + /* Common move, resize and color_set for all part. */ + switch (ep->part->type) + { + case EDJE_PART_TYPE_IMAGE: + { + Edje_Part_Description_Image *img_desc = (Edje_Part_Description_Image *)chosen_desc; + + evas_object_image_scale_hint_set(ep->object, + img_desc->image.scale_hint); + /* No break here as we share the rest of the code for all types. Intended fall-through*/ + } + + case EDJE_PART_TYPE_PROXY: + case EDJE_PART_TYPE_RECTANGLE: + case EDJE_PART_TYPE_TEXTBLOCK: + case EDJE_PART_TYPE_BOX: + case EDJE_PART_TYPE_TABLE: + case EDJE_PART_TYPE_SNAPSHOT: + case EDJE_PART_TYPE_VECTOR: + evas_object_color_set(ep->object, + (pf->color.r * pf->color.a) / 255, + (pf->color.g * pf->color.a) / 255, + (pf->color.b * pf->color.a) / 255, + pf->color.a); + +#ifdef HAVE_EPHYSICS +/* body attributes should be updated for invisible objects */ + if (!ep->part->physics_body) + { + if (!pf->visible) + { + evas_object_hide(ep->object); + break; + } + evas_object_show(ep->object); + } + else if (!pf->visible) + { + Evas_Object *face_obj; + Eina_List *l; + + EINA_LIST_FOREACH(ep->body_faces, l, face_obj) + evas_object_hide(face_obj); + evas_object_hide(ep->object); + } +#else + if (!pf->visible) + { + evas_object_hide(ep->object); + break; + } + evas_object_show(ep->object); + +#endif + /* move and resize are needed for all previous object => no break here. */ + case EDJE_PART_TYPE_SWALLOW: + case EDJE_PART_TYPE_GROUP: + case EDJE_PART_TYPE_EXTERNAL: + /* visibility and color have no meaning on SWALLOW and GROUP part. */ +#ifdef HAVE_EPHYSICS + eo_do(ep->object, + efl_gfx_size_set(pf->final.w, pf->final.h)); + if ((ep->part->physics_body) && (!ep->body)) + { + if (_edje_physics_world_geometry_check(ed->world)) + { + _edje_physics_body_add(ed, ep, ed->world); + _edje_physics_body_props_update(ed, ep, pf, EINA_TRUE); + } + } + else if (ep->body) + { + if (((ep->prev_description) && + (chosen_desc != ep->prev_description)) || + (pf != p1)) + _edje_physics_body_props_update(ed, ep, pf, !pf->physics->ignore_part_pos); + } + else + eo_do(ep->object, + efl_gfx_position_set(ed->x + pf->final.x, ed->y + pf->final.y)); +#else + eo_do(ep->object, + efl_gfx_position_set(ed->x + pf->final.x, ed->y + pf->final.y)); + + eo_do(ep->object, + efl_gfx_size_set(pf->final.w, pf->final.h)); +#endif + + if (ep->nested_smart) /* Move, Resize all nested parts */ + { /* Not really needed but will improve the bounding box evaluation done by Evas */ + eo_do(ep->nested_smart, + efl_gfx_position_set(ed->x + pf->final.x, ed->y + pf->final.y), + efl_gfx_size_set(pf->final.w, pf->final.h)); + } + if (ep->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE) + _edje_entry_real_part_configure(ed, ep); + + /* handle clip overrides */ + if (ed->has_state_clip) + { + if (pf->clip_to && pf->clip_to->object) + evas_object_clip_set(ep->object, pf->clip_to->object); + else if (ep->part->clip_to_id >= 0) + evas_object_clip_set(ep->object, ed->table_parts[ep->part->clip_to_id % ed->table_parts_size]->object); + else + evas_object_clip_set(ep->object, ed->base->clipper); + } + break; + + case EDJE_PART_TYPE_TEXT: + /* This is correctly handle in _edje_text_recalc_apply at the moment. */ + break; + + case EDJE_PART_TYPE_GRADIENT: + /* FIXME: definitivly remove this code when we switch to new format. */ + abort(); + break; + + case EDJE_PART_TYPE_SPACER: + /* We really should do nothing on SPACER part */ + break; + case EDJE_PART_TYPE_CAMERA: + { + Evas_Canvas3D_Camera *camera = NULL; + Edje_Part_Description_Camera *pd_camera; + + pd_camera = (Edje_Part_Description_Camera*) ep->chosen_description; + eo_do(ep->node, camera = evas_canvas3d_node_camera_get()); + + eo_do(camera, + evas_canvas3d_camera_projection_perspective_set(pd_camera->camera.camera.fovy, pd_camera->camera.camera.aspect, + pd_camera->camera.camera.frustum_near, pd_camera->camera.camera.frustum_far)); + + eo_do(ep->node, + evas_canvas3d_node_position_set(pd_camera->camera.position.point.x, pd_camera->camera.position.point.y, + pd_camera->camera.position.point.z)); + switch (pd_camera->camera.orientation.type) + { + case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_NONE: + case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_QUATERNION: + { + SET_QUATERNION(camera) + break; + } + case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_LOOK_AT: + SET_LOOK_AT(camera) + break; + case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_LOOK_TO: + { + SET_LOOK_TO(camera) + break; + } + case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_ANGLE_AXIS: + SET_ANGLE_AXIS(camera) + break; + } + break; + } + case EDJE_PART_TYPE_LIGHT: + { + Evas_Canvas3D_Light *light_node = NULL; + Edje_Part_Description_Light *pd_light; + + pd_light = (Edje_Part_Description_Light*) ep->chosen_description; + eo_do(ep->node, light_node = evas_canvas3d_node_light_get()); + + eo_do(light_node, + evas_canvas3d_light_ambient_set(pd_light->light.properties.ambient.r / 255, pd_light->light.properties.ambient.g / 255, + pd_light->light.properties.ambient.b / 255, pd_light->light.properties.ambient.a / 255), + evas_canvas3d_light_diffuse_set(pd_light->light.properties.diffuse.r / 255, pd_light->light.properties.diffuse.g / 255, + pd_light->light.properties.diffuse.b / 255, pd_light->light.properties.diffuse.a / 255), + evas_canvas3d_light_specular_set(pd_light->light.properties.specular.r / 255, pd_light->light.properties.specular.g / 255, + pd_light->light.properties.specular.b / 255, pd_light->light.properties.specular.a / 255), + evas_canvas3d_light_directional_set(EINA_TRUE)); + + eo_do(ep->node, + evas_canvas3d_node_position_set(pd_light->light.position.point.x, pd_light->light.position.point.y, + pd_light->light.position.point.z)); + switch (pd_light->light.orientation.type) + { + case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_NONE: + case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_QUATERNION: + { + SET_QUATERNION(light); + break; + } + case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_LOOK_AT: + SET_LOOK_AT(light) + break; + case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_LOOK_TO: + { + SET_LOOK_TO(light) + break; + } + case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_ANGLE_AXIS: + SET_ANGLE_AXIS(light) + break; + } + break; + } + case EDJE_PART_TYPE_MESH_NODE: + { + Evas_Canvas3D_Material *material = NULL; + Evas_Canvas3D_Texture *texture = NULL; + Evas_Canvas3D_Mesh *mesh = NULL; + const char *proxy; + Edje_Part_Description_Mesh_Node *pd_mesh_node; + const Eina_List *meshes; + const Eina_List *list; + + eo_do(ep->node, meshes = evas_canvas3d_node_mesh_list_get()); + + EINA_LIST_FOREACH(meshes, list, mesh) + { + eo_do(mesh, material = evas_canvas3d_mesh_frame_material_get(0)); + eo_do(material, texture = evas_canvas3d_material_texture_get(EVAS_CANVAS3D_MATERIAL_ATTRIB_DIFFUSE)); + + pd_mesh_node = (Edje_Part_Description_Mesh_Node*) ep->chosen_description; + + eo_do(material, + evas_canvas3d_material_enable_set(EVAS_CANVAS3D_MATERIAL_ATTRIB_AMBIENT, EINA_TRUE), + evas_canvas3d_material_enable_set(EVAS_CANVAS3D_MATERIAL_ATTRIB_DIFFUSE, EINA_TRUE), + evas_canvas3d_material_enable_set(EVAS_CANVAS3D_MATERIAL_ATTRIB_SPECULAR, EINA_TRUE), + evas_canvas3d_material_enable_set(EVAS_CANVAS3D_MATERIAL_ATTRIB_NORMAL, pd_mesh_node->mesh_node.properties.normal), + evas_canvas3d_material_color_set(EVAS_CANVAS3D_MATERIAL_ATTRIB_AMBIENT, + pd_mesh_node->mesh_node.properties.ambient.r / 255, + pd_mesh_node->mesh_node.properties.ambient.g / 255, + pd_mesh_node->mesh_node.properties.ambient.b / 255, + pd_mesh_node->mesh_node.properties.ambient.a / 255), + evas_canvas3d_material_color_set(EVAS_CANVAS3D_MATERIAL_ATTRIB_DIFFUSE, + pd_mesh_node->mesh_node.properties.diffuse.r / 255, + pd_mesh_node->mesh_node.properties.diffuse.g / 255, + pd_mesh_node->mesh_node.properties.diffuse.b / 255, + pd_mesh_node->mesh_node.properties.diffuse.a / 255), + evas_canvas3d_material_color_set(EVAS_CANVAS3D_MATERIAL_ATTRIB_SPECULAR, + pd_mesh_node->mesh_node.properties.specular.r / 255, + pd_mesh_node->mesh_node.properties.specular.g / 255, + pd_mesh_node->mesh_node.properties.specular.b / 255, + pd_mesh_node->mesh_node.properties.specular.a / 255), + evas_canvas3d_material_shininess_set(pd_mesh_node->mesh_node.properties.shininess)); + + switch(pd_mesh_node->mesh_node.mesh.primitive) + { + case EVAS_CANVAS3D_MESH_PRIMITIVE_CUBE: + { + Eo *primitive = NULL; + + eo_do(primitive, + evas_canvas3d_primitive_form_set(EVAS_CANVAS3D_MESH_PRIMITIVE_CUBE)); + + eo_do(mesh, + evas_canvas3d_mesh_from_primitive_set(0, primitive)); + break; + } + case EVAS_CANVAS3D_MESH_PRIMITIVE_SPHERE: + { + Eo *primitive = NULL; + + eo_do(primitive, + evas_canvas3d_primitive_form_set(EVAS_CANVAS3D_MESH_PRIMITIVE_SPHERE), + evas_canvas3d_primitive_precision_set(20)); + + eo_do(mesh, + evas_canvas3d_mesh_from_primitive_set(0, primitive)); + break; + } + default: + break; + } + + if (pd_mesh_node->mesh_node.texture.need_texture && pd_mesh_node->mesh_node.texture.textured) + { + proxy = NULL; + + eo_do(material, + texture = evas_canvas3d_material_texture_get(EVAS_CANVAS3D_MATERIAL_ATTRIB_DIFFUSE)); + + //proxy = _edje_image_name_find(ed, pd_mesh_node->mesh_node.texture.id); + /*FIXME Conflict with function _edje_image_name_find (two places in edje_utils and edje_edit.c, + temporary desicion need to clarify up to commit to phab*/ + proxy = ed->file->image_dir->entries[pd_mesh_node->mesh_node.texture.id].entry; + if (proxy) + { + eo_do(texture, + evas_canvas3d_texture_file_set(eina_stringshare_add(proxy), NULL), + evas_canvas3d_texture_filter_set(pd_mesh_node->mesh_node.texture.filter1, + pd_mesh_node->mesh_node.texture.filter2), + evas_canvas3d_texture_wrap_set(pd_mesh_node->mesh_node.texture.wrap1, + pd_mesh_node->mesh_node.texture.wrap2)); + } + } + + eo_do(mesh, + evas_canvas3d_mesh_frame_material_set(0, material), + evas_canvas3d_mesh_shade_mode_set(pd_mesh_node->mesh_node.properties.shade), + evas_canvas3d_mesh_vertex_assembly_set(pd_mesh_node->mesh_node.mesh.assembly)); + eo_do(ep->node, + evas_canvas3d_node_scale_set(ep->part->scale_3d.x, ep->part->scale_3d.y, + ep->part->scale_3d.z), + evas_canvas3d_node_position_set(pd_mesh_node->mesh_node.position.point.x, + pd_mesh_node->mesh_node.position.point.y, + pd_mesh_node->mesh_node.position.point.z)); + switch (pd_mesh_node->mesh_node.orientation.type) + { + case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_NONE: + case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_QUATERNION: + { + SET_QUATERNION(mesh_node) + break; + } + case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_LOOK_AT: + SET_LOOK_AT(mesh_node) + break; + case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_LOOK_TO: + { + SET_LOOK_TO(mesh_node) + break; + } + case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_ANGLE_AXIS: + SET_ANGLE_AXIS(mesh_node) + break; + } + } + break; + } + } + + /* Some object need special recalc. */ + switch (ep->part->type) + { + case EDJE_PART_TYPE_TEXT: + _edje_text_recalc_apply(ed, ep, pf, (Edje_Part_Description_Text*) chosen_desc, EINA_FALSE); + break; + + case EDJE_PART_TYPE_PROXY: + _edje_proxy_recalc_apply(ed, ep, pf, (Edje_Part_Description_Proxy *)chosen_desc, pos); + break; + + case EDJE_PART_TYPE_IMAGE: + _edje_image_recalc_apply(ed, ep, pf, (Edje_Part_Description_Image *)chosen_desc, pos); + break; + + case EDJE_PART_TYPE_BOX: + _edje_box_recalc_apply(ed, ep, pf, (Edje_Part_Description_Box *)chosen_desc); + break; + + case EDJE_PART_TYPE_TABLE: + _edje_table_recalc_apply(ed, ep, pf, (Edje_Part_Description_Table *)chosen_desc); + break; + + case EDJE_PART_TYPE_TEXTBLOCK: + _edje_textblock_recalc_apply(ed, ep, pf, (Edje_Part_Description_Text *)chosen_desc); + break; + + case EDJE_PART_TYPE_VECTOR: + _edje_svg_recalc_apply(ed, ep, pf, (Edje_Part_Description_Vector *)chosen_desc, pos); + break; + + case EDJE_PART_TYPE_EXTERNAL: + case EDJE_PART_TYPE_RECTANGLE: + case EDJE_PART_TYPE_SWALLOW: + case EDJE_PART_TYPE_GROUP: + /* Nothing special to do for this type of object. */ + break; + + case EDJE_PART_TYPE_GRADIENT: + /* FIXME: definitivly remove this code when we switch to new format. */ + abort(); + break; + + case EDJE_PART_TYPE_SPACER: + /* We really should do nothing on SPACER part */ + break; + } + + if (((ep->type == EDJE_RP_TYPE_SWALLOW) && + (ep->typedata.swallow)) && + (ep->typedata.swallow->swallowed_object)) + { + if (ed->has_state_clip) + { + if (pf->clip_to && pf->clip_to->object) + evas_object_clip_set(ep->typedata.swallow->swallowed_object, pf->clip_to->object); + else if (ep->part->clip_to_id >= 0) + evas_object_clip_set(ep->typedata.swallow->swallowed_object, ed->table_parts[ep->part->clip_to_id % ed->table_parts_size]->object); + else + evas_object_clip_set(ep->typedata.swallow->swallowed_object, ed->base->clipper); + } + + if (pf->visible) + { + Eina_Bool vis = EINA_TRUE; + + if (ep->part->type == EDJE_PART_TYPE_GROUP) + vis = evas_object_visible_get(ed->obj); + eo_do(ep->typedata.swallow->swallowed_object, + efl_gfx_position_set(ed->x + pf->final.x, ed->y + pf->final.y), + efl_gfx_size_set(pf->final.w, pf->final.h), + efl_gfx_visible_set(vis)); + } + else evas_object_hide(ep->typedata.swallow->swallowed_object); + mo = ep->typedata.swallow->swallowed_object; + } + else mo = ep->object; + + Evas_Object *map_obj; + + /* Apply map to smart obj holding nested parts */ + if (ep->nested_smart) map_obj = ep->nested_smart; + else map_obj = mo; + + if (ep->part->type != EDJE_PART_TYPE_SPACER) + { + if (chosen_desc->map.on) + { + static Evas_Map *map = NULL; + + ed->have_mapped_part = EINA_TRUE; + // create map and populate with part geometry + if (!map) map = evas_map_new(4); + + _edje_map_prop_set(map, pf, chosen_desc, ep, mo); + + if (map_obj) + { + eo_do(map_obj, + evas_obj_map_set(map), + evas_obj_map_enable_set(EINA_TRUE)); + } + } + else + { + Eina_Bool ret; + + if (map_obj && eo_do_ret(map_obj, ret, evas_obj_map_enable_get())) + { +#ifdef HAVE_EPHYSICS + if (!ep->nested_smart && !ep->body) + { #endif - } - if (rp2[Rel2Y]) - { - _edje_part_recalc(ed, rp2[Rel2Y], FLAG_Y, NULL); -#ifdef EDJE_CALC_CACHE - if (state2 < rp2[Rel2Y]->state) - state2 = rp2[Rel2Y]->state; + eo_do(map_obj, + evas_obj_map_enable_set(EINA_FALSE), + evas_obj_map_set(NULL)); +#ifdef HAVE_EPHYSICS + } #endif + } } + + /* TIZEN_ONLY(20160920): Add fade_ellipsis feature to TEXTBLOCK, TEXT part. */ + if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK || + ep->part->type == EDJE_PART_TYPE_TEXT) + _edje_text_ellipsize_apply(ed, ep, pf, (Edje_Part_Description_Text*) chosen_desc); + /* END */ } } - if (clip1) - { - _edje_part_recalc(ed, clip1, flags, NULL); - statecl = clip1->state; - } - if (clip2) - { - _edje_part_recalc(ed, clip2, flags, NULL); - if (statecl < clip2->state) - statecl = clip2->state; - } - if (ep->drag) + + if (map_colors_free) _map_colors_free(pf); + +#ifdef HAVE_EPHYSICS + ep->prev_description = chosen_desc; + if (!ep->body) { - if (ep->drag->confine_to) - { - confine_to = ep->drag->confine_to; - _edje_part_recalc(ed, confine_to, flags, NULL); -#ifdef EDJE_CALC_CACHE - statec = confine_to->state; -#endif - } - if (ep->drag->threshold) - { - threshold = ep->drag->threshold; - // We shall not recalculate the threshold position as - // we use it's previous position to assert the threshold - // the one before moving take action. -#ifdef EDJE_CALC_CACHE - statet = threshold->state; #endif - } + ep->x = pf->final.x; + ep->y = pf->final.y; + ep->w = pf->final.w; + ep->h = pf->final.h; +#ifdef HAVE_EPHYSICS } - // if (ep->text.source) _edje_part_recalc(ed, ep->text.source, flags); - // if (ep->text.text_source) _edje_part_recalc(ed, ep->text.text_source, flags); - /* actually calculate now */ - chosen_desc = ep->chosen_description; - if (!chosen_desc) - { - ep->calculating = FLAG_NONE; - ep->calculated |= flags; - return; - } +#endif - pos = ep->description_pos; + ep->calculated |= flags; + ep->calculating = FLAG_NONE; - if ((ep->part->type == EDJE_PART_TYPE_PROXY) && chosen_desc->visible) + if (pf == &lp3) { - int part_id = -1; - - if (ep->param2 && (pos >= FROM_DOUBLE(0.5))) - part_id = ((Edje_Part_Description_Proxy *)ep->param2->description)->proxy.id; - else - part_id = ((Edje_Part_Description_Proxy *)chosen_desc)->proxy.id; + eina_cow_free(_edje_calc_params_map_cow, (const Eina_Cow_Data **)&lp3.map); + lp3.map = NULL; +#ifdef HAVE_EPHYSICS + eina_cow_free(_edje_calc_params_physics_cow, (const Eina_Cow_Data **)&lp3.physics); + lp3.physics = NULL; +#endif + } #ifdef EDJE_CALC_CACHE - Edje_Real_Part *pp; - pp = _edje_real_part_state_get(ed, ep, flags, part_id, NULL); - if (pp && pp->invalidate) proxy_invalidate = EINA_TRUE; + if (ep->calculated == FLAG_XY) + { + ep->state = ed->state; + ep->invalidate = EINA_FALSE; + } #else - _edje_real_part_state_get(ed, ep, flags, part_id, NULL); + eina_cow_free(_edje_calc_params_map_cow, (const Eina_Cow_Data **)&lp1.map); +#ifdef HAVE_EPHYSICS + eina_cow_free(_edje_calc_params_physics_cow, (const Eina_Cow_Data **)&lp1.physics); #endif - } +#endif +} - /* Recalc if needed the map center && light source */ - if (ep->param1.description->map.on) - { - center[0] = _edje_real_part_state_get(ed, ep, flags, ep->param1.description->map.rot.id_center, &statec1); - light[0] = _edje_real_part_state_get(ed, ep, flags, ep->param1.description->map.id_light, &statel1); - if (chosen_desc->map.persp_on) - { - persp[0] = _edje_real_part_state_get(ed, ep, flags, ep->param1.description->map.id_persp, &statep1); - } - } - if (ep->param2 && ep->param2->description->map.on) +/********************************************************************************** + * + * TIZEN_ONLY_FEATURE: ellipsize.marquee, ellipsize.fade for TEXTBLOCK, TEXT part. + * 20160920: Add fade_ellipsis feature to TEXTBLOCK, TEXT part. + * 20160923: introduction of text marquee + * 20170322: fix crash issue when Edje tries to clean up fade object + * 20170427: fix clipper loop issue caused by clipper object for fade + * 20170703: Add ellipsize feature and refactory fade_ellipsis, marquee features. + * + **********************************************************************************/ +#define EDJE_DEFAULT_FADE_IMAGE "edje_default_fade_image.png" +#define LEFT_BORDER 20 +#define RIGHT_BORDER 20 +#define TOP_BORDER 20 +#define BOTTOM_BORDER 20 +#define EDJE_ELLIPSIZE_FADE_SENSITIVITY 4 + +/* moving 1 px for 0.025 sec makes 40 px/sec */ +#define EDJE_TEXT_ELLIPSIZE_MARQUEE_DEFAULT_SEC_PER_PIXEL 0.025 +#define EDJE_TEXT_ELLIPSIZE_MARQUEE_ROLL_GAP 60 + +static Evas_Object * +_edje_text_ellipsize_fade_mask_object_get(Edje_Real_Part *ep) +{ + if (!ep->typedata.text->ellipsize.fade.mask_obj) { - center[1] = _edje_real_part_state_get(ed, ep, flags, ep->param2->description->map.rot.id_center, &statec2); - light[1] = _edje_real_part_state_get(ed, ep, flags, ep->param2->description->map.id_light, &statel2); + Evas_Object *smart_parent; + Evas_Object *mask_obj; + char buf[1024]; + int iw = 0; - if (chosen_desc->map.persp_on) - { - persp[1] = _edje_real_part_state_get(ed, ep, flags, ep->param2->description->map.id_persp, &statep2); - } - } + smart_parent = evas_object_smart_parent_get(ep->object); -#ifndef EDJE_CALC_CACHE - p1 = &lp1; - p1.map = eina_cow_alloc(_edje_calc_params_map_cow); -#ifdef HAVE_EPHYSICS - p1.physics = eina_cow_alloc(_edje_calc_params_physics_cow); -#endif +#if 0 + mask_obj = evas_object_rectangle_add(evas_object_evas_get(ep->object)); + evas_object_color_set(mask_obj, 150, 0, 0, 150); #else - p1 = &ep->param1.p; -#endif + mask_obj = evas_object_image_add(evas_object_evas_get(ep->object)); + snprintf(buf, sizeof(buf), "/usr/share/edje/images/%s", EDJE_DEFAULT_FADE_IMAGE); + evas_object_image_file_set(mask_obj, buf, NULL); - if (ep->param1.description) - { -#ifdef EDJE_CALC_CACHE - if (ed->all_part_change || - ep->invalidate || - (state1 >= ep->param1.state) || - (statec >= ep->param1.state) || - (statet >= ep->param1.state) || - (statec1 >= ep->param1.state) || - (statel1 >= ep->param1.state) || - (statep1 >= ep->param1.state) || - (statecl >= ep->param1.state) || - proxy_invalidate || - state || - ed->need_map_update || - ((ep->part->type == EDJE_PART_TYPE_TEXT || - ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) && - ed->text_part_change)) -#endif - { - _edje_part_recalc_single(ed, ep, ep->param1.description, - chosen_desc, center[0], light[0], - persp[0], rp1[Rel1X], rp1[Rel1Y], - rp1[Rel2X], rp1[Rel2Y], clip1, confine_to, - threshold, p1, mmw, mmh, - pos); -#ifdef EDJE_CALC_CACHE - if (flags == FLAG_XY) ep->param1.state = ed->state; + if (evas_object_image_load_error_get(mask_obj) != EVAS_LOAD_ERROR_NONE) + { + ERR("Error loading fade image from file \"%s\".", buf); + + switch (evas_object_image_load_error_get(mask_obj)) + { + case EVAS_LOAD_ERROR_GENERIC: + ERR("Error type: EVAS_LOAD_ERROR_GENERIC"); + break; + case EVAS_LOAD_ERROR_DOES_NOT_EXIST: + ERR("Error type: EVAS_LOAD_ERROR_DOES_NOT_EXIST"); + break; + case EVAS_LOAD_ERROR_PERMISSION_DENIED: + ERR("Error type: EVAS_LOAD_ERROR_PERMISSION_DENIED"); + break; + case EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED: + ERR("Error type: EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED"); + break; + case EVAS_LOAD_ERROR_CORRUPT_FILE: + ERR("Error type: EVAS_LOAD_ERROR_CORRUPT_FILE"); + break; + case EVAS_LOAD_ERROR_UNKNOWN_FORMAT: + ERR("Error type: EVAS_LOAD_ERROR_UNKNOWN_FORMAT"); + break; + default: + ERR("Error type: ???"); + break; + } + } + + evas_object_image_size_get(mask_obj, &iw, NULL); + evas_object_pass_events_set(mask_obj, 1); + evas_object_pointer_mode_set(mask_obj, EVAS_OBJECT_POINTER_MODE_NOGRAB); + evas_object_image_border_set(mask_obj, LEFT_BORDER, RIGHT_BORDER, TOP_BORDER, BOTTOM_BORDER); + evas_object_image_border_scale_set(mask_obj, 1.0); + evas_object_image_border_center_fill_set(mask_obj, EVAS_BORDER_FILL_DEFAULT); #endif - } + evas_object_smart_member_add(mask_obj, smart_parent); + ep->typedata.text->ellipsize.fade.mask_obj = mask_obj; } - if (ep->param2) - { - int beginning_pos, part_type; - Edje_Calc_Params *p2, *p3; - if (ep->current) - { - const Edje_Calc_Params_Map *map; -#ifdef HAVE_EPHYSICS - const Edje_Calc_Params_Physics *physics; -#endif + return ep->typedata.text->ellipsize.fade.mask_obj; +} - map = p1->map; -#ifdef HAVE_EPHYSICS - physics = p1->physics; -#endif +void +_edje_text_ellipsize_marquee_remove(Edje_Real_Part *ep) +{ + if (!ep || !ep->typedata.text) return; - /* FIXME: except for text, we don't need in that case to recalc p1 at all*/ - memcpy(p1, ep->current, sizeof (Edje_Calc_Params)); + if (ep->typedata.text->ellipsize.marquee.proxy_obj) + { + evas_object_del(ep->typedata.text->ellipsize.marquee.proxy_obj); + ep->typedata.text->ellipsize.marquee.proxy_obj = NULL; + } - p1->map = map; -#ifdef HAVE_EPHYSICS - p1->physics = physics; -#endif - } + if (ep->typedata.text->ellipsize.marquee.animator) + { + ecore_animator_del(ep->typedata.text->ellipsize.marquee.animator); + ep->typedata.text->ellipsize.marquee.animator = NULL; + } - p3 = &lp3; - lp3.map = eina_cow_alloc(_edje_calc_params_map_cow); -#ifdef HAVE_EPHYSICS - lp3.physics = eina_cow_alloc(_edje_calc_params_physics_cow); -#endif + ep->typedata.text->ellipsize.marquee.loop_count = 0; + ep->typedata.text->ellipsize.marquee.distance = 0; +} -#ifndef EDJE_CALC_CACHE - p2 = &lp2; - lp2.map = eina_cow_alloc(_edje_calc_params_map_cow); -#ifdef HAVE_EPHYSICS - lp2.physics = eina_cow_alloc(_edje_calc_params_physics_cow); -#endif -#else - p2 = &ep->param2->p; +void +_edje_text_ellipsize_fade_remove(Edje_Real_Part *ep) +{ + if (!ep || !ep->typedata.text) return; - if (ed->all_part_change || - ep->invalidate || - (state2 >= ep->param2->state) || - (statec >= ep->param2->state) || - (statet >= ep->param2->state) || - (statec2 >= ep->param2->state) || - (statel2 >= ep->param2->state) || - (statep2 >= ep->param2->state) || - (statecl >= ep->param2->state) || - proxy_invalidate || - state || - ed->need_map_update || - ((ep->part->type == EDJE_PART_TYPE_TEXT || - ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) && - ed->text_part_change)) -#endif - { - _edje_part_recalc_single(ed, ep, ep->param2->description, - chosen_desc, center[1], light[1], - persp[1], rp2[Rel1X], rp2[Rel1Y], - rp2[Rel2X], rp2[Rel2Y], clip2, confine_to, - threshold, p2, mmw, mmh, - pos); -#ifdef EDJE_CALC_CACHE - if (flags == FLAG_XY) ep->param2->state = ed->state; -#endif - } + if (ep->typedata.text->ellipsize.fade.animator) + { + ecore_animator_del(ep->typedata.text->ellipsize.fade.animator); + ep->typedata.text->ellipsize.fade.animator = NULL; + } - pos2 = pos; - if (pos2 < ZERO) pos2 = ZERO; - else if (pos2 > FROM_INT(1)) - pos2 = FROM_INT(1); - beginning_pos = (pos < FROM_DOUBLE(0.5)); - part_type = ep->part->type; + if (ep->typedata.text->ellipsize.fade.mask_obj) + { + evas_object_del(ep->typedata.text->ellipsize.fade.mask_obj); + ep->typedata.text->ellipsize.fade.mask_obj = NULL; + } +} + +/* TIZEN_ONLY(20170322): fix crash issue when Edje tries to clean up fade object */ +void +_edje_text_ellipsize_remove(Edje_Real_Part *ep) +{ + if (!ep || !ep->typedata.text) return; - /* visible is special */ - if ((p1->visible) && (!p2->visible)) - p3->visible = (pos != FROM_INT(1)); - else if ((!p1->visible) && (p2->visible)) - p3->visible = (pos != ZERO); - else - p3->visible = p1->visible; + _edje_text_ellipsize_marquee_remove(ep); + _edje_text_ellipsize_fade_remove(ep); - /* clip_to will behave a bit like visible */ - if (pos == ZERO) - p3->clip_to = p1->clip_to; - else if (pos == FROM_INT(1)) - p3->clip_to = p2->clip_to; - else if (!p1->clip_to) - p3->clip_to = p2->clip_to; - else - p3->clip_to = p1->clip_to; + if (ep->typedata.text->ellipsize.clipper_obj) + { + evas_object_del(ep->typedata.text->ellipsize.clipper_obj); + ep->typedata.text->ellipsize.clipper_obj = NULL; + } +} +/* END */ - p3->smooth = (beginning_pos) ? p1->smooth : p2->smooth; +/* Get alignment of ellipsize according to ellipsize.align and Text/Textblock's status */ +static void +_edje_text_ellipsize_align_get(Edje_Real_Part *ep, Edje_Calc_Params *pf, Edje_Part_Description_Text *chosen_desc, double *halign, double *valign) +{ + Evas_BiDi_Direction bidi_dir; + Edje_Text_Ellipsize_Align ellip_align; + Evas_Coord tw, th; + double valign_ret = -1.0; + double halign_ret = -1.0; - /* FIXME: do x and y separately base on flag */ + if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) + { + Evas_Textblock_Cursor *cur; - p3->final.x = INTP(p1->final.x, p2->final.x, pos); - p3->final.y = INTP(p1->final.y, p2->final.y, pos); - p3->final.w = INTP(p1->final.w, p2->final.w, pos); - p3->final.h = INTP(p1->final.h, p2->final.h, pos); + cur = evas_object_textblock_cursor_new(ep->object); - p3->eval.x = FFP(p1->eval.x, p2->eval.x, pos); - p3->eval.y = FFP(p1->eval.y, p2->eval.y, pos); - p3->eval.w = FFP(p1->eval.w, p2->eval.w, pos); - p3->eval.h = FFP(p1->eval.h, p2->eval.h, pos); + bidi_dir = evas_textblock_cursor_paragraph_direction_get(cur); + evas_object_textblock_size_formatted_get(ep->object, &tw, &th); - p3->req.x = INTP(p1->req.x, p2->req.x, pos); - p3->req.y = INTP(p1->req.y, p2->req.y, pos); - p3->req.w = INTP(p1->req.w, p2->req.w, pos); - p3->req.h = INTP(p1->req.h, p2->req.h, pos); + evas_textblock_cursor_free(cur); + } + else + { + bidi_dir = evas_object_text_direction_get(ep->object); + tw = evas_object_text_horiz_advance_get(ep->object); + th = evas_object_text_vert_advance_get(ep->object); + } - _edje_part_pixel_adjust(ed, ep, p3); + if (chosen_desc->text.fade_ellipsis == 2.0) + chosen_desc->text.ellipsize.align = EDJE_TEXT_ELLIPSIZE_ALIGN_END; + else if (chosen_desc->text.fade_ellipsis == 1.0) + chosen_desc->text.ellipsize.align = EDJE_TEXT_ELLIPSIZE_ALIGN_START; - if (ep->part->dragable.x) + ellip_align = chosen_desc->text.ellipsize.align; + + /* Handle NORMAL ellipsis. It considers difference of TEXTBLOCK and TEXT. + * Also, it considers a logic inside of each type of object with the given ellipsis value. + */ + if (chosen_desc->text.ellipsize.mode == EDJE_TEXT_ELLIPSIZE_MODE_NORMAL) + { + /* variable for improving readability */ + double text_ellipsis_end; + double text_ellipsis_start; + + if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) { - p3->req_drag.x = INTP(p1->req_drag.x, p2->req_drag.x, pos); - p3->req_drag.w = INTP(p1->req_drag.w, p2->req_drag.w, pos); + text_ellipsis_end = 1.0; + text_ellipsis_start = 0.0; } - if (ep->part->dragable.y) + else { - p3->req_drag.y = INTP(p1->req_drag.y, p2->req_drag.y, pos); - p3->req_drag.h = INTP(p1->req_drag.h, p2->req_drag.h, pos); + text_ellipsis_end = 0.0; + text_ellipsis_start = 1.0; } - p3->color.r = INTP(p1->color.r, p2->color.r, pos2); - p3->color.g = INTP(p1->color.g, p2->color.g, pos2); - p3->color.b = INTP(p1->color.b, p2->color.b, pos2); - p3->color.a = INTP(p1->color.a, p2->color.a, pos2); + switch (ellip_align) + { + case EDJE_TEXT_ELLIPSIZE_ALIGN_LEFT: + if (bidi_dir != EVAS_BIDI_DIRECTION_RTL) + halign_ret = text_ellipsis_start; + else + halign_ret = text_ellipsis_end; + break; + case EDJE_TEXT_ELLIPSIZE_ALIGN_RIGHT: + if (bidi_dir != EVAS_BIDI_DIRECTION_RTL) + halign_ret = text_ellipsis_end; + else + halign_ret = text_ellipsis_start; + break; + case EDJE_TEXT_ELLIPSIZE_ALIGN_START: + halign_ret = text_ellipsis_start; + break; + case EDJE_TEXT_ELLIPSIZE_ALIGN_END: + halign_ret = text_ellipsis_end; + break; + case EDJE_TEXT_ELLIPSIZE_ALIGN_LOCALE: + if (evas_language_direction_get() == EVAS_BIDI_DIRECTION_RTL) + { + if (bidi_dir == EVAS_BIDI_DIRECTION_RTL) + halign_ret = text_ellipsis_end; + else + halign_ret = text_ellipsis_start; + } + else + { + if (bidi_dir == EVAS_BIDI_DIRECTION_RTL) + halign_ret = text_ellipsis_start; + else + halign_ret = text_ellipsis_end; + } + break; + default: + halign_ret = -1.0; + } + } + else + { + /* variable for improving readability */ + double text_ellipsis_left; + double text_ellipsis_right; -#ifdef HAVE_EPHYSICS - if (ep->part->physics_body || ep->body) + text_ellipsis_left = 0.0; + text_ellipsis_right = 1.0; + + switch (ellip_align) { - EINA_COW_CALC_PHYSICS_BEGIN(p3, p3_write) - { - p3_write->mass = TO_DOUBLE(FINTP(p1->physics->mass, p2->physics->mass, - pos)); - p3_write->restitution = TO_DOUBLE(FINTP(p1->physics->restitution, - p2->physics->restitution, - pos)); - p3_write->friction = TO_DOUBLE(FINTP(p1->physics->friction, - p2->physics->friction, pos)); - p3_write->density = TO_DOUBLE(FINTP(p1->physics->density, - p2->physics->density, pos)); - p3_write->hardness = TO_DOUBLE(FINTP(p1->physics->hardness, - p2->physics->hardness, pos)); + case EDJE_TEXT_ELLIPSIZE_ALIGN_LEFT: + halign_ret = text_ellipsis_left; + break; + case EDJE_TEXT_ELLIPSIZE_ALIGN_RIGHT: + halign_ret = text_ellipsis_right; + break; + case EDJE_TEXT_ELLIPSIZE_ALIGN_START: + if (bidi_dir != EVAS_BIDI_DIRECTION_RTL) + halign_ret = text_ellipsis_left; + else + halign_ret = text_ellipsis_right; + break; + case EDJE_TEXT_ELLIPSIZE_ALIGN_END: + if (bidi_dir != EVAS_BIDI_DIRECTION_RTL) + halign_ret = text_ellipsis_right; + else + halign_ret = text_ellipsis_left; + break; + case EDJE_TEXT_ELLIPSIZE_ALIGN_LOCALE: + if (evas_language_direction_get() == EVAS_BIDI_DIRECTION_RTL) + halign_ret = text_ellipsis_left; + else + halign_ret = text_ellipsis_right; + break; + default: + halign_ret = -1.0; + } + } - p3_write->damping.linear = TO_DOUBLE(FINTP(p1->physics->damping.linear, - p2->physics->damping.linear, pos)); - p3_write->damping.angular = TO_DOUBLE(FINTP(p1->physics->damping.angular, - p2->physics->damping.angular, pos)); + if ((ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) && + (th > ep->h)) + { + /* variable for improving readability */ + double text_ellipsis_top; + double text_ellipsis_bottom; - p3_write->sleep.linear = TO_DOUBLE(FINTP(p1->physics->sleep.linear, - p2->physics->sleep.linear, pos)); - p3_write->sleep.angular = TO_DOUBLE(FINTP(p1->physics->sleep.angular, - p2->physics->sleep.angular, pos)); + text_ellipsis_top = 0.0; + text_ellipsis_bottom = 1.0; - p3_write->z = INTP(p1->physics->z, p2->physics->z, pos); - p3_write->depth = INTP(p1->physics->depth, p2->physics->depth, pos); + /* LEFT, RIGHT, LOCALE are meaningless for vertical direction. + * So, LEFT, RIGHT, LOCALE will work just like END (default). + * Only START, END will work. */ + switch (ellip_align) + { + case EDJE_TEXT_ELLIPSIZE_ALIGN_LEFT: + valign_ret = text_ellipsis_bottom; + break; + case EDJE_TEXT_ELLIPSIZE_ALIGN_RIGHT: + valign_ret = text_ellipsis_bottom; + break; + case EDJE_TEXT_ELLIPSIZE_ALIGN_START: + valign_ret = text_ellipsis_top; + break; + case EDJE_TEXT_ELLIPSIZE_ALIGN_END: + valign_ret = text_ellipsis_bottom; + break; + case EDJE_TEXT_ELLIPSIZE_ALIGN_LOCALE: + valign_ret = text_ellipsis_bottom; + break; + default: + valign_ret = -1.0; + } + } - if ((p1->physics->ignore_part_pos) && (p2->physics->ignore_part_pos)) - p3_write->ignore_part_pos = 1; - else - p3_write->ignore_part_pos = 0; + if (halign) + *halign = halign_ret; - if ((p1->physics->material) && (p2->physics->material)) - p3_write->material = p1->physics->material; - else - p3_write->material = EPHYSICS_BODY_MATERIAL_CUSTOM; + if (valign) + *valign = valign_ret; +} - p3_write->light_on = p1->physics->light_on || p2->physics->light_on; - p3_write->backcull = p1->physics->backcull || p2->physics->backcull; +static Evas_Object * +_edje_text_ellipsize_marquee_proxy_object_get(Edje_Real_Part *ep) +{ + if (!ep->typedata.text->ellipsize.marquee.proxy_obj) + { + Evas_Object *p_obj; + Evas_Object *smart_parent; + double scale = evas_object_scale_get(ep->object); + int pr, pg, pb, pa; - p3_write->mov_freedom.lin.x = p1->physics->mov_freedom.lin.x || - p2->physics->mov_freedom.lin.x; - p3_write->mov_freedom.lin.y = p1->physics->mov_freedom.lin.y || - p2->physics->mov_freedom.lin.y; - p3_write->mov_freedom.lin.z = p1->physics->mov_freedom.lin.z || - p2->physics->mov_freedom.lin.z; - p3_write->mov_freedom.ang.x = p1->physics->mov_freedom.ang.x || - p2->physics->mov_freedom.ang.x; - p3_write->mov_freedom.ang.y = p1->physics->mov_freedom.ang.y || - p2->physics->mov_freedom.ang.y; - p3_write->mov_freedom.ang.z = p1->physics->mov_freedom.ang.z || - p2->physics->mov_freedom.ang.z; - } - EINA_COW_CALC_PHYSICS_END(p3, p3_write); - } -#endif + smart_parent = evas_object_smart_parent_get(ep->object); + evas_object_color_get(ep->object, &pr, &pg, &pb, &pa); - switch (part_type) + if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) { - case EDJE_PART_TYPE_IMAGE: - p3->type.common.spec.image.l = INTP(p1->type.common.spec.image.l, p2->type.common.spec.image.l, pos); - p3->type.common.spec.image.r = INTP(p1->type.common.spec.image.r, p2->type.common.spec.image.r, pos); - p3->type.common.spec.image.t = INTP(p1->type.common.spec.image.t, p2->type.common.spec.image.t, pos); - p3->type.common.spec.image.b = INTP(p1->type.common.spec.image.b, p2->type.common.spec.image.b, pos); - p3->type.common.spec.image.border_scale_by = FFP(p1->type.common.spec.image.border_scale_by, p2->type.common.spec.image.border_scale_by, pos); + const Evas_Textblock_Style *st = evas_object_textblock_style_get(ep->object); - case EDJE_PART_TYPE_PROXY: - p3->type.common.fill.x = INTP(p1->type.common.fill.x, p2->type.common.fill.x, pos); - p3->type.common.fill.y = INTP(p1->type.common.fill.y, p2->type.common.fill.y, pos); - p3->type.common.fill.w = INTP(p1->type.common.fill.w, p2->type.common.fill.w, pos); - p3->type.common.fill.h = INTP(p1->type.common.fill.h, p2->type.common.fill.h, pos); - break; + p_obj = evas_object_textblock_add(evas_object_evas_get(ep->object)); + evas_object_textblock_style_set(p_obj, st); + evas_object_textblock_text_markup_set(p_obj, ep->typedata.text->text); + } + else + { + const char *font = NULL; + int font_size = 0; + Evas_Text_Style_Type style; + int tr, tg, tb, ta; - case EDJE_PART_TYPE_TEXT: - p3->type.text.size = INTP(p1->type.text.size, p2->type.text.size, pos); + evas_object_text_font_get(ep->object, &font, &font_size); + style = evas_object_text_style_get(ep->object); - /* no break as we share code with the TEXTBLOCK type here. Intended fall-through */ - case EDJE_PART_TYPE_TEXTBLOCK: - p3->type.text.color2.r = INTP(p1->type.text.color2.r, p2->type.text.color2.r, pos2); - p3->type.text.color2.g = INTP(p1->type.text.color2.g, p2->type.text.color2.g, pos2); - p3->type.text.color2.b = INTP(p1->type.text.color2.b, p2->type.text.color2.b, pos2); - p3->type.text.color2.a = INTP(p1->type.text.color2.a, p2->type.text.color2.a, pos2); + p_obj = evas_object_text_add(evas_object_evas_get(ep->object)); + evas_object_text_font_set(p_obj, font, font_size); + evas_object_text_style_set(p_obj, style); - p3->type.text.color3.r = INTP(p1->type.text.color3.r, p2->type.text.color3.r, pos2); - p3->type.text.color3.g = INTP(p1->type.text.color3.g, p2->type.text.color3.g, pos2); - p3->type.text.color3.b = INTP(p1->type.text.color3.b, p2->type.text.color3.b, pos2); - p3->type.text.color3.a = INTP(p1->type.text.color3.a, p2->type.text.color3.a, pos2); + evas_object_text_outline_color_get(ep->object, &tr, &tg, &tb, &ta); + evas_object_text_outline_color_set(p_obj, tr, tg, tb, ta); + evas_object_text_shadow_color_get(ep->object, &tr, &tg, &tb, &ta); + evas_object_text_shadow_color_set(p_obj, tr, tg, tb, ta); + evas_object_text_glow_color_get(ep->object, &tr, &tg, &tb, &ta); + evas_object_text_glow_color_set(p_obj, tr, tg, tb, ta); + evas_object_text_glow2_color_get(ep->object, &tr, &tg, &tb, &ta); + evas_object_text_glow2_color_set(p_obj, tr, tg, tb, ta); - p3->type.text.align.x = FFP(p1->type.text.align.x, p2->type.text.align.x, pos); - p3->type.text.align.y = FFP(p1->type.text.align.y, p2->type.text.align.y, pos); - p3->type.text.ellipsis = TO_DOUBLE(FINTP(p1->type.text.ellipsis, p2->type.text.ellipsis, pos2)); - break; + evas_object_text_text_set(p_obj, ep->typedata.text->text); } - /* mapped is a special case like visible */ - if ((p1->mapped) && (!p2->mapped)) - p3->mapped = (pos != FROM_INT(1)); - else if ((!p1->mapped) && (p2->mapped)) - p3->mapped = (pos != ZERO); + evas_object_smart_member_add(p_obj, smart_parent); + evas_object_color_set(p_obj, pr, pg, pb, pa); + + if (ep->typedata.text->ellipsize.is_fade) + evas_object_clip_set(p_obj, ep->typedata.text->ellipsize.fade.mask_obj); else - p3->mapped = p1->mapped; + evas_object_clip_set(p_obj, ep->typedata.text->ellipsize.clipper_obj); - p3->persp_on = p3->mapped ? p1->persp_on | p2->persp_on : 0; - p3->lighted = p3->mapped ? p1->lighted | p2->lighted : 0; - if (p3->mapped) - { - EINA_COW_CALC_MAP_BEGIN(p3, p3_write) - { - p3_write->center.x = INTP(p1->map->center.x, p2->map->center.x, pos); - p3_write->center.y = INTP(p1->map->center.y, p2->map->center.y, pos); - p3_write->center.z = INTP(p1->map->center.z, p2->map->center.z, pos); - p3_write->rotation.x = FFP(p1->map->rotation.x, p2->map->rotation.x, pos); - p3_write->rotation.y = FFP(p1->map->rotation.y, p2->map->rotation.y, pos); - p3_write->rotation.z = FFP(p1->map->rotation.z, p2->map->rotation.z, pos); - p3_write->zoom.x = FFP(p1->map->zoom.x, p2->map->zoom.x, pos); - p3_write->zoom.y = FFP(p1->map->zoom.y, p2->map->zoom.y, pos); + evas_object_scale_set(p_obj, scale); + ep->typedata.text->ellipsize.marquee.proxy_obj = p_obj; + } + + return ep->typedata.text->ellipsize.marquee.proxy_obj; +} + +static Eina_Bool +_edje_text_ellipsize_fade_animator_cb(void *data) +{ + Edje_Real_Part *ep = (Edje_Real_Part *)data; + Evas_Object *mask_obj = _edje_text_ellipsize_fade_mask_object_get(ep); + int x, y, w, h; + + if (!mask_obj) + { + ep->typedata.text->ellipsize.fade.animator = NULL; + return ECORE_CALLBACK_CANCEL; + } + + evas_object_geometry_get(mask_obj, &x, &y, &w, &h); + + if ((x == ep->typedata.text->ellipsize.fade.x) && + (y == ep->typedata.text->ellipsize.fade.y) && + (w == ep->typedata.text->ellipsize.fade.w) && + (h == ep->typedata.text->ellipsize.fade.h)) + { + ep->typedata.text->ellipsize.fade.animator = NULL; + return ECORE_CALLBACK_DONE; + } + + if (x < ep->typedata.text->ellipsize.fade.x) + { + x += EDJE_ELLIPSIZE_FADE_SENSITIVITY; + if (x > ep->typedata.text->ellipsize.fade.x) + x = ep->typedata.text->ellipsize.fade.x; + } + else if (x > ep->typedata.text->ellipsize.fade.x) + { + x -= EDJE_ELLIPSIZE_FADE_SENSITIVITY; + if (x < ep->typedata.text->ellipsize.fade.x) + x = ep->typedata.text->ellipsize.fade.x; + } + + if (y < ep->typedata.text->ellipsize.fade.y) + { + y += EDJE_ELLIPSIZE_FADE_SENSITIVITY; + if (y > ep->typedata.text->ellipsize.fade.y) + y = ep->typedata.text->ellipsize.fade.y; + } + else if (y > ep->typedata.text->ellipsize.fade.y) + { + y -= EDJE_ELLIPSIZE_FADE_SENSITIVITY; + if (y < ep->typedata.text->ellipsize.fade.y) + y = ep->typedata.text->ellipsize.fade.y; + } + + if (w < ep->typedata.text->ellipsize.fade.w) + { + w += EDJE_ELLIPSIZE_FADE_SENSITIVITY; + if (w > ep->typedata.text->ellipsize.fade.w) + w = ep->typedata.text->ellipsize.fade.w; + } + else if (w > ep->typedata.text->ellipsize.fade.w) + { + w -= EDJE_ELLIPSIZE_FADE_SENSITIVITY; + if (w < ep->typedata.text->ellipsize.fade.w) + w = ep->typedata.text->ellipsize.fade.w; + } + + if (h < ep->typedata.text->ellipsize.fade.h) + { + h += EDJE_ELLIPSIZE_FADE_SENSITIVITY; + if (h > ep->typedata.text->ellipsize.fade.h) + h = ep->typedata.text->ellipsize.fade.h; + } + else if (h > ep->typedata.text->ellipsize.fade.h) + { + h -= EDJE_ELLIPSIZE_FADE_SENSITIVITY; + if (h < ep->typedata.text->ellipsize.fade.h) + h = ep->typedata.text->ellipsize.fade.h; + } + + evas_object_resize(mask_obj, w, h); + evas_object_image_fill_set(mask_obj, 0, 0, w, h); + evas_object_move(mask_obj, x, y); + + return ECORE_CALLBACK_RENEW; +} + +void +_edje_text_ellipsize_fade_update(Edje_Real_Part *ep, Eina_Bool anim) +{ + Evas_Object *mask_obj = _edje_text_ellipsize_fade_mask_object_get(ep); + int left_fade_off_x, right_fade_off_x, left_fade_x, right_fade_x; + int top_fade_off_y, bottom_fade_off_y, top_fade_y, bottom_fade_y; + int tx, ty, tw, th; + int cx, cy, cw, ch; -#define MIX(P1, P2, P3, pos, info) \ - P3->info = P1->map->info + TO_INT(SCALE(pos, P2->map->info - P1->map->info)); - map_colors_free = _map_colors_interp(p1, p2, p3_write, pos); + evas_object_geometry_get(ep->typedata.text->ellipsize.clipper_obj, &cx, &cy, &cw, &ch); - if (p1->lighted && p2->lighted) - { - MIX(p1, p2, p3_write, pos, light.x); - MIX(p1, p2, p3_write, pos, light.y); - MIX(p1, p2, p3_write, pos, light.z); - MIX(p1, p2, p3_write, pos, light.r); - MIX(p1, p2, p3_write, pos, light.g); - MIX(p1, p2, p3_write, pos, light.b); - MIX(p1, p2, p3_write, pos, light.ar); - MIX(p1, p2, p3_write, pos, light.ag); - MIX(p1, p2, p3_write, pos, light.ab); - } - else if (p1->lighted) - { - memcpy(&p3_write->light, &p1->map->light, sizeof (p1->map->light)); - } - else if (p2->lighted) - { - memcpy(&p3_write->light, &p2->map->light, sizeof (p2->map->light)); - } + left_fade_x = left_fade_off_x = cx - LEFT_BORDER; + right_fade_x = right_fade_off_x = cx + cw + RIGHT_BORDER; + top_fade_y = top_fade_off_y = cy - TOP_BORDER; + bottom_fade_y = bottom_fade_off_y = cy + ch + BOTTOM_BORDER; - if (p1->persp_on && p2->persp_on) - { - MIX(p1, p2, p3_write, pos, persp.x); - MIX(p1, p2, p3_write, pos, persp.y); - MIX(p1, p2, p3_write, pos, persp.z); - MIX(p1, p2, p3_write, pos, persp.focal); - } - else if (p1->persp_on) - { - memcpy(&p3_write->persp, &p1->map->persp, sizeof (p1->map->persp)); - } - else if (p2->persp_on) - { - memcpy(&p3_write->persp, &p2->map->persp, sizeof (p2->map->persp)); - } - } - EINA_COW_CALC_MAP_END(p3, p3_write); - } + evas_object_geometry_get(ep->object, &tx, &ty, NULL, NULL); + tw = ep->typedata.text->ellipsize.text_w; + th = ep->typedata.text->ellipsize.text_h; -#ifndef EDJE_CALC_CACHE - eina_cow_free(_edje_calc_params_map_cow, (const Eina_Cow_Data **)&lp2.map); -#ifdef HAVE_EPHYSICS - eina_cow_free(_edje_calc_params_physics_cow, (const Eina_Cow_Data **)&lp2.physics); -#endif -#endif - pf = p3; + /* Calculate position and size of fade mask object */ + if ((tx < cx) && (tx + tw > cx)) + { + if (left_fade_x < left_fade_off_x + (cx - tx) * EDJE_ELLIPSIZE_FADE_SENSITIVITY) + left_fade_x = left_fade_off_x + (cx - tx) * EDJE_ELLIPSIZE_FADE_SENSITIVITY; + if (left_fade_x > cx) + left_fade_x = cx; } - else + + if ((tx < cx + cw) && (tx + tw > cx + cw)) { - pf = p1; + if (right_fade_x > right_fade_off_x - ((tx + tw) - (cx + cw)) * EDJE_ELLIPSIZE_FADE_SENSITIVITY) + right_fade_x = right_fade_off_x - ((tx + tw) - (cx + cw)) * EDJE_ELLIPSIZE_FADE_SENSITIVITY; + if (right_fade_x < cx + cw) + right_fade_x = cx + cw; } - if (!pf->persp_on && chosen_desc->map.persp_on) + if ((ty < cy) && (ty + th > cy)) { - if (ed->persp) - { - EINA_COW_CALC_MAP_BEGIN(pf, pf_write) - { - pf_write->persp.x = ed->persp->px; - pf_write->persp.y = ed->persp->py; - pf_write->persp.z = ed->persp->z0; - pf_write->persp.focal = ed->persp->foc; - } - EINA_COW_CALC_MAP_END(pf, pf_write); - } - else - { - const Edje_Perspective *ps; + if (top_fade_y < top_fade_off_y + (cy - ty) * EDJE_ELLIPSIZE_FADE_SENSITIVITY) + top_fade_y = top_fade_off_y + (cy - ty) * EDJE_ELLIPSIZE_FADE_SENSITIVITY; + if (top_fade_y > cy) + top_fade_y = cy; + } - // fixme: a tad inefficient as this is a has lookup - ps = edje_object_perspective_get(ed->obj); - if (!ps) - ps = edje_evas_global_perspective_get(evas_object_evas_get(ed->obj)); - EINA_COW_CALC_MAP_BEGIN(pf, pf_write) - { - if (ps) - { - pf_write->persp.x = ps->px; - pf_write->persp.y = ps->py; - pf_write->persp.z = ps->z0; - pf_write->persp.focal = ps->foc; - } - else - { - pf_write->persp.x = ed->x + (ed->w / 2); - pf_write->persp.y = ed->y + (ed->h / 2); - pf_write->persp.z = 0; - pf_write->persp.focal = 1000; - } - } - EINA_COW_CALC_MAP_END(pf, pf_write); - } + if ((ty < cy + ch) && (ty + th > cy + ch)) + { + if (bottom_fade_y > bottom_fade_off_y - ((ty + th) - (cy + ch)) * EDJE_ELLIPSIZE_FADE_SENSITIVITY) + bottom_fade_y = bottom_fade_off_y - ((ty + th) - (cy + ch)) * EDJE_ELLIPSIZE_FADE_SENSITIVITY; + if (bottom_fade_y < cy + ch) + bottom_fade_y = cy + ch; } - if (state) + if (ep->typedata.text->ellipsize.marquee.proxy_obj && + evas_object_visible_get(ep->typedata.text->ellipsize.marquee.proxy_obj)) { - const Edje_Calc_Params_Map *map; -#ifdef HAVE_EPHYSICS - const Edje_Calc_Params_Physics *physics; -#endif + evas_object_geometry_get(ep->typedata.text->ellipsize.marquee.proxy_obj, + &tx, &ty, NULL, NULL); - map = state->map; -#ifdef HAVE_EPHYSICS - physics = state->physics; -#endif + if ((tx < cx) && (tx + tw > cx)) + { + if (left_fade_x < left_fade_off_x + (cx - tx) * EDJE_ELLIPSIZE_FADE_SENSITIVITY) + left_fade_x = left_fade_off_x + (cx - tx) * EDJE_ELLIPSIZE_FADE_SENSITIVITY; + if (left_fade_x > cx) + left_fade_x = cx; + } - memcpy(state, pf, sizeof (Edje_Calc_Params)); + if ((tx < cx + cw) && (tx + tw > cx + cw)) + { + if (right_fade_x > right_fade_off_x - ((tx + tw) - (cx + cw)) * EDJE_ELLIPSIZE_FADE_SENSITIVITY) + right_fade_x = right_fade_off_x - ((tx + tw) - (cx + cw)) * EDJE_ELLIPSIZE_FADE_SENSITIVITY; + if (right_fade_x < cx + cw) + right_fade_x = cx + cw; + } - state->map = map; -#ifdef HAVE_EPHYSICS - state->physics = physics; -#endif - eina_cow_memcpy(_edje_calc_params_map_cow, (const Eina_Cow_Data **)&state->map, pf->map); -#ifdef HAVE_EPHYSICS - eina_cow_memcpy(_edje_calc_params_physics_cow, (const Eina_Cow_Data **)&state->physics, pf->physics); -#endif + if ((ty < cy) && (ty + th > cy)) + { + if (top_fade_y < top_fade_off_y + (cy - ty) * EDJE_ELLIPSIZE_FADE_SENSITIVITY) + top_fade_y = top_fade_off_y + (cy - ty) * EDJE_ELLIPSIZE_FADE_SENSITIVITY; + if (top_fade_y > cy) + top_fade_y = cy; + } + + if ((ty < cy + ch) && (ty + th > cy + ch)) + { + if (bottom_fade_y > bottom_fade_off_y - ((ty + th) - (cy + ch)) * EDJE_ELLIPSIZE_FADE_SENSITIVITY) + bottom_fade_y = bottom_fade_off_y - ((ty + th) - (cy + ch)) * EDJE_ELLIPSIZE_FADE_SENSITIVITY; + if (bottom_fade_y < cy + ch) + bottom_fade_y = cy + ch; + } } - ep->req = pf->req; + ep->typedata.text->ellipsize.fade.x = left_fade_x; + ep->typedata.text->ellipsize.fade.y = top_fade_y; + ep->typedata.text->ellipsize.fade.w = right_fade_x - left_fade_x; + ep->typedata.text->ellipsize.fade.h = bottom_fade_y - top_fade_y; - if (ep->drag && ep->drag->need_reset) + if (anim) { - FLOAT_T dx, dy; - - dx = ZERO; - dy = ZERO; - _edje_part_dragable_calc(ed, ep, &dx, &dy); - ep->drag->x = dx; - ep->drag->y = dy; - ep->drag->tmp.x = 0; - ep->drag->tmp.y = 0; - ep->drag->need_reset = 0; + if (!ep->typedata.text->ellipsize.fade.animator) + ep->typedata.text->ellipsize.fade.animator = ecore_animator_add(_edje_text_ellipsize_fade_animator_cb, ep); } - if (!ed->calc_only) + else { - Evas_Object *mo; - - /* Common move, resize and color_set for all part. */ - switch (ep->part->type) + if (ep->typedata.text->ellipsize.fade.animator) { - case EDJE_PART_TYPE_IMAGE: - { - Edje_Part_Description_Image *img_desc = (Edje_Part_Description_Image *)chosen_desc; + ecore_animator_del(ep->typedata.text->ellipsize.fade.animator); + ep->typedata.text->ellipsize.fade.animator = NULL; + } - evas_object_image_scale_hint_set(ep->object, - img_desc->image.scale_hint); - /* No break here as we share the rest of the code for all types. Intended fall-through*/ - } + evas_object_resize(mask_obj, + ep->typedata.text->ellipsize.fade.w, + ep->typedata.text->ellipsize.fade.h); + evas_object_image_fill_set(mask_obj, 0, 0, + ep->typedata.text->ellipsize.fade.w, + ep->typedata.text->ellipsize.fade.h); + evas_object_move(mask_obj, + ep->typedata.text->ellipsize.fade.x, + ep->typedata.text->ellipsize.fade.y); + } +} - case EDJE_PART_TYPE_PROXY: - case EDJE_PART_TYPE_RECTANGLE: - case EDJE_PART_TYPE_TEXTBLOCK: - case EDJE_PART_TYPE_BOX: - case EDJE_PART_TYPE_TABLE: - case EDJE_PART_TYPE_SNAPSHOT: - case EDJE_PART_TYPE_VECTOR: - evas_object_color_set(ep->object, - (pf->color.r * pf->color.a) / 255, - (pf->color.g * pf->color.a) / 255, - (pf->color.b * pf->color.a) / 255, - pf->color.a); +static Eina_Bool +_edje_text_ellipsize_marquee_animator_cb(void *data) +{ + double cur_time; + double elapsed_time; + Edje_Real_Part *ep = (Edje_Real_Part *)data; + Edje_Part_Description_Text *chosen_desc = (Edje_Part_Description_Text *)ep->chosen_description; + Evas_Object *clipper_obj = ep->typedata.text->ellipsize.clipper_obj; + Evas_Coord_Rectangle text_cur_area; + Evas_Coord_Rectangle clipper_area; + /* TODO: roll_gap should be controlled by edc developers? */ + double time_sec_per_pixel = ep->typedata.text->ellipsize.marquee.sec_per_pixel; + int roll_gap = EDJE_TEXT_ELLIPSIZE_MARQUEE_ROLL_GAP; + int loop_jump_from_pos = 0; + int loop_jump_to_pos = 0; + int distance_per_loop = 0; + int move_pixel = 0; + Eina_Bool text_marquee_top_left; + Eina_Bool text_marquee_vertical; -#ifdef HAVE_EPHYSICS -/* body attributes should be updated for invisible objects */ - if (!ep->part->physics_body) - { - if (!pf->visible) - { - evas_object_hide(ep->object); - break; - } - evas_object_show(ep->object); - } - else if (!pf->visible) - { - Evas_Object *face_obj; - Eina_List *l; + evas_object_geometry_get(ep->object, &text_cur_area.x, &text_cur_area.y, + &text_cur_area.w, &text_cur_area.h); - EINA_LIST_FOREACH(ep->body_faces, l, face_obj) - evas_object_hide(face_obj); - evas_object_hide(ep->object); - } -#else - if (!pf->visible) - { - evas_object_hide(ep->object); - break; - } - evas_object_show(ep->object); + if ((text_cur_area.w != ep->typedata.text->ellipsize.text_w) || + (text_cur_area.h != ep->typedata.text->ellipsize.text_h)) + { + text_cur_area.w = ep->typedata.text->ellipsize.text_w; + text_cur_area.h = ep->typedata.text->ellipsize.text_h; + evas_object_resize(ep->object, text_cur_area.w, text_cur_area.h); + } -#endif - /* move and resize are needed for all previous object => no break here. */ - case EDJE_PART_TYPE_SWALLOW: - case EDJE_PART_TYPE_GROUP: - case EDJE_PART_TYPE_EXTERNAL: - /* visibility and color have no meaning on SWALLOW and GROUP part. */ -#ifdef HAVE_EPHYSICS - eo_do(ep->object, - efl_gfx_size_set(pf->final.w, pf->final.h)); - if ((ep->part->physics_body) && (!ep->body)) - { - if (_edje_physics_world_geometry_check(ed->world)) - { - _edje_physics_body_add(ed, ep, ed->world); - _edje_physics_body_props_update(ed, ep, pf, EINA_TRUE); - } - } - else if (ep->body) - { - if (((ep->prev_description) && - (chosen_desc != ep->prev_description)) || - (pf != p1)) - _edje_physics_body_props_update(ed, ep, pf, !pf->physics->ignore_part_pos); - } - else - eo_do(ep->object, - efl_gfx_position_set(ed->x + pf->final.x, ed->y + pf->final.y)); -#else - eo_do(ep->object, - efl_gfx_position_set(ed->x + pf->final.x, ed->y + pf->final.y)); + if (ep->typedata.text->ellipsize.valign != -1.0) + text_marquee_vertical = EINA_TRUE; + else + text_marquee_vertical = EINA_FALSE; - //TIZEN_ONLY(20160923): introduction of text marquee - if(ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) - { - tw = pf->final.w; - th = pf->final.h; + if (text_marquee_vertical) + { + if (ep->typedata.text->ellipsize.valign == 1.0) + text_marquee_top_left = EINA_TRUE; + else + text_marquee_top_left = EINA_FALSE; + } + else + { + if (ep->typedata.text->ellipsize.halign == 1.0) + text_marquee_top_left = EINA_TRUE; + else + text_marquee_top_left = EINA_FALSE; + } - text_chosen_desc = (Edje_Part_Description_Text *)ep->chosen_description; - if (text_chosen_desc->text.ellipsize.mode == EDJE_TEXT_ELLIPSIZE_MODE_MARQUEE && - text_chosen_desc->text.ellipsize.marquee_repeat_limit != 0) - { - eo_do(ep->object, - evas_obj_textblock_size_formatted_get(&tw, &th)); - if (tw < pf->final.w) tw = pf->final.w; - if (th < pf->final.h) th = pf->final.h; - } - eo_do(ep->object, - efl_gfx_size_set(tw, th)); - } - // - else - eo_do(ep->object, - efl_gfx_size_set(pf->final.w, pf->final.h)); -#endif + /* If text's current width is smaller than part's width, cancel marquee */ + if ((text_cur_area.w <= ep->w) && (text_cur_area.h <= ep->h)) + { + evas_object_move(ep->object, + ep->typedata.text->ellipsize.marquee.orig_x, + ep->typedata.text->ellipsize.marquee.orig_y); + ep->typedata.text->ellipsize.marquee.animator = NULL; + _edje_text_ellipsize_marquee_remove(ep); + _edje_text_ellipsize_fade_update(ep, EINA_FALSE); - if (ep->nested_smart) /* Move, Resize all nested parts */ - { /* Not really needed but will improve the bounding box evaluation done by Evas */ - eo_do(ep->nested_smart, - efl_gfx_position_set(ed->x + pf->final.x, ed->y + pf->final.y), - efl_gfx_size_set(pf->final.w, pf->final.h)); - } - if (ep->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE) - _edje_entry_real_part_configure(ed, ep); + return ECORE_CALLBACK_CANCEL; + } - /* handle clip overrides */ - if (ed->has_state_clip) - { - if (pf->clip_to && pf->clip_to->object) - evas_object_clip_set(ep->object, pf->clip_to->object); - else if (ep->part->clip_to_id >= 0) - evas_object_clip_set(ep->object, ed->table_parts[ep->part->clip_to_id % ed->table_parts_size]->object); - else - evas_object_clip_set(ep->object, ed->base->clipper); - } - break; + evas_object_geometry_get(clipper_obj, + &clipper_area.x, &clipper_area.y, + &clipper_area.w, &clipper_area.h); - case EDJE_PART_TYPE_TEXT: - /* This is correctly handle in _edje_text_recalc_apply at the moment. */ - break; + cur_time = ecore_time_get(); + elapsed_time = cur_time - ep->typedata.text->ellipsize.marquee.animator_prev_time; - case EDJE_PART_TYPE_GRADIENT: - /* FIXME: definitivly remove this code when we switch to new format. */ - abort(); - break; + /* Calculates move_pixel when only elapsed_time has positive value. + * The elapsed_time variable could have negative value if there is loop_delay. */ + if (elapsed_time > 0.0) + { + while (elapsed_time > time_sec_per_pixel) + { + elapsed_time -= time_sec_per_pixel; + move_pixel++; + } - case EDJE_PART_TYPE_SPACER: - /* We really should do nothing on SPACER part */ - break; - case EDJE_PART_TYPE_CAMERA: - { - Evas_Canvas3D_Camera *camera = NULL; - Edje_Part_Description_Camera *pd_camera; + ep->typedata.text->ellipsize.marquee.animator_prev_time = cur_time - elapsed_time; + } - pd_camera = (Edje_Part_Description_Camera*) ep->chosen_description; - eo_do(ep->node, camera = evas_canvas3d_node_camera_get()); + if (move_pixel > 0) + { + double overpixel_for_jump = 0.0; + double overtime_for_loop = 0.0; + double overpixel_for_loop = 0.0; + int clipper_pos, clipper_length; + int text_pos, text_length; - eo_do(camera, - evas_canvas3d_camera_projection_perspective_set(pd_camera->camera.camera.fovy, pd_camera->camera.camera.aspect, - pd_camera->camera.camera.frustum_near, pd_camera->camera.camera.frustum_far)); + if (text_marquee_vertical) + { + clipper_pos = clipper_area.y; + clipper_length = clipper_area.h; + text_pos = text_cur_area.y; + text_length = text_cur_area.h; + } + else + { + clipper_pos = clipper_area.x; + clipper_length = clipper_area.w; + text_pos = text_cur_area.x; + text_length = text_cur_area.w; + } - eo_do(ep->node, - evas_canvas3d_node_position_set(pd_camera->camera.position.point.x, pd_camera->camera.position.point.y, - pd_camera->camera.position.point.z)); - switch (pd_camera->camera.orientation.type) - { - case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_NONE: - case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_QUATERNION: - { - SET_QUATERNION(camera) - break; - } - case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_LOOK_AT: - SET_LOOK_AT(camera) - break; - case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_LOOK_TO: - { - SET_LOOK_TO(camera) - break; - } - case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_ANGLE_AXIS: - SET_ANGLE_AXIS(camera) - break; - } - break; - } - case EDJE_PART_TYPE_LIGHT: - { - Evas_Canvas3D_Light *light_node = NULL; - Edje_Part_Description_Light *pd_light; + /* Calculate basic information of a loop according to marquee type */ + switch (chosen_desc->text.ellipsize.marquee.type) + { + case EDJE_TEXT_ELLIPSIZE_MARQUEE_TYPE_ROLL: + distance_per_loop = text_length + roll_gap; - pd_light = (Edje_Part_Description_Light*) ep->chosen_description; - eo_do(ep->node, light_node = evas_canvas3d_node_light_get()); + if (text_marquee_top_left) + { + loop_jump_from_pos = clipper_pos - text_length - roll_gap; + loop_jump_to_pos = clipper_pos; + } + else + { + loop_jump_from_pos = clipper_pos + clipper_length + roll_gap; + loop_jump_to_pos = clipper_pos + clipper_length - text_length; + } + break; + case EDJE_TEXT_ELLIPSIZE_MARQUEE_TYPE_DEFAULT: + default: + distance_per_loop = text_length + clipper_length; - eo_do(light_node, - evas_canvas3d_light_ambient_set(pd_light->light.properties.ambient.r / 255, pd_light->light.properties.ambient.g / 255, - pd_light->light.properties.ambient.b / 255, pd_light->light.properties.ambient.a / 255), - evas_canvas3d_light_diffuse_set(pd_light->light.properties.diffuse.r / 255, pd_light->light.properties.diffuse.g / 255, - pd_light->light.properties.diffuse.b / 255, pd_light->light.properties.diffuse.a / 255), - evas_canvas3d_light_specular_set(pd_light->light.properties.specular.r / 255, pd_light->light.properties.specular.g / 255, - pd_light->light.properties.specular.b / 255, pd_light->light.properties.specular.a / 255), - evas_canvas3d_light_directional_set(EINA_TRUE)); + if (text_marquee_top_left) + { + loop_jump_from_pos = clipper_pos - text_length; + loop_jump_to_pos = clipper_pos + clipper_length; + } + else + { + loop_jump_from_pos = clipper_pos + clipper_length; + loop_jump_to_pos = clipper_pos - text_length; + } + } - eo_do(ep->node, - evas_canvas3d_node_position_set(pd_light->light.position.point.x, pd_light->light.position.point.y, - pd_light->light.position.point.z)); - switch (pd_light->light.orientation.type) - { - case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_NONE: - case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_QUATERNION: - { - SET_QUATERNION(light); - break; - } - case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_LOOK_AT: - SET_LOOK_AT(light) - break; - case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_LOOK_TO: - { - SET_LOOK_TO(light) - break; - } - case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_ANGLE_AXIS: - SET_ANGLE_AXIS(light) - break; - } - break; - } - case EDJE_PART_TYPE_MESH_NODE: - { - Evas_Canvas3D_Material *material = NULL; - Evas_Canvas3D_Texture *texture = NULL; - Evas_Canvas3D_Mesh *mesh = NULL; - const char *proxy; - Edje_Part_Description_Mesh_Node *pd_mesh_node; - const Eina_List *meshes; - const Eina_List *list; + /* Calculate new x, y position according to current marquee direction */ + if (text_marquee_top_left) + { + text_pos -= move_pixel; - eo_do(ep->node, meshes = evas_canvas3d_node_mesh_list_get()); + /* If x pos exceed loop_jump_from_pos, jump to loop_jump_to_pos */ + if (text_pos <= loop_jump_from_pos) + { + overpixel_for_jump = loop_jump_from_pos - text_pos; + text_pos = loop_jump_to_pos - overpixel_for_jump; + } + } + else + { + text_pos += move_pixel; - EINA_LIST_FOREACH(meshes, list, mesh) - { - eo_do(mesh, material = evas_canvas3d_mesh_frame_material_get(0)); - eo_do(material, texture = evas_canvas3d_material_texture_get(EVAS_CANVAS3D_MATERIAL_ATTRIB_DIFFUSE)); + /* If x pos exceed loop_jump_from_pos, jump to loop_jump_to_pos */ + if (text_pos >= loop_jump_from_pos) + { + overpixel_for_jump = text_pos - loop_jump_from_pos; + text_pos = loop_jump_to_pos + overpixel_for_jump; + } + } - pd_mesh_node = (Edje_Part_Description_Mesh_Node*) ep->chosen_description; + /* If there is a loop limit, update loop and check it */ + if (chosen_desc->text.ellipsize.marquee_repeat_limit > 0) + { + /* Update moved distance which is used to update loop count */ + ep->typedata.text->ellipsize.marquee.distance += move_pixel; - eo_do(material, - evas_canvas3d_material_enable_set(EVAS_CANVAS3D_MATERIAL_ATTRIB_AMBIENT, EINA_TRUE), - evas_canvas3d_material_enable_set(EVAS_CANVAS3D_MATERIAL_ATTRIB_DIFFUSE, EINA_TRUE), - evas_canvas3d_material_enable_set(EVAS_CANVAS3D_MATERIAL_ATTRIB_SPECULAR, EINA_TRUE), - evas_canvas3d_material_enable_set(EVAS_CANVAS3D_MATERIAL_ATTRIB_NORMAL, pd_mesh_node->mesh_node.properties.normal), - evas_canvas3d_material_color_set(EVAS_CANVAS3D_MATERIAL_ATTRIB_AMBIENT, - pd_mesh_node->mesh_node.properties.ambient.r / 255, - pd_mesh_node->mesh_node.properties.ambient.g / 255, - pd_mesh_node->mesh_node.properties.ambient.b / 255, - pd_mesh_node->mesh_node.properties.ambient.a / 255), - evas_canvas3d_material_color_set(EVAS_CANVAS3D_MATERIAL_ATTRIB_DIFFUSE, - pd_mesh_node->mesh_node.properties.diffuse.r / 255, - pd_mesh_node->mesh_node.properties.diffuse.g / 255, - pd_mesh_node->mesh_node.properties.diffuse.b / 255, - pd_mesh_node->mesh_node.properties.diffuse.a / 255), - evas_canvas3d_material_color_set(EVAS_CANVAS3D_MATERIAL_ATTRIB_SPECULAR, - pd_mesh_node->mesh_node.properties.specular.r / 255, - pd_mesh_node->mesh_node.properties.specular.g / 255, - pd_mesh_node->mesh_node.properties.specular.b / 255, - pd_mesh_node->mesh_node.properties.specular.a / 255), - evas_canvas3d_material_shininess_set(pd_mesh_node->mesh_node.properties.shininess)); + /* Update loop count */ + if (ep->typedata.text->ellipsize.marquee.distance >= distance_per_loop) + { + ep->typedata.text->ellipsize.marquee.loop_count += ep->typedata.text->ellipsize.marquee.distance / distance_per_loop; + ep->typedata.text->ellipsize.marquee.distance %= distance_per_loop; - switch(pd_mesh_node->mesh_node.mesh.primitive) - { - case EVAS_CANVAS3D_MESH_PRIMITIVE_CUBE: - { - Eo *primitive = NULL; + /* Give a latency for next loop. The code below corrects the latency of the next loop, + taking into account the pixels beyond the loop. */ + if (chosen_desc->text.ellipsize.marquee.loop_delay > 0.0) + { + double next_delay_time; - eo_do(primitive, - evas_canvas3d_primitive_form_set(EVAS_CANVAS3D_MESH_PRIMITIVE_CUBE)); + overpixel_for_loop = ep->typedata.text->ellipsize.marquee.distance; + overtime_for_loop = overpixel_for_loop * time_sec_per_pixel; + next_delay_time = chosen_desc->text.ellipsize.marquee.loop_delay - overtime_for_loop; - eo_do(mesh, - evas_canvas3d_mesh_from_primitive_set(0, primitive)); - break; - } - case EVAS_CANVAS3D_MESH_PRIMITIVE_SPHERE: - { - Eo *primitive = NULL; + if (next_delay_time >= 0.0) + { + ep->typedata.text->ellipsize.marquee.animator_prev_time += next_delay_time; + overpixel_for_loop = -ep->typedata.text->ellipsize.marquee.distance; + } + else + { + /* Below is a code of extraordinary situations. + If the time beyond a loop is greater than the latency of a given loop, + then it is necessary to remove the pixels of the corresponding delay. + The overpixel_for_loop variable will have negative value. */ + overpixel_for_loop = next_delay_time * time_sec_per_pixel; + } - eo_do(primitive, - evas_canvas3d_primitive_form_set(EVAS_CANVAS3D_MESH_PRIMITIVE_SPHERE), - evas_canvas3d_primitive_precision_set(20)); + ep->typedata.text->ellipsize.marquee.distance += overpixel_for_loop; + } + } - eo_do(mesh, - evas_canvas3d_mesh_from_primitive_set(0, primitive)); - break; - } - default: - break; - } + /* Check if the loop count reaches the given loop limit. */ + if (ep->typedata.text->ellipsize.marquee.loop_count >= + chosen_desc->text.ellipsize.marquee_repeat_limit) + { + evas_object_move(ep->object, + ep->typedata.text->ellipsize.marquee.orig_x, + ep->typedata.text->ellipsize.marquee.orig_y); - if (pd_mesh_node->mesh_node.texture.need_texture && pd_mesh_node->mesh_node.texture.textured) - { - proxy = NULL; + ep->typedata.text->ellipsize.marquee.animator = NULL; + _edje_text_ellipsize_marquee_remove(ep); + _edje_text_ellipsize_fade_update(ep, EINA_TRUE); - eo_do(material, - texture = evas_canvas3d_material_texture_get(EVAS_CANVAS3D_MATERIAL_ATTRIB_DIFFUSE)); + return ECORE_CALLBACK_DONE; + } + } - //proxy = _edje_image_name_find(ed, pd_mesh_node->mesh_node.texture.id); - /*FIXME Conflict with function _edje_image_name_find (two places in edje_utils and edje_edit.c, - temporary desicion need to clarify up to commit to phab*/ - proxy = ed->file->image_dir->entries[pd_mesh_node->mesh_node.texture.id].entry; - if (proxy) - { - eo_do(texture, - evas_canvas3d_texture_file_set(eina_stringshare_add(proxy), NULL), - evas_canvas3d_texture_filter_set(pd_mesh_node->mesh_node.texture.filter1, - pd_mesh_node->mesh_node.texture.filter2), - evas_canvas3d_texture_wrap_set(pd_mesh_node->mesh_node.texture.wrap1, - pd_mesh_node->mesh_node.texture.wrap2)); - } - } + if (text_marquee_top_left) + text_pos -= overpixel_for_loop; + else + text_pos += overpixel_for_loop; - eo_do(mesh, - evas_canvas3d_mesh_frame_material_set(0, material), - evas_canvas3d_mesh_shade_mode_set(pd_mesh_node->mesh_node.properties.shade), - evas_canvas3d_mesh_vertex_assembly_set(pd_mesh_node->mesh_node.mesh.assembly)); - eo_do(ep->node, - evas_canvas3d_node_scale_set(ep->part->scale_3d.x, ep->part->scale_3d.y, - ep->part->scale_3d.z), - evas_canvas3d_node_position_set(pd_mesh_node->mesh_node.position.point.x, - pd_mesh_node->mesh_node.position.point.y, - pd_mesh_node->mesh_node.position.point.z)); - switch (pd_mesh_node->mesh_node.orientation.type) - { - case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_NONE: - case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_QUATERNION: - { - SET_QUATERNION(mesh_node) - break; - } - case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_LOOK_AT: - SET_LOOK_AT(mesh_node) - break; - case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_LOOK_TO: - { - SET_LOOK_TO(mesh_node) - break; - } - case EVAS_CANVAS3D_NODE_ORIENTATION_TYPE_ANGLE_AXIS: - SET_ANGLE_AXIS(mesh_node) - break; - } - } - break; - } + /* If current marquee type needs a proxy object, update it, too. */ + if (chosen_desc->text.ellipsize.marquee.type == EDJE_TEXT_ELLIPSIZE_MARQUEE_TYPE_ROLL) + { + Evas_Object *p_obj = _edje_text_ellipsize_marquee_proxy_object_get(ep); + int proxy_text_x, proxy_text_y; + int proxy_text_pos = text_pos; + + if (text_marquee_top_left) + proxy_text_pos += text_length + roll_gap; + else + proxy_text_pos -= text_length + roll_gap; + + if (text_marquee_vertical) + { + proxy_text_x = text_cur_area.x; + proxy_text_y = proxy_text_pos; + } + else + { + proxy_text_x = proxy_text_pos; + proxy_text_y = text_cur_area.y; + } + + evas_object_move(p_obj, proxy_text_x, proxy_text_y); + evas_object_resize(p_obj, text_cur_area.w, text_cur_area.h); + evas_object_show(p_obj); } - /* Some object need special recalc. */ - switch (ep->part->type) - { - case EDJE_PART_TYPE_TEXT: - _edje_text_recalc_apply(ed, ep, pf, (Edje_Part_Description_Text*) chosen_desc, EINA_FALSE); - break; + if (text_marquee_vertical) + text_cur_area.y = text_pos; + else + text_cur_area.x = text_pos; - case EDJE_PART_TYPE_PROXY: - _edje_proxy_recalc_apply(ed, ep, pf, (Edje_Part_Description_Proxy *)chosen_desc, pos); - break; + /* Update Textblock/Text object using updated position */ + evas_object_move(ep->object, text_cur_area.x, text_cur_area.y); - case EDJE_PART_TYPE_IMAGE: - _edje_image_recalc_apply(ed, ep, pf, (Edje_Part_Description_Image *)chosen_desc, pos); - break; + _edje_text_ellipsize_fade_update(ep, EINA_TRUE); + } - case EDJE_PART_TYPE_BOX: - _edje_box_recalc_apply(ed, ep, pf, (Edje_Part_Description_Box *)chosen_desc); - break; + return ECORE_CALLBACK_RENEW; +} - case EDJE_PART_TYPE_TABLE: - _edje_table_recalc_apply(ed, ep, pf, (Edje_Part_Description_Table *)chosen_desc); - break; +/* + * _edje_text_ellipsize_apply() is a main function to apply ellipsis, fade, marquee. + * ellipsize.mode: NONE will off this feature and respect old way of ellipsis. + * + * example: + * description { + * text { + * ellipsize { + * mode: FADE_MARQUEE; // NONE(default), NORMAL, FADE, FADE_MARQUEE, MARQUEE + * align: END; // END(default), START, LEFT, RIGHT, LOCALE + * marquee { + * type: ROLL; // NORMAL(default), ROLL + * speed: 50; // pixel per sec. It is a scalable variable when its part is scalable. + * // duration: 4.0;// sec per loop. The speed will be changed according to text's length. + * loop: 3; + * loop_delay: 2.0; // sec. delay for starting each loop + * } + * } + * } + * } + * + * It also support legacy fade_ellipsis. + */ +static void +_edje_text_ellipsize_apply(Edje *ed, Edje_Real_Part *ep, + Edje_Calc_Params *pf, + Edje_Part_Description_Text *chosen_desc) +{ + Evas_Object *edje_orig_clipper; + Evas_Object *clipper_obj; + Evas_Object *mask_obj; + double halign, valign; + Eina_Bool ellipsis_status; + Eina_Bool is_fade = EINA_FALSE; + Eina_Bool is_marquee = EINA_FALSE; + /* TODO: roll_gap should be controlled by edc developers? */ + int roll_gap = EDJE_TEXT_ELLIPSIZE_MARQUEE_ROLL_GAP; + int clipper_x, clipper_y, clipper_w, clipper_h; + int tx, ty, tw, th; - case EDJE_PART_TYPE_TEXTBLOCK: - _edje_textblock_recalc_apply(ed, ep, pf, (Edje_Part_Description_Text *)chosen_desc); - break; + if ((ep->part->type != EDJE_PART_TYPE_TEXTBLOCK) && + (ep->part->type != EDJE_PART_TYPE_TEXT)) + return; - case EDJE_PART_TYPE_VECTOR: - _edje_svg_recalc_apply(ed, ep, pf, (Edje_Part_Description_Vector *)chosen_desc, pos); - break; + if (pf->clip_to && pf->clip_to->object) + evas_object_clip_set(ep->object, pf->clip_to->object); + else if (ep->part->clip_to_id >= 0) + evas_object_clip_set(ep->object, ed->table_parts[ep->part->clip_to_id % ed->table_parts_size]->object); + else + evas_object_clip_set(ep->object, ed->base->clipper); - case EDJE_PART_TYPE_EXTERNAL: - case EDJE_PART_TYPE_RECTANGLE: - case EDJE_PART_TYPE_SWALLOW: - case EDJE_PART_TYPE_GROUP: - /* Nothing special to do for this type of object. */ - break; + if (ep->typedata.text->ellipsize.fade.animator) + { + ecore_animator_del(ep->typedata.text->ellipsize.fade.animator); + ep->typedata.text->ellipsize.fade.animator = NULL; + } - case EDJE_PART_TYPE_GRADIENT: - /* FIXME: definitivly remove this code when we switch to new format. */ - abort(); - break; + if (ep->typedata.text->ellipsize.marquee.animator) + { + _edje_text_ellipsize_marquee_remove(ep); + _edje_text_ellipsize_fade_update(ep, EINA_FALSE); + } - case EDJE_PART_TYPE_SPACER: - /* We really should do nothing on SPACER part */ - break; + /* Hide fade image if fade_ellipsis option is off or object size is zero. */ + if ((pf->final.w == 0) || (pf->final.h == 0) || + ((chosen_desc->text.ellipsize.mode == EDJE_TEXT_ELLIPSIZE_MODE_NONE) && + (chosen_desc->text.fade_ellipsis - 1.0 == -1.0))) + { + if (ep->typedata.text->ellipsize.clipper_obj) + { + evas_object_clip_unset(ep->typedata.text->ellipsize.clipper_obj); + evas_object_hide(ep->typedata.text->ellipsize.clipper_obj); } - if (((ep->type == EDJE_RP_TYPE_SWALLOW) && - (ep->typedata.swallow)) && - (ep->typedata.swallow->swallowed_object)) + if (ep->typedata.text->ellipsize.fade.mask_obj) { - if (ed->has_state_clip) - { - if (pf->clip_to && pf->clip_to->object) - evas_object_clip_set(ep->typedata.swallow->swallowed_object, pf->clip_to->object); - else if (ep->part->clip_to_id >= 0) - evas_object_clip_set(ep->typedata.swallow->swallowed_object, ed->table_parts[ep->part->clip_to_id % ed->table_parts_size]->object); - else - evas_object_clip_set(ep->typedata.swallow->swallowed_object, ed->base->clipper); - } + evas_object_clip_unset(ep->typedata.text->ellipsize.fade.mask_obj); + evas_object_hide(ep->typedata.text->ellipsize.fade.mask_obj); + } - if (pf->visible) - { - Eina_Bool vis = EINA_TRUE; + /* Disable normal ellipsis and proceed */ + if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) + evas_object_textblock_ellipsis_set(ep->object, -1.0); + else if (ep->part->type == EDJE_PART_TYPE_TEXT) + evas_object_text_ellipsis_set(ep->object, -1.0); - if (ep->part->type == EDJE_PART_TYPE_GROUP) - vis = evas_object_visible_get(ed->obj); - eo_do(ep->typedata.swallow->swallowed_object, - efl_gfx_position_set(ed->x + pf->final.x, ed->y + pf->final.y), - efl_gfx_size_set(pf->final.w, pf->final.h), - efl_gfx_visible_set(vis)); - } - else evas_object_hide(ep->typedata.swallow->swallowed_object); - mo = ep->typedata.swallow->swallowed_object; - } - else mo = ep->object; + return; + } - Evas_Object *map_obj; + if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) + ellipsis_status = evas_object_textblock_ellipsis_status_get(ep->object); + else + ellipsis_status = evas_object_text_ellipsis_status_get(ep->object); - /* Apply map to smart obj holding nested parts */ - if (ep->nested_smart) map_obj = ep->nested_smart; - else map_obj = mo; + /* Get alignment of ellipsize according to ellipsize.align and Text/Textblock's status */ + _edje_text_ellipsize_align_get(ep, pf, chosen_desc, &halign, &valign); - if (ep->part->type != EDJE_PART_TYPE_SPACER) + /* Enable normal ellipsis and quit the function */ + if (chosen_desc->text.ellipsize.mode == EDJE_TEXT_ELLIPSIZE_MODE_NORMAL) + { + if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) { - if (chosen_desc->map.on) - { - static Evas_Map *map = NULL; + evas_object_textblock_ellipsis_set(ep->object, halign); + } + else if (ep->part->type == EDJE_PART_TYPE_TEXT) + { + evas_object_text_ellipsis_set(ep->object, halign); + evas_object_resize(ep->object, pf->final.w, pf->final.h); + } - ed->have_mapped_part = EINA_TRUE; - // create map and populate with part geometry - if (!map) map = evas_map_new(4); + if (ep->typedata.text->ellipsize.clipper_obj) + { + evas_object_clip_unset(ep->typedata.text->ellipsize.clipper_obj); + evas_object_hide(ep->typedata.text->ellipsize.clipper_obj); + } - _edje_map_prop_set(map, pf, chosen_desc, ep, mo); + if (ep->typedata.text->ellipsize.fade.mask_obj) + { + evas_object_clip_unset(ep->typedata.text->ellipsize.fade.mask_obj); + evas_object_hide(ep->typedata.text->ellipsize.fade.mask_obj); + } - if (map_obj) - { - eo_do(map_obj, - evas_obj_map_set(map), - evas_obj_map_enable_set(EINA_TRUE)); - } - } - else - { - Eina_Bool ret; + return; + } - if (map_obj && eo_do_ret(map_obj, ret, evas_obj_map_enable_get())) - { -#ifdef HAVE_EPHYSICS - if (!ep->nested_smart && !ep->body) - { -#endif - eo_do(map_obj, - evas_obj_map_enable_set(EINA_FALSE), - evas_obj_map_set(NULL)); -#ifdef HAVE_EPHYSICS - } -#endif - } - } + /* Disable normal ellipsis and proceed */ + if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) + evas_object_textblock_ellipsis_set(ep->object, -1.0); + else if (ep->part->type == EDJE_PART_TYPE_TEXT) + evas_object_text_ellipsis_set(ep->object, -1.0); - /* TIZEN_ONLY(20160920): Add fade_ellipsis feature to TEXTBLOCK, TEXT part. */ - if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK || - ep->part->type == EDJE_PART_TYPE_TEXT) - { - /* TIZEN_ONLY(20170427): fix clipper loop issue caused by clipper object for fade ellipsis. - * Reset clipper for Textblock to fix the issue. */ - if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) - { - if (pf->clip_to && pf->clip_to->object) - evas_object_clip_set(ep->object, pf->clip_to->object); - else if (ep->part->clip_to_id >= 0) - evas_object_clip_set(ep->object, ed->table_parts[ep->part->clip_to_id % ed->table_parts_size]->object); - else - evas_object_clip_set(ep->object, ed->base->clipper); - } - /* END */ + /* Enable fade if one of fade types is set or legacy fade_ellipsis option is set */ + if ((chosen_desc->text.ellipsize.mode == EDJE_TEXT_ELLIPSIZE_MODE_FADE) || + (chosen_desc->text.ellipsize.mode == EDJE_TEXT_ELLIPSIZE_MODE_FADE_MARQUEE) || + (chosen_desc->text.fade_ellipsis > 0.0)) + is_fade = EINA_TRUE; - _edje_fade_ellipsis_apply(ed, ep, pf, (Edje_Part_Description_Text*) chosen_desc); - //TIZEN_ONLY(20160923): introduction of text marquee - _edje_text_marquee_apply(ed, ep, pf, (Edje_Part_Description_Text *) chosen_desc); - // - } - /* END */ + /* Enable marquee if one of marquee types is set and loop count is bigger than zero */ + if (((chosen_desc->text.ellipsize.mode == EDJE_TEXT_ELLIPSIZE_MODE_MARQUEE) || + (chosen_desc->text.ellipsize.mode == EDJE_TEXT_ELLIPSIZE_MODE_FADE_MARQUEE)) && + (chosen_desc->text.ellipsize.marquee_repeat_limit != 0)) + is_marquee = EINA_TRUE; + + if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) + { + evas_object_textblock_size_formatted_get(ep->object, &tw, &th); + } + else + { + tw = evas_object_text_horiz_advance_get(ep->object); + th = evas_object_text_vert_advance_get(ep->object); + } + + /* Hide fade image if text is not exceed the given area. */ + if ((tw <= pf->final.w) && (th <= pf->final.h) && !ellipsis_status) + { + if (ep->typedata.text->ellipsize.clipper_obj) + { + evas_object_clip_unset(ep->typedata.text->ellipsize.clipper_obj); + evas_object_hide(ep->typedata.text->ellipsize.clipper_obj); } + + if (ep->typedata.text->ellipsize.fade.mask_obj) + { + evas_object_clip_unset(ep->typedata.text->ellipsize.fade.mask_obj); + evas_object_hide(ep->typedata.text->ellipsize.fade.mask_obj); + } + + return; } - if (map_colors_free) _map_colors_free(pf); + if (ellipsis_status) + { + if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) + { + evas_object_textblock_ellipsis_disabled_set(ep->object, EINA_TRUE); + evas_object_textblock_size_formatted_get(ep->object, &tw, &th); + evas_object_textblock_ellipsis_disabled_set(ep->object, EINA_FALSE); + } + else + { + tw = evas_object_text_horiz_width_without_ellipsis_get(ep->object); + } + } -#ifdef HAVE_EPHYSICS - ep->prev_description = chosen_desc; - if (!ep->body) + /* Add a cllipper object */ + if (!ep->typedata.text->ellipsize.clipper_obj) { -#endif - ep->x = pf->final.x; - ep->y = pf->final.y; - ep->w = pf->final.w; - ep->h = pf->final.h; -#ifdef HAVE_EPHYSICS + ep->typedata.text->ellipsize.clipper_obj = evas_object_rectangle_add(evas_object_evas_get(ep->object)); + evas_object_pass_events_set(ep->typedata.text->ellipsize.clipper_obj, 1); + evas_object_pointer_mode_set(ep->typedata.text->ellipsize.clipper_obj, EVAS_OBJECT_POINTER_MODE_NOGRAB); + evas_object_smart_member_add(ep->typedata.text->ellipsize.clipper_obj, ed->obj); } -#endif + clipper_obj = ep->typedata.text->ellipsize.clipper_obj; + clipper_x = ed->x + pf->final.x; + clipper_y = ed->y + pf->final.y; + clipper_w = pf->final.w; + clipper_h = pf->final.h; - ep->calculated |= flags; - ep->calculating = FLAG_NONE; + if (halign == 0.0) + tx = ed->x + pf->final.x + pf->final.w - tw; + else + tx = ed->x + pf->final.x; - if (pf == &lp3) + if (valign == 0.0) + ty = ed->y + pf->final.y + pf->final.h - th; + else + ty = ed->y + pf->final.y; + + ep->typedata.text->ellipsize.text_w = tw; + ep->typedata.text->ellipsize.text_h = th; + ep->typedata.text->ellipsize.is_fade = is_fade; + ep->typedata.text->ellipsize.is_marquee = is_marquee; + ep->typedata.text->ellipsize.halign = (float)halign; + ep->typedata.text->ellipsize.valign = (float)valign; + + /* Set clippers for ellipsize */ + edje_orig_clipper = evas_object_clip_get(ep->object); + evas_object_clip_set(clipper_obj, edje_orig_clipper); + + /* If fade feature is enabled, set additional clipper for masking. */ + if (is_fade) { - eina_cow_free(_edje_calc_params_map_cow, (const Eina_Cow_Data **)&lp3.map); - lp3.map = NULL; -#ifdef HAVE_EPHYSICS - eina_cow_free(_edje_calc_params_physics_cow, (const Eina_Cow_Data **)&lp3.physics); - lp3.physics = NULL; + mask_obj = _edje_text_ellipsize_fade_mask_object_get(ep); +#if 0 + evas_object_clip_set(ep->object, clipper_obj); +#else + evas_object_clip_set(ep->object, mask_obj); + evas_object_clip_set(mask_obj, clipper_obj); #endif + evas_object_show(mask_obj); + } + else + { + evas_object_hide(ep->typedata.text->ellipsize.fade.mask_obj); + evas_object_clip_set(ep->object, clipper_obj); } -#ifdef EDJE_CALC_CACHE - if (ep->calculated == FLAG_XY) + evas_object_resize(clipper_obj, clipper_w, clipper_h); + evas_object_move(clipper_obj, clipper_x, clipper_y); + evas_object_show(clipper_obj); + + evas_object_resize(ep->object, tw, th); + evas_object_move(ep->object, tx, ty); + + if (is_marquee) { - ep->state = ed->state; - ep->invalidate = EINA_FALSE; + Eina_Bool text_marquee_vertical; + + if (valign != -1.0) + text_marquee_vertical = EINA_TRUE; + else + text_marquee_vertical = EINA_FALSE; + + if (chosen_desc->text.ellipsize.marquee.speed > 0.0) + { + /* Convert px_per_sec (speed) to sec_per_pixel */ + FLOAT_T sc = 1.0; + + if (ep->part->scale) + { + sc = DIV(ed->scale, ed->file->base_scale); + if (sc == 0.0) sc = 1.0; + } + + ep->typedata.text->ellipsize.marquee.sec_per_pixel = 1.0 / (chosen_desc->text.ellipsize.marquee.speed * TO_DOUBLE(sc)); + } + else if (chosen_desc->text.ellipsize.marquee.duration > 0.0) + { + /* Convert sec_per_loop (duration) to sec_per_pixel */ + int distance_per_loop = 0.0; + + switch (chosen_desc->text.ellipsize.marquee.type) + { + case EDJE_TEXT_ELLIPSIZE_MARQUEE_TYPE_ROLL: + if (text_marquee_vertical) + distance_per_loop = th + pf->final.h; + else + distance_per_loop = tw + pf->final.w; + break; + case EDJE_TEXT_ELLIPSIZE_MARQUEE_TYPE_DEFAULT: + default: + if (text_marquee_vertical) + distance_per_loop = th + roll_gap; + else + distance_per_loop = tw + roll_gap; + } + + ep->typedata.text->ellipsize.marquee.sec_per_pixel = + chosen_desc->text.ellipsize.marquee.duration / (double)distance_per_loop; + } + else + { + /* If there is no description for speed or duration, set default speed */ + FLOAT_T sc = 1.0; + + if (ep->part->scale) + { + sc = DIV(ed->scale, ed->file->base_scale); + if (sc == 0.0) sc = 1.0; + } + + ep->typedata.text->ellipsize.marquee.sec_per_pixel = EDJE_TEXT_ELLIPSIZE_MARQUEE_DEFAULT_SEC_PER_PIXEL / TO_DOUBLE(sc); + } + + ep->typedata.text->ellipsize.marquee.animator_prev_time = ecore_time_get(); + ep->typedata.text->ellipsize.marquee.orig_x = tx; + ep->typedata.text->ellipsize.marquee.orig_y = ty; + + /* Give a latency for first loop. */ + if (chosen_desc->text.ellipsize.marquee.loop_delay > 0.0) + ep->typedata.text->ellipsize.marquee.animator_prev_time += chosen_desc->text.ellipsize.marquee.loop_delay; + + ep->typedata.text->ellipsize.marquee.animator = ecore_animator_add(_edje_text_ellipsize_marquee_animator_cb, ep); } -#else - eina_cow_free(_edje_calc_params_map_cow, (const Eina_Cow_Data **)&lp1.map); -#ifdef HAVE_EPHYSICS - eina_cow_free(_edje_calc_params_physics_cow, (const Eina_Cow_Data **)&lp1.physics); -#endif -#endif + + if (is_fade) + _edje_text_ellipsize_fade_update(ep, EINA_FALSE); } + +/********************************************************************************** + * + * TIZEN_ONLY_FEATURE_END: ellipsize.marquee, ellipsize.fade for TEXTBLOCK, TEXT part. + * + **********************************************************************************/ diff --git a/src/lib/edje/edje_data.c b/src/lib/edje/edje_data.c index 333651b..2f3fa02 100644 --- a/src/lib/edje/edje_data.c +++ b/src/lib/edje/edje_data.c @@ -1146,6 +1146,13 @@ _edje_edd_init(void) EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_text, Edje_Part_Description_Text, "text.ellipsize.mode", text.ellipsize.mode, EET_T_INT); EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_text, Edje_Part_Description_Text, "text.ellipsize.marquee_repeat_limit", text.ellipsize.marquee_repeat_limit, EET_T_INT); // + /* TIZEN_ONLY(20170703): Add ellipsize feature and refactory fade_ellipsis, marquee features. */ + EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_text, Edje_Part_Description_Text, "text.ellipsize.align", text.ellipsize.align, EET_T_INT); + EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_text, Edje_Part_Description_Text, "text.ellipsize.marquee.type", text.ellipsize.marquee.type, EET_T_INT); + EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_text, Edje_Part_Description_Text, "text.ellipsize.marquee.loop_delay", text.ellipsize.marquee.loop_delay, EET_T_DOUBLE); + EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_text, Edje_Part_Description_Text, "text.ellipsize.marquee.speed", text.ellipsize.marquee.speed, EET_T_DOUBLE); + EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_text, Edje_Part_Description_Text, "text.ellipsize.marquee.duration", text.ellipsize.marquee.duration, EET_T_DOUBLE); + /* END */ EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_text, Edje_Part_Description_Text, "text.filter", filter.code, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_LIST_STRING(_edje_edd_edje_part_description_text, Edje_Part_Description_Text, "text.filter_sources", filter.sources); EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY(_edje_edd_edje_part_description_text, Edje_Part_Description_Text, "text.filter.data", filter.data, _edje_edd_edje_part_description_filter_data); // @since 1.15 @@ -1189,6 +1196,13 @@ _edje_edd_init(void) EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.ellipsize.mode", text.ellipsize.mode, EET_T_INT); EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.ellipsize.marquee_repeat_limit", text.ellipsize.marquee_repeat_limit, EET_T_INT); // + /* TIZEN_ONLY(20170703): Add ellipsize feature and refactory fade_ellipsis, marquee features. */ + EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.ellipsize.align", text.ellipsize.align, EET_T_INT); + EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.ellipsize.marquee.type", text.ellipsize.marquee.type, EET_T_INT); + EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.ellipsize.marquee.loop_delay", text.ellipsize.marquee.loop_delay, EET_T_DOUBLE); + EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.ellipsize.marquee.speed", text.ellipsize.marquee.speed, EET_T_DOUBLE); + EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.ellipsize.marquee.duration", text.ellipsize.marquee.duration, EET_T_DOUBLE); + /* END */ EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Edje_Part_Description_Box); eddc.func.mem_free = mem_free_box; diff --git a/src/lib/edje/edje_load.c b/src/lib/edje/edje_load.c index d348850..2d89acb 100644 --- a/src/lib/edje/edje_load.c +++ b/src/lib/edje/edje_load.c @@ -1598,7 +1598,7 @@ _edje_file_del(Edje *ed, Eina_Bool reuse_ic) eina_stringshare_del(rp->typedata.text->cache.in_str); eina_stringshare_del(rp->typedata.text->cache.out_str); /* TIZEN_ONLY(20170322): fix crash issue when Edje tries to clean up fade object */ - _edje_fade_ellipsis_remove(rp); + _edje_text_ellipsize_remove(rp); /* END */ free(rp->typedata.text); } diff --git a/src/lib/edje/edje_private.h b/src/lib/edje/edje_private.h index dd7cf7e..8ac31526 100644 --- a/src/lib/edje/edje_private.h +++ b/src/lib/edje/edje_private.h @@ -1430,8 +1430,19 @@ struct _Edje_Part_Description_Spec_Text struct { Edje_Text_Ellipsize_Mode mode; int marquee_repeat_limit; - int marquee_repeat_count; - Evas_Coord_Point marquee_start_point; + int marquee_repeat_count; /* Deprecated: Use loop_count in Edje_Real_Part_Text */ + Evas_Coord_Point marquee_start_point; /* Deprecated: Use marquee_start_x, y in Edje_Real_Part_Text */ + + /* TIZEN_ONLY(20170703): Add ellipsize feature and refactory fade_ellipsis, marquee features. */ + Edje_Text_Ellipsize_Align align; + + struct { + Edje_Text_Ellipsize_Marquee_Type type; + double loop_delay; + double speed; + double duration; + } marquee; + /* END */ } ellipsize; // }; @@ -1928,9 +1939,29 @@ struct _Edje_Real_Part_Text /* END */ /* TIZEN_ONLY(20160920): Add fade_ellipsis feature to TEXTBLOCK, TEXT part. */ struct { - Evas_Object *object; // 4 - float align; // 4 - } fade; + Evas_Object *clipper_obj; // 4 + float halign; // 4 + float valign; // 4 + int text_w, text_h; + Eina_Bool is_fade; + Eina_Bool is_marquee; + + struct { + Evas_Object *mask_obj; + Ecore_Animator *animator; + int x, y, w, h; + } fade; + + struct { + Evas_Object *proxy_obj; + Ecore_Animator *animator; + double animator_prev_time; + double sec_per_pixel; + int orig_x, orig_y; + int loop_count; + int distance; + } marquee; + } ellipsize; /* END */ struct { unsigned char fit_x, fit_y; // 2 @@ -2014,11 +2045,6 @@ struct _Edje_Real_Part #endif Evas_Event_Flags ignore_flags; Evas_Event_Flags mask_flags; - //TIZEN_ONLY(20160923): introduction of text marquee - double text_marquee_prev_time; - Ecore_Animator *text_marquee_animator; - Evas_Object *text_marquee_clipper; - // unsigned char type; // 1 unsigned char calculated : 2; // 1 unsigned char calculating : 2; // 0 @@ -2026,9 +2052,6 @@ struct _Edje_Real_Part #ifdef EDJE_CALC_CACHE Eina_Bool invalidate : 1; // 0 #endif - //TIZEN_ONLY(20160923): introduction of text marquee - unsigned char text_marquee_to_left : 1; - // unsigned char mouse_events : 1; unsigned char repeat_events : 1; }; // 128 @@ -3072,7 +3095,7 @@ void _edje_real_part_ignore_flags_set(Edje *ed, Edje_Real_Part *rp, Evas_Event_F Evas_Event_Flags _edje_real_part_mask_flags_get(Edje *ed, Edje_Real_Part *rp); void _edje_real_part_mask_flags_set(Edje *ed, Edje_Real_Part *rp, Evas_Event_Flags mask_flags); /* TIZEN_ONLY(20170322): fix crash issue when Edje tries to clean up fade object */ -void _edje_fade_ellipsis_remove(Edje_Real_Part *ep); +void _edje_text_ellipsize_remove(Edje_Real_Part *ep); /* END */ #ifdef HAVE_LIBREMIX diff --git a/src/lib/edje/edje_smart.c b/src/lib/edje/edje_smart.c index 4372a61..cfd028b 100644 --- a/src/lib/edje/edje_smart.c +++ b/src/lib/edje/edje_smart.c @@ -145,24 +145,56 @@ _edje_object_evas_object_smart_del(Eo *obj, Edje *ed) //TIZEN_ONLY(20160923): introduction of text marquee static void -_marquee_text_object_move(Edje *ed, Edje_Real_Part *ep, Evas_Coord_Point ed_diff) +_edje_object_text_ellipsize_clipper_move(Edje *ed, Edje_Real_Part *ep, Evas_Coord_Point ed_diff) { - Evas_Coord x, y; - Edje_Part_Description_Text *chosen_desc; + Evas_Coord x = 0, y = 0; - chosen_desc = (Edje_Part_Description_Text *)ep->chosen_description; + if (ep->typedata.text->ellipsize.marquee.animator) + { + evas_object_geometry_get(ep->object, &x, &y, NULL, NULL); - evas_object_geometry_get(ep->object, &x, &y, NULL, NULL); + /* Horizontal Case */ + x += ed_diff.x; + y += ed_diff.y; - /* ed_diff should be handled because of horizontal scroll */ - evas_object_move(ep->object, - x + ed_diff.x, - ed->y + ep->y + ep->typedata.text->offset.y); + /* ed_diff should be handled because of horizontal scroll */ + ep->typedata.text->ellipsize.marquee.orig_x += ed_diff.x; + ep->typedata.text->ellipsize.marquee.orig_y += ed_diff.y; + } + else + { + x = ed->x + ep->x + ep->typedata.text->offset.x; + y = ed->y + ep->y + ep->typedata.text->offset.y; + } - evas_object_move(ep->text_marquee_clipper, ed->x + ep->x, ed->y + ep->y); + if (ep->typedata.text->ellipsize.marquee.proxy_obj) + { + int px, py; - chosen_desc->text.ellipsize.marquee_start_point.x += ed_diff.x; - chosen_desc->text.ellipsize.marquee_start_point.y += ed_diff.y; + evas_object_geometry_get(ep->typedata.text->ellipsize.marquee.proxy_obj, + &px, &py, NULL, NULL); + evas_object_move(ep->typedata.text->ellipsize.marquee.proxy_obj, + px + ed_diff.x, py + ed_diff.y); + } + + if (ep->typedata.text->ellipsize.fade.animator) + { + ep->typedata.text->ellipsize.fade.x += ed_diff.x; + ep->typedata.text->ellipsize.fade.y += ed_diff.y; + } + + if (ep->typedata.text->ellipsize.fade.mask_obj) + { + int mx, my; + + evas_object_geometry_get(ep->typedata.text->ellipsize.fade.mask_obj, + &mx, &my, NULL, NULL); + evas_object_move(ep->typedata.text->ellipsize.fade.mask_obj, + mx + ed_diff.x, my + ed_diff.y); + } + + evas_object_move(ep->typedata.text->ellipsize.clipper_obj, ed->x + ep->x, ed->y + ep->y); + evas_object_move(ep->object, x, y); } // @@ -195,8 +227,9 @@ _edje_object_evas_object_smart_move(Eo *obj EINA_UNUSED, Edje *ed, Evas_Coord x, if ((ep->type == EDJE_RP_TYPE_TEXT) && (ep->typedata.text)) { //TIZEN_ONLY(20160923): introduction of text marquee - if (ep->text_marquee_animator) - _marquee_text_object_move(ed, ep, ed_diff); + if (ep->typedata.text->ellipsize.clipper_obj && + evas_object_visible_get(ep->typedata.text->ellipsize.clipper_obj)) + _edje_object_text_ellipsize_clipper_move(ed, ep, ed_diff); else // evas_object_move(ep->object, @@ -205,12 +238,7 @@ _edje_object_evas_object_smart_move(Eo *obj EINA_UNUSED, Edje *ed, Evas_Coord x, } else { - //TIZEN_ONLY(20160923): introduction of text marquee - if (ep->text_marquee_animator && ep->typedata.text) - _marquee_text_object_move(ed, ep, ed_diff); - else - // - evas_object_move(ep->object, ed->x + ep->x, ed->y + ep->y); + evas_object_move(ep->object, ed->x + ep->x, ed->y + ep->y); if ((ep->type == EDJE_RP_TYPE_SWALLOW) && (ep->typedata.swallow)) diff --git a/src/lib/evas/Evas_Legacy.h b/src/lib/evas/Evas_Legacy.h index 85f8b9b..2ab97c2 100644 --- a/src/lib/evas/Evas_Legacy.h +++ b/src/lib/evas/Evas_Legacy.h @@ -3896,6 +3896,27 @@ EAPI Eina_Bool evas_object_textblock_ellipsis_disabled_get(Evas_Object *eo_obj); /* END */ +/** + * TIZEN_ONLY(20170703): Add ellipsize feature and refactory fade_ellipsis, marquee features. + * @internal + */ +EAPI void +evas_object_textblock_ellipsis_set(Evas_Object *eo_obj, double ellipsis); + +/** + * TIZEN_ONLY(20170703): Add ellipsize feature and refactory fade_ellipsis, marquee features. + * @internal + */ +EAPI double +evas_object_textblock_ellipsis_get(const Evas_Object *eo_obj); + +/** + * TIZEN_ONLY(20170703): Add ellipsize feature and refactory fade_ellipsis, marquee features. + * @internal + */ +EAPI Evas_BiDi_Direction +evas_textblock_cursor_paragraph_direction_get(const Evas_Textblock_Cursor *cur); + #include "canvas/evas_textblock.eo.legacy.h" /** diff --git a/src/lib/evas/canvas/evas_object_textblock.c b/src/lib/evas/canvas/evas_object_textblock.c index 26c9a10..470b332 100644 --- a/src/lib/evas/canvas/evas_object_textblock.c +++ b/src/lib/evas/canvas/evas_object_textblock.c @@ -550,6 +550,9 @@ struct _Evas_Object_Textblock int l, r, t, b; } style_pad; double valign; + /* TIZEN_ONLY(20170703): Add ellipsize feature and refactory fade_ellipsis, marquee features. */ + double ellipsis; + /* END */ Eina_Stringshare *markup_text; void *engine_data; const char *repch; @@ -5336,6 +5339,10 @@ _layout_par(Ctxt *c) { double ellip; ellip = it->format->ellipsis; + /* TIZEN_ONLY(20170703): Add ellipsize feature and refactory fade_ellipsis, marquee features. */ + if (c->o->ellipsis != -1.0) + ellip = c->o->ellipsis; + /* END */ /* TIZEN_ONLY(20161011): add ellipsis_disabled_set/get APIs if ((0 <= ellip) && (ellip < 1.0) && c->line_no == 0) */ @@ -5511,7 +5518,7 @@ _layout_par(Ctxt *c) !it->format->wrap_mixed && !it->format->wrap_hyphenation))) */ if (!c->o->ellipsis_disabled && - (it->format->ellipsis == 1.0) && (c->h >= 0) && + ((c->o->ellipsis == 1.0) || (it->format->ellipsis == 1.0)) && (c->h >= 0) && ((c->y + ellip_h_thresh > c->h - c->o->style_pad.t - c->o->style_pad.b) || (!it->format->wrap_word && !it->format->wrap_char && @@ -5660,7 +5667,11 @@ _layout_par(Ctxt *c) { /* FIXME: Should redo the ellipsis handling. * If we can do ellipsis, just cut here. */ + /* TIZEN_ONLY(20170703): Add ellipsize feature and refactory fade_ellipsis, marquee features. if (it->format->ellipsis == 1.0) + */ + if ((c->o->ellipsis == 1.0) || (it->format->ellipsis == 1.0)) + /* END */ { _layout_handle_ellipsis(c, it, i); ret = 1; @@ -6540,6 +6551,9 @@ _evas_textblock_eo_base_constructor(Eo *eo_obj, Evas_Textblock_Data *class_data o = obj->private_data; o->cursor = calloc(1, sizeof(Evas_Textblock_Cursor)); + /* TIZEN_ONLY(20170703): Add ellipsize feature and refactory fade_ellipsis, marquee features. */ + o->ellipsis = -1.0; + /* END */ _format_command_init(); evas_object_textblock_init(eo_obj); @@ -13861,6 +13875,66 @@ evas_object_textblock_ellipsis_disabled_get(Evas_Object *eo_obj) } /* END */ +/* TIZEN_ONLY(20170703): Add ellipsize feature and refactory fade_ellipsis, marquee features. */ +EAPI void +evas_object_textblock_ellipsis_set(Evas_Object *eo_obj, double ellipsis) +{ + TB_HEAD(); + + if (o->ellipsis == ellipsis) return; + + o->ellipsis = ellipsis; + + _evas_textblock_invalidate_all(o); + _evas_textblock_changed(o, eo_obj); +} + +EAPI double +evas_object_textblock_ellipsis_get(const Evas_Object *eo_obj) +{ + Evas_Object_Textblock_Paragraph *par; + Evas_Object_Textblock_Item *it; + Evas_Textblock_Data *o; + Eina_List *l; + + TB_HEAD_RETURN(-1.0); + + o = eo_data_scope_get(eo_obj, MY_CLASS); + + if (o->ellipsis != -1.0) + return o->ellipsis; + + EINA_INLIST_FOREACH(o->paragraphs, par) + { + EINA_LIST_FOREACH(par->logical_items, l, it) + { + if (it->format) + return it->format->ellipsis; + } + } + + return -1.0; +} + +EAPI Evas_BiDi_Direction +evas_textblock_cursor_paragraph_direction_get(const Evas_Textblock_Cursor *cur) +{ + if (!cur) return EVAS_BIDI_DIRECTION_NEUTRAL; + if (!cur->node) + { + ERR("There is no node information on the given cursor: %p", cur); + return EVAS_BIDI_DIRECTION_NEUTRAL; + } + if (!cur->node->par) + { + ERR("There is no paragraph information on the given cursor: %p, node: %p", cur, cur->node); + return EVAS_BIDI_DIRECTION_NEUTRAL; + } + + return cur->node->par->direction; +} +/* END */ + /** * @} */