edje: import ellipsize features from Tizen with new TIZEN_ONLY tags
authorYoungbok Shin <youngb.shin@samsung.com>
Thu, 9 Nov 2017 10:26:51 +0000 (19:26 +0900)
committerJiyoun Park <jy0703.park@samsung.com>
Thu, 21 Dec 2017 07:49:31 +0000 (16:49 +0900)
All code for ellipsize and fade_ellipsis are merged by a common TIZEN_ONLY tag.
Put the following tag if you want to add a new code section for this feature.
This is for convenience of migration work.

/***********************************************************************************
 * TIZEN_ONLY_FEATURE: ellipsize.marquee, ellipsize.fade for TEXTBLOCK, TEXT part. *
 ***********************************************************************************/

... code ...

/*******
 * END *
 *******/

@tizen_feature

Change-Id: I601d410732cd258300e3aa575a8cb1ca670fcf2d

src/bin/edje/edje_cc_handlers.c
src/lib/edje/Edje_Common.h
src/lib/edje/edje_calc.c
src/lib/edje/edje_data.c
src/lib/edje/edje_load.c
src/lib/edje/edje_private.h
src/lib/edje/edje_smart.c
src/lib/edje/edje_text.c
src/lib/edje/edje_util.c

index 73a09f1..bb7671d 100644 (file)
@@ -418,10 +418,24 @@ static void st_collections_group_parts_part_description_text_align(void);
 static void st_collections_group_parts_part_description_text_source(void);
 static void st_collections_group_parts_part_description_text_text_source(void);
 static void st_collections_group_parts_part_description_text_ellipsis(void);
-//TIZEN_ONLY(20160923): introduction of text marquee
+/***********************************************************************************
+ * TIZEN_ONLY_FEATURE: ellipsize.marquee, ellipsize.fade for TEXTBLOCK, TEXT part. *
+ ***********************************************************************************/
+static void st_collections_group_parts_part_description_text_fade_ellipsis(void); /* Legacy */
 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);
-//
+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);
+static void st_collections_group_parts_part_description_text_ellipsize_normal_mode(void);
+static void st_collections_group_parts_part_description_text_ellipsize_fade_mode(void);
+static void st_collections_group_parts_part_description_text_ellipsize_marquee_mode(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);
@@ -949,11 +963,25 @@ New_Statement_Handler statement_handlers[] =
      {"collections.group.parts.part.description.text.fonts.font", st_fonts_font}, /* dup */
      {"collections.group.parts.part.description.text.elipsis", st_collections_group_parts_part_description_text_ellipsis},
      {"collections.group.parts.part.description.text.ellipsis", st_collections_group_parts_part_description_text_ellipsis},
-     //TIZEN_ONLY(20160923): introduction of text marquee
+     {"collections.group.parts.part.description.text.filter", st_collections_group_parts_part_description_filter_code}, /* dup */
+     /***********************************************************************************
+      * TIZEN_ONLY_FEATURE: ellipsize.marquee, ellipsize.fade for TEXTBLOCK, TEXT part. *
+      ***********************************************************************************/
      {"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},
-     //
-     {"collections.group.parts.part.description.text.filter", st_collections_group_parts_part_description_filter_code}, /* dup */
+     {"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},
+     {"collections.group.parts.part.description.text.ellipsize.normal.mode", st_collections_group_parts_part_description_text_ellipsize_normal_mode},
+     {"collections.group.parts.part.description.text.ellipsize.fade.mode", st_collections_group_parts_part_description_text_ellipsize_fade_mode},
+     {"collections.group.parts.part.description.text.ellipsize.marquee.mode", st_collections_group_parts_part_description_text_ellipsize_marquee_mode},
+     {"collections.group.parts.part.description.text.fade_ellipsis", st_collections_group_parts_part_description_text_fade_ellipsis}, /* Legacy */
+     /*******
+      * END * 
+      *******/
      {"collections.group.parts.part.description.box.layout", st_collections_group_parts_part_description_box_layout},
      {"collections.group.parts.part.description.box.align", st_collections_group_parts_part_description_box_align},
      {"collections.group.parts.part.description.box.padding", st_collections_group_parts_part_description_box_padding},
@@ -1551,8 +1579,17 @@ New_Object_Handler object_handlers[] =
      {"collections.group.parts.part.description.fill.origin", NULL},
      {"collections.group.parts.part.description.fill.size", NULL},
      {"collections.group.parts.part.description.text", NULL},
-     {"collections.group.parts.part.description.text.ellipsize", NULL},
      {"collections.group.parts.part.description.text.fonts", NULL}, /* dup */
+     /***********************************************************************************
+      * TIZEN_ONLY_FEATURE: ellipsize.marquee, ellipsize.fade for TEXTBLOCK, TEXT part. *
+      ***********************************************************************************/
+     {"collections.group.parts.part.description.text.ellipsize", NULL},
+     {"collections.group.parts.part.description.text.ellipsize.marquee", NULL},
+     {"collections.group.parts.part.description.text.ellipsize.normal", NULL},
+     {"collections.group.parts.part.description.text.ellipsize.fade", NULL},
+     /*******
+      * END *
+      *******/
      {"collections.group.parts.part.description.images", NULL}, /* dup */
      {"collections.group.parts.part.description.images.set", ob_images_set}, /* dup */
      {"collections.group.parts.part.description.images.set.image", ob_images_set_image}, /* dup */
@@ -1787,9 +1824,10 @@ _edje_part_description_alloc(unsigned char type, const char *collection, const c
           ed->text.align.y = FROM_DOUBLE(0.5);
           ed->text.id_source = -1;
           ed->text.id_text_source = -1;
-           //TIZEN_ONLY(20160923): introduction of text marquee
+           /* TIZEN_ONLY_FEATURE: ellipsize.marquee, ellipsize.fade for TEXTBLOCK, TEXT part. */
+           ed->text.fade_ellipsis = FROM_DOUBLE(0.0); /* Legacy */
            ed->text.ellipsize.marquee_repeat_limit = -1;
-           //
+           /* END */
 
           result = &ed->common;
           break;
@@ -8726,6 +8764,9 @@ st_collections_group_parts_part_description_inherit(void)
               _filter_copy(&ted->filter, &tparent->filter);
               data_queue_copied_part_nest_lookup(pc, &(tparent->text.id_source), &(ted->text.id_source), &ted->text.id_source_part);
               data_queue_copied_part_nest_lookup(pc, &(tparent->text.id_text_source), &(ted->text.id_text_source), &ted->text.id_text_source_part);
+              /* TIZEN_ONLY_FEATURE: ellipsize.marquee, ellipsize.fade for TEXTBLOCK, TEXT part. */
+              ted->text.fade_ellipsis = tparent->text.fade_ellipsis;
+              /* END */
 
               break;
            }
@@ -11771,7 +11812,30 @@ st_collections_group_parts_part_description_text_ellipsis(void)
    ed->text.ellipsis = parse_float_range(0, -1.0, 1.0);
 }
 
-//TIZEN_ONLY(20160923): introduction of text marquee
+/***********************************************************************************
+ * TIZEN_ONLY_FEATURE: ellipsize.marquee, ellipsize.fade for TEXTBLOCK, TEXT part. *
+ ***********************************************************************************/
+/* Legacy */
+static void
+st_collections_group_parts_part_description_text_fade_ellipsis(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.fade_ellipsis = parse_float_range(0, -1.0, 1.0) + 1.0;
+}
+
 static void
 st_collections_group_parts_part_description_text_ellipsize_mode(void)
 {
@@ -11819,7 +11883,214 @@ st_collections_group_parts_part_description_text_ellipsize_marquee_repeat_limit(
 
    ed->text.ellipsize.marquee_repeat_limit = parse_int_range(0, -1, 0x7fffffff);
 }
-//
+
+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;
+}
+
+static void
+st_collections_group_parts_part_description_text_ellipsize_normal_mode(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.mode = 0;
+   ed->text.ellipsize.normal.mode = parse_enum(0,
+                                               "OFF", EDJE_TEXT_ELLIPSIZE_NORMAL_MODE_OFF,
+                                               "ON", EDJE_TEXT_ELLIPSIZE_NORMAL_MODE_ON,
+                                               NULL);
+}
+
+static void
+st_collections_group_parts_part_description_text_ellipsize_fade_mode(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.mode = 0;
+   ed->text.ellipsize.fade.mode = parse_enum(0,
+                                             "OFF", EDJE_TEXT_ELLIPSIZE_FADE_MODE_OFF,
+                                             "ON", EDJE_TEXT_ELLIPSIZE_FADE_MODE_ON,
+                                             NULL);
+}
+
+static void
+st_collections_group_parts_part_description_text_ellipsize_marquee_mode(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.mode = 0;
+   ed->text.ellipsize.marquee.mode = parse_enum(0,
+                                                "OFF", EDJE_TEXT_ELLIPSIZE_MARQUEE_MODE_OFF,
+                                                "ON", EDJE_TEXT_ELLIPSIZE_MARQUEE_MODE_ON,
+                                                "ALWAYS", EDJE_TEXT_ELLIPSIZE_MARQUEE_MODE_ALWAYS,
+                                                NULL);
+}
+/*******/
+/* END */
+/*******/
+
 /** @edcsubsection{collections_group_parts_description_box,
  *                 Group.Parts.Part.Description.Box} */
 
index 1ab6d44..18f09cd 100644 (file)
@@ -1325,19 +1325,62 @@ typedef enum _Edje_Text_Effect
    EDJE_TEXT_EFFECT_SHADOW_DIRECTION_RIGHT        = (0x7 << 4)  /**< right shadow direction value */
 } Edje_Text_Effect;
 
-//TIZEN_ONLY(20160923): introduction of text marquee
+/***********************************************************************************
+ * TIZEN_ONLY_FEATURE: ellipsize.marquee, ellipsize.fade for TEXTBLOCK, TEXT part. *
+ ***********************************************************************************/
 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;
-//
+
+typedef enum _Edje_Text_Ellipsize_Normal_Mode
+{
+   EDJE_TEXT_ELLIPSIZE_NORMAL_MODE_OFF = 0,
+   EDJE_TEXT_ELLIPSIZE_NORMAL_MODE_ON
+} Edje_Text_Ellipsize_Normal_Mode;
+
+typedef enum _Edje_Text_Ellipsize_Fade_Mode
+{
+   EDJE_TEXT_ELLIPSIZE_FADE_MODE_OFF = 0,
+   EDJE_TEXT_ELLIPSIZE_FADE_MODE_ON
+} Edje_Text_Ellipsize_Fade_Mode;
+
+typedef enum _Edje_Text_Ellipsize_Marquee_Mode
+{
+   EDJE_TEXT_ELLIPSIZE_MARQUEE_MODE_OFF = 0,
+   EDJE_TEXT_ELLIPSIZE_MARQUEE_MODE_ON,
+   EDJE_TEXT_ELLIPSIZE_MARQUEE_MODE_ALWAYS
+} Edje_Text_Ellipsize_Marquee_Mode;
+
+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)
index b05e012..8524c43 100644 (file)
@@ -19,6 +19,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_FEATURE: ellipsize.marquee, ellipsize.fade for TEXTBLOCK, TEXT part. */
+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) \
    _edje_calc_params_need_ext(Calc); \
@@ -746,10 +751,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";
 
@@ -855,49 +856,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)
-                         {
-                            efl_text_ellipsis_set(ep->object, EINA_FALSE);
-                         }
-                       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_text_ellipsis_get(ep->object);
-                            efl_text_ellipsis_set(ep->object, !ellipsis);
-                         }
-                    }
-               }
-          }
-        //
      }
 
    ed->recalc_hints = EINA_TRUE;
@@ -3789,232 +3747,6 @@ _edje_part_calc_params_memcpy(Edje_Calc_Params *p, Edje_Calc_Params *s, Edje_Par
      }
 }
 /* END */
-//TIZEN_ONLY(20160923): introduction of text marquee
-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->text_marquee_clipper)
-     {
-        ep->text_marquee_clipper = evas_object_rectangle_add(evas_object_evas_get(ep->object));
-        evas_object_color_set(ep->text_marquee_clipper, 255, 255, 255, 255);
-        evas_object_show(ep->text_marquee_clipper);
-
-        Evas_Object *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);
-        evas_object_move(ep->text_marquee_clipper, text_cur_area.x - ep->typedata.text->offset.x,
-                                                   text_cur_area.y - ep->typedata.text->offset.y);
-
-        ep->text_marquee_prev_time = ecore_time_get();
-     }
-
-   evas_object_resize(ep->text_marquee_clipper, ep->w, ep->h);
-   evas_object_geometry_get(ep->text_marquee_clipper, &clipper_area.x, &clipper_area.y,
-                                                      &clipper_area.w, &clipper_area.h);
-
-   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 (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++;
-
-             text_cur_area.x = clipper_area.x + clipper_area.w;
-          }
-        else
-          {
-             text_cur_area.x = text_cur_area.x - move_length;
-          }
-     }
-   else
-     {
-        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++;
-
-             text_cur_area.x = clipper_area.x - text_cur_area.w;
-          }
-        else
-          {
-             text_cur_area.x = text_cur_area.x + move_length;
-          }
-     }
-
-   /* reset text to start point */
-   if (chosen_desc->text.ellipsize.marquee_repeat_limit ==
-       chosen_desc->text.ellipsize.marquee_repeat_count)
-    {
-       evas_object_move(ep->object,
-                        chosen_desc->text.ellipsize.marquee_start_point.x,
-                        chosen_desc->text.ellipsize.marquee_start_point.y);
-       return ECORE_CALLBACK_CANCEL;
-    }
-
-   evas_object_move(ep->object, text_cur_area.x, text_cur_area.y);
-   return ECORE_CALLBACK_RENEW;
-}
-
-static void
-_text_marquee_job(void *data)
-{
-   Edje_Real_Part *ep;
-   Evas_BiDi_Direction dir;
-   Edje_Part_Description_Text *chosen_desc;
-   Evas_Coord_Rectangle text_cur_position;
-
-   ep = data;
-   chosen_desc = (Edje_Part_Description_Text *)ep->chosen_description;
-
-   /* keep marquee start point */
-   evas_object_geometry_get(ep->object, &text_cur_position.x,
-                                        &text_cur_position.y,
-                                                  NULL, NULL);
-   chosen_desc->text.ellipsize.marquee_start_point.x = text_cur_position.x;
-   chosen_desc->text.ellipsize.marquee_start_point.y = text_cur_position.y;
-
-   if (ep->text_marquee_animator)
-     {
-        ecore_animator_del(ep->text_marquee_animator);
-        ep->text_marquee_animator = NULL;
-     }
-   ep->text_marquee_animator = ecore_animator_add(_text_object_marquee_animator, ep);
-
-   /* 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);
-          }
-     }
-   else
-     {
-        dir = evas_object_text_direction_get(ep->object);
-     }
-
-   /* define marquee direction */
-   ep->text_marquee_to_left = (dir != EVAS_BIDI_DIRECTION_RTL);
-
-   ep->text_marquee_job = NULL;
-}
-
-static void
-_text_marquee_clipper_update(Edje_Real_Part *ep, Eina_Bool del_clipper)
-{
-   Evas_Object *prev_clipper;
-   Evas_Coord_Rectangle text_cur_area;
-
-   prev_clipper = evas_object_clip_get(ep->text_marquee_clipper);
-   if (!del_clipper)
-     {
-        /* reset marquee clipper changed in _edje_part_recalc */
-        if (prev_clipper && prev_clipper != ep->text_marquee_clipper)
-          {
-             evas_object_clip_set(ep->text_marquee_clipper, prev_clipper);
-             evas_object_clip_set(ep->object, ep->text_marquee_clipper);
-          }
-
-        evas_object_geometry_get(ep->object, &text_cur_area.x, &text_cur_area.y,
-                                             &text_cur_area.w, &text_cur_area.h);
-        evas_object_move(ep->text_marquee_clipper, text_cur_area.x - ep->typedata.text->offset.x,
-                                                   text_cur_area.y - ep->typedata.text->offset.y);
-        evas_object_resize(ep->text_marquee_clipper, ep->w, ep->h);
-     }
-   else
-     {
-        evas_object_del(ep->text_marquee_clipper);
-        ep->text_marquee_clipper = NULL;
-
-        if (prev_clipper) evas_object_clip_set(ep->object, prev_clipper);
-     }
-}
-
-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_job)
-     {
-        ecore_job_del(ep->text_marquee_job);
-        ep->text_marquee_job = NULL;
-     }
-
-   if (ep->text_marquee_animator)
-     {
-        ecore_animator_del(ep->text_marquee_animator);
-        ep->text_marquee_animator = NULL;
-        _text_marquee_clipper_update(ep, EINA_TRUE);
-     }
-}
-
-static void
-_edje_text_marquee_apply(Edje *ed EINA_UNUSED, Edje_Real_Part *ep,
-                         Edje_Calc_Params *params EINA_UNUSED,
-                         Edje_Part_Description_Text *chosen_desc)
-{
-   Eina_Bool is_marquee_on;
-
-   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));
-
-   if (ep->text_marquee_job)
-     {
-        ecore_job_del(ep->text_marquee_job);
-        ep->text_marquee_job = NULL;
-     }
-
-   if (ep->text_marquee_animator)
-     {
-        ecore_animator_del(ep->text_marquee_animator);
-        ep->text_marquee_animator = NULL;
-        /* in case of marquee mode, do not remove existing clipper */
-        _text_marquee_clipper_update(ep, !is_marquee_on);
-     }
-
-   if (is_marquee_on)
-     {
-        ep->text_marquee_job = ecore_job_add(_text_marquee_job, ep);
-        evas_object_event_callback_add(ep->object, EVAS_CALLBACK_DEL,
-                                       _text_object_del_cb, ep);
-     }
-}
-//
 
 void
 _edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int flags, Edje_Calc_Params *state)
@@ -4049,10 +3781,6 @@ _edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int flags, Edje_Calc_Params *sta
    Edje_Calc_Params lp3 = { {0} };
    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;
-   //
 
 #ifdef EDJE_CALC_CACHE
 #else
@@ -4958,26 +4686,7 @@ _edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int flags, Edje_Calc_Params *sta
 #else
              efl_gfx_position_set(ep->object, EINA_POSITION2D(ed->x + pf->final.x, ed->y + pf->final.y));
 
-             //TIZEN_ONLY(20160923): introduction of text marquee
-             if(ep->part->type == EDJE_PART_TYPE_TEXTBLOCK)
-               {
-                  tw = pf->final.w;
-                  th = pf->final.h;
-
-                  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)
-                    {
-                       evas_object_textblock_size_formatted_get(ep->object, &tw, &th);
-                       efl_gfx_size_set(ep->object, EINA_SIZE2D(tw, th));
-                       if (tw < pf->final.w) tw = pf->final.w;
-                       if (th < pf->final.h) th = pf->final.h;
-                    }
-                  efl_gfx_size_set(ep->object, EINA_SIZE2D(tw, th));
-               }
-             //
-              else
-                efl_gfx_size_set(ep->object, EINA_SIZE2D(pf->final.w, pf->final.h));
+             efl_gfx_size_set(ep->object, EINA_SIZE2D(pf->final.w, pf->final.h));
 #endif
 
              if (ep->nested_smart) /* Move, Resize all nested parts */
@@ -5322,14 +5031,10 @@ _edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int flags, Edje_Calc_Params *sta
                     }
                }
 
-             /* TIZEN_ONLY(20160920): Add fade_ellipsis feature to TEXTBLOCK, TEXT part. */
+                        /* TIZEN_ONLY_FEATURE: ellipsize.marquee, ellipsize.fade for TEXTBLOCK, TEXT part. */
              if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK ||
                  ep->part->type == EDJE_PART_TYPE_TEXT)
-               {
-                  //TIZEN_ONLY(20160923): introduction of text marquee
-                  _edje_text_marquee_apply(ed, ep, pf, (Edje_Part_Description_Text *) chosen_desc);
-                  //
-               }
+               _edje_text_ellipsize_apply(ed, ep, pf, (Edje_Part_Description_Text*) chosen_desc);
              /* END */
           }
      }
@@ -5368,3 +5073,1303 @@ _edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int flags, Edje_Calc_Params *sta
 #endif
 
 }
+
+
+
+/**************************************************************************************
+ *                                                                                    *
+ * 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.     *
+ * 20170725: fix wrong speed calculation for text marquee's duration.                 *
+ * 20170725: fix to apply loop_delay even if there is no loop limit.                  *
+ * 20170725: restore ellipsis state of TEXT part when marquee mode is NONE.           *
+ * 20170801: add text marquee duration set/get APIs for internal usages.              *
+ * 20170802: remove build warnings caused by unused parameter or variable.            *
+ * 20170804: add text marquee speed set/get APIs for internal usages.                 *
+ * 20170804: fixed top-aligned issue when marquee is started.                         *
+ * 20170818: move Text, Textblock object based on its original position in smart move *
+ * 20170830: fix valign issue when slide_roll style.                                  *
+ * 20170906: apply x/y offset to run marquee with short text                          *
+ * 20171109: import ellipsize features from Tizen with new TIZEN_ONLY tags.           *
+ *                                                                                    *
+ **************************************************************************************/
+#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)
+     {
+        Evas_Object *smart_parent;
+        Evas_Object *mask_obj;
+        char buf[1024];
+        int iw = 0;
+
+        smart_parent = evas_object_smart_parent_get(ep->object);
+
+#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
+        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 (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;
+     }
+
+   return ep->typedata.text->ellipsize.fade.mask_obj;
+}
+
+void
+_edje_text_ellipsize_marquee_remove(Edje_Real_Part *ep)
+{
+   if (!ep || !ep->typedata.text) return;
+
+   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;
+     }
+
+   if (ep->typedata.text->ellipsize.marquee.animator)
+     {
+        ecore_animator_del(ep->typedata.text->ellipsize.marquee.animator);
+        ep->typedata.text->ellipsize.marquee.animator = NULL;
+     }
+
+   ep->typedata.text->ellipsize.marquee.loop_count = 0;
+   ep->typedata.text->ellipsize.marquee.distance = 0;
+}
+
+void
+_edje_text_ellipsize_fade_remove(Edje_Real_Part *ep)
+{
+   if (!ep || !ep->typedata.text) return;
+
+   if (ep->typedata.text->ellipsize.fade.animator)
+     {
+        ecore_animator_del(ep->typedata.text->ellipsize.fade.animator);
+        ep->typedata.text->ellipsize.fade.animator = NULL;
+     }
+
+   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;
+
+   _edje_text_ellipsize_marquee_remove(ep);
+   _edje_text_ellipsize_fade_remove(ep);
+
+   if (ep->typedata.text->ellipsize.clipper_obj)
+     {
+        evas_object_del(ep->typedata.text->ellipsize.clipper_obj);
+        ep->typedata.text->ellipsize.clipper_obj = NULL;
+     }
+}
+/* END */
+
+/* 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_Text_Ellipsize_Align ellip_align, Eina_Bool is_normal, double *halign, double *valign)
+{
+   Evas_BiDi_Direction bidi_dir;
+   Eina_Bool is_multiline = EINA_FALSE;
+   double valign_ret = -1.0;
+   double halign_ret = -1.0;
+
+   if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK)
+     {
+        Evas_Textblock_Cursor *cur;
+
+        cur = evas_object_textblock_cursor_new(ep->object);
+
+        bidi_dir = evas_textblock_cursor_paragraph_direction_get(cur);
+        is_multiline = evas_textblock_cursor_line_set(cur, 1);
+
+        evas_textblock_cursor_free(cur);
+     }
+   else
+     {
+        bidi_dir = evas_object_text_direction_get(ep->object);
+     }
+
+   /* 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 (is_normal)
+     {
+        /* variable for improving readability */
+        double text_ellipsis_end;
+        double text_ellipsis_start;
+
+        if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK)
+          {
+             text_ellipsis_end = 1.0;
+             text_ellipsis_start = 0.0;
+          }
+        else
+          {
+             text_ellipsis_end = 0.0;
+             text_ellipsis_start = 1.0;
+          }
+
+        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;
+
+        text_ellipsis_left = 0.0;
+        text_ellipsis_right = 1.0;
+
+        switch (ellip_align)
+          {
+           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;
+          }
+     }
+
+   if (is_multiline)
+     {
+        /* variable for improving readability */
+        double text_ellipsis_top;
+        double text_ellipsis_bottom;
+
+        text_ellipsis_top = 0.0;
+        text_ellipsis_bottom = 1.0;
+
+        /* 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 (halign)
+     *halign = halign_ret;
+
+   if (valign)
+     *valign = valign_ret;
+}
+
+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;
+
+        smart_parent = evas_object_smart_parent_get(ep->object);
+        evas_object_color_get(ep->object, &pr, &pg, &pb, &pa);
+
+        if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK)
+          {
+             const Evas_Textblock_Style *st = evas_object_textblock_style_get(ep->object);
+             double valign = evas_object_textblock_valign_get(ep->object);
+
+             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);
+             evas_object_textblock_valign_set(p_obj, valign);
+          }
+        else
+          {
+             const char *font = NULL;
+             int font_size = 0;
+             Evas_Text_Style_Type style;
+             int tr, tg, tb, ta;
+
+             evas_object_text_font_get(ep->object, &font, &font_size);
+             style = evas_object_text_style_get(ep->object);
+
+             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);
+
+             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);
+
+             evas_object_text_text_set(p_obj, ep->typedata.text->text);
+          }
+
+        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
+          evas_object_clip_set(p_obj, ep->typedata.text->ellipsize.clipper_obj);
+
+        if (ep->typedata.text->ellipsize.is_normal)
+          evas_object_textblock_ellipsis_set(p_obj,
+                                             evas_object_textblock_ellipsis_get(ep->object));
+
+        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;
+
+   evas_object_geometry_get(ep->typedata.text->ellipsize.clipper_obj, &cx, &cy, &cw, &ch);
+
+   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;
+
+   evas_object_geometry_get(ep->object, &tx, &ty, NULL, NULL);
+   tx += ep->typedata.text->ellipsize.offset_x;
+   ty += ep->typedata.text->ellipsize.offset_y;
+   tw = ep->typedata.text->ellipsize.text_w;
+   th = ep->typedata.text->ellipsize.text_h;
+
+   /* 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;
+     }
+
+   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;
+     }
+
+   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;
+     }
+
+   if (ep->typedata.text->ellipsize.marquee.proxy_obj &&
+       evas_object_visible_get(ep->typedata.text->ellipsize.marquee.proxy_obj))
+     {
+        evas_object_geometry_get(ep->typedata.text->ellipsize.marquee.proxy_obj,
+                                 &tx, &ty, NULL, NULL);
+        tx += ep->typedata.text->ellipsize.offset_x;
+        ty += ep->typedata.text->ellipsize.offset_y;
+
+        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;
+          }
+
+        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;
+          }
+
+        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->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 (anim)
+     {
+        if (!ep->typedata.text->ellipsize.fade.animator)
+          ep->typedata.text->ellipsize.fade.animator = ecore_animator_add(_edje_text_ellipsize_fade_animator_cb, ep);
+     }
+   else
+     {
+        if (ep->typedata.text->ellipsize.fade.animator)
+          {
+             ecore_animator_del(ep->typedata.text->ellipsize.fade.animator);
+             ep->typedata.text->ellipsize.fade.animator = NULL;
+          }
+
+        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);
+     }
+}
+
+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 *ed = ep->typedata.text->ellipsize.marquee.edje;
+   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;
+
+   evas_object_geometry_get(ep->object, &text_cur_area.x, &text_cur_area.y,
+                            &text_cur_area.w, &text_cur_area.h);
+
+   if (ep->typedata.text->ellipsize.valign != -1.0)
+     text_marquee_vertical = EINA_TRUE;
+   else
+     text_marquee_vertical = EINA_FALSE;
+
+   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;
+     }
+
+   evas_object_geometry_get(clipper_obj,
+                            &clipper_area.x, &clipper_area.y,
+                            &clipper_area.w, &clipper_area.h);
+
+   cur_time = ecore_time_get();
+   elapsed_time = cur_time - ep->typedata.text->ellipsize.marquee.animator_prev_time;
+
+   /* 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++;
+          }
+
+        ep->typedata.text->ellipsize.marquee.animator_prev_time = cur_time - elapsed_time;
+     }
+
+   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;
+        Edje_Text_Ellipsize_Marquee_Type marquee_type;
+        int offset = 0;
+
+        if (text_marquee_vertical)
+          {
+             clipper_pos = clipper_area.y;
+             clipper_length = clipper_area.h;
+             text_pos = text_cur_area.y;
+             text_length = ep->typedata.text->ellipsize.text_h;
+             offset = ep->typedata.text->ellipsize.offset_y;
+          }
+        else
+          {
+             clipper_pos = clipper_area.x;
+             clipper_length = clipper_area.w;
+             text_pos = text_cur_area.x;
+             text_length = ep->typedata.text->ellipsize.text_w;
+             offset = ep->typedata.text->ellipsize.offset_x;
+          }
+
+        marquee_type = chosen_desc->text.ellipsize.marquee.type;
+
+        /* Calculate basic information of a loop according to marquee type */
+        switch (marquee_type)
+          {
+           case EDJE_TEXT_ELLIPSIZE_MARQUEE_TYPE_ROLL:
+              if (clipper_length - text_length - offset > roll_gap)
+                roll_gap = clipper_length - text_length - offset;
+
+              distance_per_loop = text_length + roll_gap;
+
+              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;
+
+              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;
+                }
+          }
+
+        loop_jump_from_pos -= offset;
+        loop_jump_to_pos -= offset;
+
+        /* Calculate new x, y position according to current marquee direction */
+        if (text_marquee_top_left)
+          {
+             text_pos -= move_pixel;
+
+             /* 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;
+
+             /* 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;
+               }
+          }
+
+        /* Update moved distance which is used to update loop count */
+        ep->typedata.text->ellipsize.marquee.distance += move_pixel;
+
+        /* 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;
+
+             /* 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;
+
+                  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;
+
+                  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;
+                    }
+
+                  ep->typedata.text->ellipsize.marquee.distance += overpixel_for_loop;
+               }
+
+             /* Emit a signal when a loop(or loops) is done. */
+             _edje_emit(ed, "text,ellipsize,marquee,loop", ep->part->name);
+          }
+
+        /* Check if the loop count reaches the given loop limit. */
+        if ((chosen_desc->text.ellipsize.marquee_repeat_limit > 0) &&
+            (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);
+
+             ep->typedata.text->ellipsize.marquee.animator = NULL;
+             _edje_text_ellipsize_marquee_remove(ep);
+             _edje_text_ellipsize_fade_update(ep, EINA_TRUE);
+
+             /* Emit a signal when all loops are done. */
+             _edje_emit(ed, "text,ellipsize,marquee,done", ep->part->name);
+
+             return ECORE_CALLBACK_DONE;
+          }
+
+        if (text_marquee_top_left)
+          text_pos -= overpixel_for_loop;
+        else
+          text_pos += overpixel_for_loop;
+
+        /* If current marquee type needs a proxy object, update it, too. */
+        if (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);
+          }
+
+        if (text_marquee_vertical)
+          text_cur_area.y = text_pos;
+        else
+          text_cur_area.x = text_pos;
+
+        /* Update Textblock/Text object using updated position */
+        evas_object_move(ep->object, text_cur_area.x, text_cur_area.y);
+
+        _edje_text_ellipsize_fade_update(ep, EINA_TRUE);
+     }
+
+   return ECORE_CALLBACK_RENEW;
+}
+
+static void
+_edje_text_ellipsize_position_offset_get(Edje_Real_Part *ep,
+                                         int pw, int ph, int tw, int th,
+                                         int *x_offset, int *y_offset)
+{
+   int ret_x = 0, ret_y = 0;
+
+   if ((tw >= pw) && (th >= ph)) return;
+
+   if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK)
+     {
+        Evas_Textblock_Cursor *cur;
+        int lx, ly, lw, lh;
+
+        /* FIXME: It does not make sense for horizontal marquee of multiline Textblock */
+        cur = evas_object_textblock_cursor_new(ep->object);
+        evas_textblock_cursor_line_geometry_get(cur, &lx, &ly, &lw, &lh);
+        evas_textblock_cursor_free(cur);
+
+        ret_x = lx;
+        ret_y = ly;
+     }
+   else
+     {
+        ret_x = ep->typedata.text->offset.x;
+        ret_y = ep->typedata.text->offset.y;
+     }
+
+   if (x_offset && (pw > tw)) *x_offset = ret_x;
+   if (y_offset && (ph > th)) *y_offset = ret_y;
+}
+
+static void
+_edje_text_ellipsize_update_legacy_mode(Edje_Part_Description_Text *chosen_desc)
+{
+   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))
+     chosen_desc->text.ellipsize.fade.mode = EDJE_TEXT_ELLIPSIZE_FADE_MODE_ON;
+
+   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.mode = EDJE_TEXT_ELLIPSIZE_MARQUEE_MODE_ON;
+
+   if (chosen_desc->text.ellipsize.mode == EDJE_TEXT_ELLIPSIZE_MODE_NORMAL)
+     chosen_desc->text.ellipsize.normal.mode = EDJE_TEXT_ELLIPSIZE_NORMAL_MODE_ON;
+
+   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;
+}
+
+/*
+ * _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 is_normal = EINA_FALSE;
+   Eina_Bool is_fade = EINA_FALSE;
+   Eina_Bool is_marquee = EINA_FALSE;
+   Eina_Bool ellipsis_status = 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;
+   int resize_w, resize_h;
+   int offset_x, offset_y;
+
+   if ((ep->part->type != EDJE_PART_TYPE_TEXTBLOCK) &&
+       (ep->part->type != EDJE_PART_TYPE_TEXT))
+     return;
+
+   if (!pf || !pf->type.text)
+     {
+        ERR("Edje ellipsize: pf[%p] or pf->type.text is NULL. Do nothing for the ellipsize feature.", pf);
+        return;
+     }
+
+   /* Reset clipper objects from Edje.
+    * It should be same as other code for setting default clipper in Edje. */
+   if (pf->ext && pf->ext->clip_to && pf->ext->clip_to->object)
+     evas_object_clip_set(ep->object, pf->ext->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);
+
+   if (ep->typedata.text->ellipsize.fade.animator)
+     {
+        ecore_animator_del(ep->typedata.text->ellipsize.fade.animator);
+        ep->typedata.text->ellipsize.fade.animator = NULL;
+     }
+
+   if (ep->typedata.text->ellipsize.marquee.animator)
+     {
+        _edje_text_ellipsize_marquee_remove(ep);
+        _edje_text_ellipsize_fade_update(ep, EINA_FALSE);
+     }
+
+   /* Update ellipsize properties using legacy properties. */
+   _edje_text_ellipsize_update_legacy_mode(chosen_desc);
+
+   if (chosen_desc->text.ellipsize.normal.mode == EDJE_TEXT_ELLIPSIZE_NORMAL_MODE_ON)
+     is_normal = EINA_TRUE;
+
+   /* Enable fade if one of fade types is set or legacy fade_ellipsis option is set */
+   if (chosen_desc->text.ellipsize.fade.mode == EDJE_TEXT_ELLIPSIZE_FADE_MODE_ON)
+     is_fade = EINA_TRUE;
+
+   /* Enable marquee if one of marquee types is set and loop count is bigger than zero */
+   if ((chosen_desc->text.ellipsize.marquee.mode >= EDJE_TEXT_ELLIPSIZE_MARQUEE_MODE_ON) &&
+       (chosen_desc->text.ellipsize.marquee_repeat_limit != 0))
+     is_marquee = EINA_TRUE;
+
+   /* Hide ellipsize clipper and mask object all options are disabled. */
+   if ((pf->final.w == 0) || (pf->final.h == 0) ||
+       !(is_normal || is_fade || is_marquee))
+     {
+        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);
+          }
+
+        /* 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,
+                                        chosen_desc->text.min_x ? -1.0 : pf->type.text->ellipsis);
+
+        if (is_marquee)
+          {
+             /* Emit a signal when text is too short to do slide. */
+             _edje_emit(ed, "text,ellipsize,marquee,none", ep->part->name);
+          }
+
+        return;
+     }
+
+   /* Enable normal ellipsis */
+   if (is_normal)
+     {
+        /* Get align only for normal ellipsis */
+        _edje_text_ellipsize_align_get(ep, chosen_desc->text.ellipsize.align, EINA_TRUE, &halign, NULL);
+
+        if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK)
+          {
+             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);
+          }
+
+        /* Skip the rest of code if only normal mode is turned on. */
+        if (!(is_fade || is_marquee))
+          {
+             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;
+          }
+     }
+   else
+     {
+        /* 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);
+     }
+
+   /* Get size of contents. If normal mode is off, disable ellipsis and get whole size. */
+   if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK)
+     {
+        ellipsis_status = evas_object_textblock_ellipsis_status_get(ep->object);
+
+        if (ellipsis_status && !is_normal)
+          evas_object_textblock_ellipsis_disabled_set(ep->object, EINA_TRUE);
+
+        evas_object_textblock_size_formatted_get(ep->object, &tw, &th);
+
+        if (ellipsis_status && !is_normal)
+          evas_object_textblock_ellipsis_disabled_set(ep->object, EINA_FALSE);
+     }
+   else
+     {
+        ellipsis_status = evas_object_text_ellipsis_status_get(ep->object);
+
+        if (ellipsis_status && !is_normal)
+          tw = evas_object_text_horiz_width_without_ellipsis_get(ep->object);
+        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 ((chosen_desc->text.ellipsize.marquee.mode != EDJE_TEXT_ELLIPSIZE_MARQUEE_MODE_ALWAYS) &&
+       ((tw <= pf->final.w) && (th <= pf->final.h)))
+     {
+        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);
+          }
+
+        if (is_marquee)
+          {
+             /* Emit a signal when text is too short to do slide. */
+             _edje_emit(ed, "text,ellipsize,marquee,none", ep->part->name);
+          }
+
+        return;
+     }
+
+   /* Add a cllipper object */
+   if (!ep->typedata.text->ellipsize.clipper_obj)
+     {
+        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);
+     }
+
+   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;
+
+   /* Get alignment of ellipsize according to ellipsize.align and Text/Textblock's status */
+   _edje_text_ellipsize_align_get(ep, chosen_desc->text.ellipsize.align, EINA_FALSE, &halign, &valign);
+
+   if ((halign == 0.0) && (tw > pf->final.w))
+     tx = ed->x + pf->final.x + pf->final.w - tw;
+   else
+     tx = ed->x + pf->final.x;
+
+   if ((valign == 0.0) && (th > pf->final.h))
+     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_normal = is_normal;
+   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)
+     {
+        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);
+     }
+
+   evas_object_resize(clipper_obj, clipper_w, clipper_h);
+   evas_object_move(clipper_obj, clipper_x, clipper_y);
+   evas_object_show(clipper_obj);
+
+   resize_w = (pf->final.w > tw) ? pf->final.w : tw;
+   resize_h = (pf->final.h > th) ? pf->final.h : th;
+   evas_object_resize(ep->object, resize_w, resize_h);
+   evas_object_move(ep->object, tx, ty);
+
+   offset_x = offset_y = 0;
+   _edje_text_ellipsize_position_offset_get(ep,
+                                            pf->final.w, pf->final.h, tw, th,
+                                            &offset_x, &offset_y);
+   ep->typedata.text->ellipsize.offset_x = offset_x;
+   ep->typedata.text->ellipsize.offset_y = offset_y;
+
+   if (is_marquee)
+     {
+        double duration = chosen_desc->text.ellipsize.marquee.duration;
+        double speed = chosen_desc->text.ellipsize.marquee.speed;
+        Eina_Bool text_marquee_vertical;
+
+        if (valign != -1.0)
+          text_marquee_vertical = EINA_TRUE;
+        else
+          text_marquee_vertical = EINA_FALSE;
+
+        if (ep->typedata.text->ellipsize.marquee.duration > 0.0)
+          duration = ep->typedata.text->ellipsize.marquee.duration;
+
+        if (ep->typedata.text->ellipsize.marquee.speed > 0.0)
+          speed = ep->typedata.text->ellipsize.marquee.speed;
+
+        if (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 / (speed * TO_DOUBLE(sc));
+          }
+        else if (duration > 0.0)
+          {
+             /* Convert sec_per_loop (duration) to sec_per_pixel */
+             int distance_per_loop = 0.0;
+             int text_length;
+             int clipper_length;
+             int offset;
+
+             if (text_marquee_vertical)
+               {
+                  clipper_length = clipper_h;
+                  text_length = th;
+                  offset = offset_y;
+               }
+             else
+               {
+                  clipper_length = clipper_w;
+                  text_length = tw;
+                  offset = offset_x;
+               }
+
+             switch (chosen_desc->text.ellipsize.marquee.type)
+               {
+                case EDJE_TEXT_ELLIPSIZE_MARQUEE_TYPE_ROLL:
+                   if (clipper_length - text_length - offset > roll_gap)
+                     roll_gap = clipper_length - text_length - offset;
+
+                   distance_per_loop = text_length + roll_gap;
+                   break;
+                case EDJE_TEXT_ELLIPSIZE_MARQUEE_TYPE_DEFAULT:
+                default:
+                   distance_per_loop = text_length + clipper_length;
+               }
+
+             ep->typedata.text->ellipsize.marquee.sec_per_pixel = 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;
+        ep->typedata.text->ellipsize.marquee.edje = ed;
+
+        /* 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);
+     }
+
+   if (is_fade)
+     _edje_text_ellipsize_fade_update(ep, EINA_FALSE);
+}
+
+/**************************************************************************************
+ *                                                                                    *
+ * TIZEN_ONLY_FEATURE_END: ellipsize.marquee, ellipsize.fade for TEXTBLOCK, TEXT part.*
+ *                                                                                    *
+ **************************************************************************************/
index bb92cc3..dca8f05 100644 (file)
@@ -1177,13 +1177,26 @@ _edje_edd_init(void)
    EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_text, Edje_Part_Description_Text, "text.id_text_source", text.id_text_source, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_text, Edje_Part_Description_Text, "text.id_text_source_part", text.id_text_source_part, EET_T_STRING);
    EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_text, Edje_Part_Description_Text, "text.ellipsis", text.ellipsis, EET_T_DOUBLE);
-   //TIZEN_ONLY(20160923): introduction of text marquee
-   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);
-   //
    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
+   /***********************************************************************************
+    * TIZEN_ONLY_FEATURE: ellipsize.marquee, ellipsize.fade for TEXTBLOCK, TEXT part. *
+    ***********************************************************************************/
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_text, Edje_Part_Description_Text, "text.fade_ellipsis", text.fade_ellipsis, EET_T_DOUBLE);
+   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);
+   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);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_text, Edje_Part_Description_Text, "text.ellipsize.normal.mode", text.ellipsize.normal.mode, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_text, Edje_Part_Description_Text, "text.ellipsize.fade.mode", text.ellipsize.fade.mode, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_text, Edje_Part_Description_Text, "text.ellipsize.marquee.mode", text.ellipsize.marquee.mode, EET_T_INT);
+   /*******
+    * END *
+    *******/
 
    EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Edje_Part_Description_Text);
    eddc.func.mem_free = mem_free_textblock;
@@ -1217,10 +1230,23 @@ _edje_edd_init(void)
    EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.id_text_source", text.id_text_source, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.id_text_source_part", text.id_text_source_part, EET_T_STRING);
    EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.ellipsis", text.ellipsis, EET_T_DOUBLE);
-   //TIZEN_ONLY(20160923): introduction of text marquee
+   /***********************************************************************************
+    * TIZEN_ONLY_FEATURE: ellipsize.marquee, ellipsize.fade for TEXTBLOCK, TEXT part. *
+    ***********************************************************************************/
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.fade_ellipsis", text.fade_ellipsis, EET_T_DOUBLE);
    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);
-   //
+   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);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.ellipsize.normal.mode", text.ellipsize.normal.mode, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.ellipsize.fade.mode", text.ellipsize.fade.mode, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.ellipsize.marquee.mode", text.ellipsize.marquee.mode, EET_T_INT);
+   /*******
+    * END *
+    *******/
 
    EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Edje_Part_Description_Box);
    eddc.func.mem_free = mem_free_box;
index cf207a9..2ab005b 100644 (file)
@@ -1950,6 +1950,9 @@ _edje_file_del(Edje *ed)
                   eina_stringshare_del(rp->typedata.text->font);
                   eina_stringshare_del(rp->typedata.text->cache.in_str);
                   eina_stringshare_del(rp->typedata.text->cache.out_str);
+                  /* TIZEN_ONLY_FEATURE: ellipsize.marquee, ellipsize.fade for TEXTBLOCK, TEXT part. */
+                  _edje_text_ellipsize_remove(rp);
+                  /* END */
                   free(rp->typedata.text);
                   rp->typedata.text = NULL;
                }
index f801a0c..1cff50d 100644 (file)
@@ -1465,14 +1465,38 @@ struct _Edje_Part_Description_Spec_Text
    unsigned char  max_x; /* if text size should be part max size */
    unsigned char  max_y; /* if text size should be part max size */
 
-   //TIZEN_ONLY(20160923): introduction of text marquee
+   /***********************************************************************************
+    * TIZEN_ONLY_FEATURE: ellipsize.marquee, ellipsize.fade for TEXTBLOCK, TEXT part. *
+    ***********************************************************************************/
+   double         fade_ellipsis;
+
    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 */
+
+      Edje_Text_Ellipsize_Align align;
+
+      struct {
+         Edje_Text_Ellipsize_Marquee_Type type;
+         double                           loop_delay;
+         double                           speed;
+         double                           duration;
+         Edje_Text_Ellipsize_Marquee_Mode mode;
+      } marquee;
+
+      struct {
+         Edje_Text_Ellipsize_Normal_Mode mode;
+      } normal;
+
+      struct {
+         Edje_Text_Ellipsize_Fade_Mode mode;
+      } fade;
    } ellipsize;
-   //
+   /*******
+    * END *
+    *******/
 };
 
 struct _Edje_Part_Description_Spec_Box
@@ -1992,6 +2016,48 @@ struct _Edje_Real_Part_Text
    const char            *style; // 4
    Edje_Position          offset; // 8
    short                  size; // 2
+
+   /***********************************************************************************
+    * TIZEN_ONLY_FEATURE: ellipsize.marquee, ellipsize.fade for TEXTBLOCK, TEXT part. *
+    ***********************************************************************************/
+   struct {
+      double                 duration; // 8
+   } marquee;
+
+   struct {
+      Evas_Object    *clipper_obj; // 4
+      float           halign;      // 4
+      float           valign;      // 4
+      int             text_w, text_h;
+      int             offset_x, offset_y;
+      Eina_Bool       is_normal;
+      Eina_Bool       is_fade;
+      Eina_Bool       is_marquee;
+
+      struct {
+         Evas_Object    *mask_obj;
+         Ecore_Animator *animator;
+         int             x, y, w, h;
+      } fade;
+
+      struct {
+         Edje           *edje;
+         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;
+
+         double          duration;
+         double          speed;
+      } marquee;
+   } ellipsize;
+   /*******
+    * END *
+    *******/
+
    struct {
       unsigned char       fit_x, fit_y; // 2
       short               in_size; // 2
@@ -2060,12 +2126,6 @@ struct _Edje_Real_Part
    unsigned short            state; // 2
 #endif
    char                      clicked_button; // 1
-   //TIZEN_ONLY(20160923): introduction of text marquee
-   double                    text_marquee_prev_time;
-   Ecore_Animator           *text_marquee_animator;
-   Ecore_Job                *text_marquee_job;
-   Evas_Object              *text_marquee_clipper;
-   //
    unsigned char             type; // 1
    Evas_Event_Flags          ignore_flags;
    Evas_Event_Flags          mask_flags;
@@ -2077,9 +2137,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;
-   //
 }; // 128
 // WITH EDJE_CALC_CACHE: 407
 
@@ -3169,6 +3226,9 @@ Evas_Event_Flags _edje_real_part_ignore_flags_get(Edje *ed, Edje_Real_Part *rp);
 void _edje_real_part_ignore_flags_set(Edje *ed, Edje_Real_Part *rp, Evas_Event_Flags ignore_flags);
 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_FEATURE: ellipsize.marquee, ellipsize.fade for TEXTBLOCK, TEXT part. */
+void _edje_text_ellipsize_remove(Edje_Real_Part *ep);
+/* END */
 
 /* part drag apis */
 Edje_Drag_Dir _edje_object_part_drag_dir_get(Edje *ed, const char *part);
index 3ca56d4..5cda974 100644 (file)
@@ -154,28 +154,55 @@ _efl_canvas_layout_efl_canvas_group_group_del(Eo *obj, Edje *ed)
    efl_canvas_group_del(efl_super(obj, MY_CLASS));
 }
 
-//TIZEN_ONLY(20160923): introduction of text marquee
+/***********************************************************************************
+ * TIZEN_ONLY_FEATURE: ellipsize.marquee, ellipsize.fade for TEXTBLOCK, TEXT part. *
+ ***********************************************************************************/
 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;
-
-   chosen_desc = (Edje_Part_Description_Text *)ep->chosen_description;
+   Evas_Coord x = 0, y = 0;
 
    evas_object_geometry_get(ep->object, &x, &y, NULL, NULL);
 
-   /* 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);
+   x += ed_diff.x;
+   y += ed_diff.y;
+
+   /* ed_diff should be handled because of marquee */
+   ep->typedata.text->ellipsize.marquee.orig_x += ed_diff.x;
+   ep->typedata.text->ellipsize.marquee.orig_y += ed_diff.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);
 }
-//
+/*******
+ * END *
+ *******/
 
 EOLIAN static void
 _efl_canvas_layout_efl_gfx_position_set(Eo *obj, Edje *ed, Eina_Position2D pos)
@@ -185,11 +212,11 @@ _efl_canvas_layout_efl_gfx_position_set(Eo *obj, Edje *ed, Eina_Position2D pos)
    if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_MOVE, 0, pos.x, pos.y))
      return;
 
-   //TIZEN_ONLY(20160923): introduction of text marquee
+   /* TIZEN_ONLY_FEATURE: ellipsize.marquee, ellipsize.fade for TEXTBLOCK, TEXT part. */
    Evas_Coord_Point ed_diff;
    ed_diff.x = pos.x - ed->x;
    ed_diff.y = pos.y - ed->y;
-   //
+   /* END */
 
    efl_gfx_position_set(efl_super(obj, MY_CLASS), pos);
 
@@ -211,23 +238,23 @@ _efl_canvas_layout_efl_gfx_position_set(Eo *obj, Edje *ed, Eina_Position2D pos)
         ep = ed->table_parts[i];
         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);
+             /* TIZEN_ONLY_FEATURE: ellipsize.marquee, ellipsize.fade for TEXTBLOCK, TEXT part.
+             evas_object_move(ep->object,
+                              ed->x + ep->x + ep->typedata.text->offset.x,
+                              ed->y + ep->y + ep->typedata.text->offset.y);
+              */
+             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,
                                 ed->x + ep->x + ep->typedata.text->offset.x,
                                 ed->y + ep->y + ep->typedata.text->offset.y);
+             /* END */
           }
         else
           {
-             //TIZEN_ONLY(20160923): introduction of text marquee
-             if (ep->text_marquee_animator)
-               _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))
index 402a3e2..562bd56 100644 (file)
@@ -218,11 +218,11 @@ _edje_text_recalc_apply(Edje *ed, Edje_Real_Part *ep,
    Eina_Bool same_text = EINA_FALSE;
    FLOAT_T sc;
 
-   //TIZEN_ONLY(20160923): introduction of text marquee
-   //Necessary for state having EDJE_TEXT_ELLIPSIZE_MODE_MARQUEE by default
+   /* TIZEN_ONLY_FEATURE: ellipsize.marquee, ellipsize.fade for TEXTBLOCK, TEXT part. *
+    * Necessary for state having EDJE_TEXT_ELLIPSIZE_MODE_MARQUEE by default          */
    if (chosen_desc->text.ellipsize.mode == EDJE_TEXT_ELLIPSIZE_MODE_MARQUEE)
      params->type.text->ellipsis = -1;
-   //
+   /* END */
 
    if ((ep->type != EDJE_RP_TYPE_TEXT) ||
        (!ep->typedata.text)) return;
index 258a749..a87caa7 100644 (file)
@@ -6281,4 +6281,112 @@ edje_object_part_text_get(const Edje_Object *obj, const char *part)
    return _edje_efl_text_get((Eo *)obj, ed, part, EINA_TRUE, EINA_FALSE);
 }
 
+/***********************************************************************************
+ * TIZEN_ONLY_FEATURE: ellipsize.marquee, ellipsize.fade for TEXTBLOCK, TEXT part. *
+ ***********************************************************************************/
+EOLIAN Eina_Bool
+_edje_object_part_text_marquee_duration_set(Eo *eo_obj EINA_UNUSED, Edje *ed, const char *part, double duration)
+{
+   Edje_Real_Part *rp;
+
+   if (!part) return EINA_FALSE;
+   rp = _edje_real_part_recursive_get(&ed, part);
+   if (!rp) return EINA_FALSE;
+   if ((rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) &&
+       (rp->part->type != EDJE_PART_TYPE_TEXT))
+     return EINA_FALSE;
+
+   if (rp->typedata.text)
+     {
+        rp->typedata.text->ellipsize.marquee.duration = duration;
+
+        return EINA_TRUE;
+     }
+
+   return EINA_FALSE;
+}
+
+EOLIAN double
+_edje_object_part_text_marquee_duration_get(Eo *eo_obj EINA_UNUSED, Edje *ed, const char *part)
+{
+   Edje_Real_Part *rp;
+   Edje_Part_Description_Text *desc;
+
+   if (!part) return -1.0;
+   rp = _edje_real_part_recursive_get(&ed, part);
+   if (!rp) return -1.0;
+   if ((rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) &&
+       (rp->part->type != EDJE_PART_TYPE_TEXT))
+     return -1.0;
+
+   if (rp->typedata.text)
+     {
+        if (rp->typedata.text->ellipsize.marquee.duration <= 0.0)
+          {
+             desc = (Edje_Part_Description_Text *)rp->chosen_description;
+             return desc->text.ellipsize.marquee.duration;
+          }
+        else
+          {
+             return rp->typedata.text->ellipsize.marquee.duration;
+          }
+     }
+
+   return -1.0;
+}
+
+EOLIAN Eina_Bool
+_edje_object_part_text_marquee_speed_set(Eo *eo_obj EINA_UNUSED, Edje *ed, const char *part, double speed)
+{
+   Edje_Real_Part *rp;
+
+   if (!part) return EINA_FALSE;
+   rp = _edje_real_part_recursive_get(&ed, part);
+   if (!rp) return EINA_FALSE;
+   if ((rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) &&
+       (rp->part->type != EDJE_PART_TYPE_TEXT))
+     return EINA_FALSE;
+
+   if (rp->typedata.text)
+     {
+        rp->typedata.text->ellipsize.marquee.speed = speed;
+
+        return EINA_TRUE;
+     }
+
+   return EINA_FALSE;
+}
+
+EOLIAN double
+_edje_object_part_text_marquee_speed_get(Eo *eo_obj EINA_UNUSED, Edje *ed, const char *part)
+{
+   Edje_Real_Part *rp;
+   Edje_Part_Description_Text *desc;
+
+   if (!part) return -1.0;
+   rp = _edje_real_part_recursive_get(&ed, part);
+   if (!rp) return -1.0;
+   if ((rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) &&
+       (rp->part->type != EDJE_PART_TYPE_TEXT))
+     return -1.0;
+
+   if (rp->typedata.text)
+     {
+        if (rp->typedata.text->ellipsize.marquee.speed <= 0.0)
+          {
+             desc = (Edje_Part_Description_Text *)rp->chosen_description;
+             return desc->text.ellipsize.marquee.speed;
+          }
+        else
+          {
+             return rp->typedata.text->ellipsize.marquee.speed;
+          }
+     }
+
+   return -1.0;
+}
+/*******
+ * END *
+ *******/
+
 /* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/