hermet pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=bf7e05586f002aa66688c37eabcd3a44f847ee16

commit bf7e05586f002aa66688c37eabcd3a44f847ee16
Author: Hermet Park <[email protected]>
Date:   Mon Jul 22 16:47:43 2019 +0900

    efl_ui_textpath: introduce efl_ui_textpath_circular_set() interface.
    
    Summary:
    This patch revises efl_ui_textpath_circle_set() interface.
    
    Current circle_set() behavior is wrongly working,
    it makes object minimal size with (x * 2, y * 2).
    Insanely, how big size if the object is far from the screen origin.
    
    Secondly, current interface requires center position,
    How this center position could be guranteed if user wants to put it into a 
container?
    
    Third, actual textpath output could be out of the textpath boundary,
    since the textpath is originated to middle of text height.
    the display boundary can be outside of the textpath geometry by (half of 
text height).
    
    All in all, put altogether in fix,
    I confirmed there is no methods without any compatibility break.
    
    This brings elm_textpath_circular_set() api introduced.
    
    @feature
    
    Reviewers: #committers, kimcinoo, jsuya
    
    Subscribers: zmike, bu5hm4n, segfaultxavi, cedric, #reviewers, #committers
    
    Tags: #efl
    
    Differential Revision: https://phab.enlightenment.org/D9260
---
 src/bin/elementary/test_ui_textpath.c          |  10 +-
 src/lib/elementary/efl_ui_textpath.c           | 163 ++++++++++++++++++++-----
 src/lib/elementary/efl_ui_textpath.eo          |   7 +-
 src/lib/elementary/efl_ui_textpath_eo.legacy.c |   5 +-
 src/lib/elementary/efl_ui_textpath_eo.legacy.h |  16 +++
 5 files changed, 156 insertions(+), 45 deletions(-)

diff --git a/src/bin/elementary/test_ui_textpath.c 
b/src/bin/elementary/test_ui_textpath.c
index e4756996f3..111ebe1af4 100644
--- a/src/bin/elementary/test_ui_textpath.c
+++ b/src/bin/elementary/test_ui_textpath.c
@@ -6,8 +6,6 @@
 #include <Efl_Ui.h>
 #include <Elementary.h>
 
-#define CX 180
-#define CY 150
 #define CR 100
 
 #define TEST_UI_TEXTPATH_LONG_TEXT "This text follows the path which you 
defined. This is a &lt;long&gt; text designed to make it ellipsis."
@@ -31,7 +29,7 @@ _direction_changed_cb(void *data, const Efl_Event *event)
    Eina_Bool val = elm_check_selected_get(event->object);
    Efl_Ui_Textpath_Direction dir = val ? EFL_UI_TEXTPATH_DIRECTION_CW :
                                          EFL_UI_TEXTPATH_DIRECTION_CCW;
-   efl_ui_textpath_circle_set(txtpath, CX, CY, CR, angle, dir);
+   efl_ui_textpath_circular_set(txtpath, CR, angle, dir);
 }
 
 static void
@@ -43,7 +41,7 @@ _angle_changed_cb(void *data, const Efl_Event *event)
    Eina_Bool val = elm_check_selected_get(dir_chk);
    Efl_Ui_Textpath_Direction dir = val ? EFL_UI_TEXTPATH_DIRECTION_CW :
                                          EFL_UI_TEXTPATH_DIRECTION_CCW;
-   efl_ui_textpath_circle_set(txtpath, CX, CY, CR, angle, dir);
+   efl_ui_textpath_circular_set(txtpath, CR, angle, dir);
 }
 
 static void
@@ -76,7 +74,7 @@ _change_shape_cb(void *data, Evas_Object *obj EINA_UNUSED, 
void *event_info EINA
         Eina_Bool val = elm_check_selected_get(dir_chk);
         Efl_Ui_Textpath_Direction dir = val ? EFL_UI_TEXTPATH_DIRECTION_CW :
                                               EFL_UI_TEXTPATH_DIRECTION_CCW;
-        efl_ui_textpath_circle_set(txtpath, CX, CY, CR, angle, dir);
+   efl_ui_textpath_circular_set(txtpath, CR, angle, dir);
      }
 }
 
@@ -109,7 +107,7 @@ test_ui_textpath(void *data EINA_UNUSED, Evas_Object *obj 
EINA_UNUSED, void *eve
 
    efl_text_set(txtpath, TEST_UI_TEXTPATH_LONG_TEXT);
 
-   efl_ui_textpath_circle_set(txtpath, CX, CY, CR, 0, 
EFL_UI_TEXTPATH_DIRECTION_CCW);
+   efl_ui_textpath_circular_set(txtpath, CR, 0, EFL_UI_TEXTPATH_DIRECTION_CCW);
    efl_gfx_entity_visible_set(txtpath, EINA_TRUE);
    path_type = 0;
 
diff --git a/src/lib/elementary/efl_ui_textpath.c 
b/src/lib/elementary/efl_ui_textpath.c
index c25410e1fc..aa89865a42 100644
--- a/src/lib/elementary/efl_ui_textpath.c
+++ b/src/lib/elementary/efl_ui_textpath.c
@@ -70,6 +70,7 @@ struct _Efl_Ui_Textpath_Data
 #ifdef EFL_UI_TEXTPATH_LINE_DEBUG
    Eina_List *lines;
 #endif
+   Eina_Bool circular : 1;   //TODO: Remove this flag when 
elm_textpath_circle_set() is removed.
 };
 
 #define EFL_UI_TEXTPATH_DATA_GET(o, sd) \
@@ -407,7 +408,7 @@ _path_data_get(Eo *obj, Efl_Ui_Textpath_Data *pd)
    const Efl_Gfx_Path_Command_Type *cmd;
    const double *points;
    Efl_Ui_Textpath_Segment *seg;
-   Eina_Position2D opos;
+   Eina_Position2D obj_pos;
 
    EINA_INLIST_FREE(pd->segments, seg)
      {
@@ -415,7 +416,16 @@ _path_data_get(Eo *obj, Efl_Ui_Textpath_Data *pd)
         free(seg);
      }
 
-   opos = efl_gfx_entity_position_get(obj);
+   obj_pos = efl_gfx_entity_position_get(obj);
+
+   /* textpath calculates boundary with the middle of text height.
+      this has better precise boundary than circle_set() behavior. */
+   if (pd->circular)
+     {
+        Eina_Size2D text_size = efl_gfx_entity_size_get(pd->text_obj);
+        obj_pos.x += (text_size.h / 2);
+        obj_pos.y += (text_size.h / 2);
+     }
 
    pd->total_length = 0;
    efl_gfx_path_get(obj, &cmd, &points);
@@ -430,9 +440,9 @@ _path_data_get(Eo *obj, Efl_Ui_Textpath_Data *pd)
              if (*cmd == EFL_GFX_PATH_COMMAND_TYPE_MOVE_TO)
                {
                   pos++;
-                  px0 = points[pos] + opos.x;
+                  px0 = points[pos] + obj_pos.x;
                   pos++;
-                  py0 = points[pos] + opos.y;
+                  py0 = points[pos] + obj_pos.y;
                }
              else if (*cmd == EFL_GFX_PATH_COMMAND_TYPE_CUBIC_TO)
                {
@@ -441,17 +451,17 @@ _path_data_get(Eo *obj, Efl_Ui_Textpath_Data *pd)
                   Eina_Rect brect;
 
                   pos++;
-                  ctrl_x0 = points[pos] + opos.x;
+                  ctrl_x0 = points[pos] + obj_pos.x;
                   pos++;
-                  ctrl_y0 = points[pos] + opos.y;
+                  ctrl_y0 = points[pos] + obj_pos.y;
                   pos++;
-                  ctrl_x1 = points[pos] + opos.x;
+                  ctrl_x1 = points[pos] + obj_pos.x;
                   pos++;
-                  ctrl_y1 = points[pos] + opos.y;
+                  ctrl_y1 = points[pos] + obj_pos.y;
                   pos++;
-                  px1 = points[pos] + opos.x;
+                  px1 = points[pos] + obj_pos.x;
                   pos++;
-                  py1 = points[pos] + opos.y;
+                  py1 = points[pos] + obj_pos.y;
 
                   eina_bezier_values_set(&bz, px0, py0, ctrl_x0, ctrl_y0, 
ctrl_x1, ctrl_y1, px1, py1);
                   seg = malloc(sizeof(Efl_Ui_Textpath_Segment));
@@ -481,9 +491,9 @@ _path_data_get(Eo *obj, Efl_Ui_Textpath_Data *pd)
                   Eina_Rect lrect;
 
                   pos++;
-                  px1 = points[pos] + opos.x;
+                  px1 = points[pos] + obj_pos.x;
                   pos++;
-                  py1 = points[pos] + opos.y;
+                  py1 = points[pos] + obj_pos.y;
 
                   seg = malloc(sizeof(Efl_Ui_Textpath_Segment));
                   if (!seg)
@@ -612,6 +622,7 @@ _path_start_angle_adjust(Eo *obj, Efl_Ui_Textpath_Data *pd)
    offset_angle /= 2.0;
 
    efl_gfx_path_reset(obj);
+
    if (pd->direction == EFL_UI_TEXTPATH_DIRECTION_CW_CENTER)
      {
         efl_gfx_path_append_arc(obj,
@@ -753,21 +764,22 @@ _efl_ui_textpath_efl_ui_widget_theme_apply(Eo *obj, 
Efl_Ui_Textpath_Data *pd)
 EOLIAN static void
 _efl_ui_textpath_efl_gfx_entity_position_set(Eo *obj, Efl_Ui_Textpath_Data 
*pd, Eina_Position2D pos)
 {
-   Eina_Position2D opos, diff;
+   Eina_Position2D ppos, diff;
    Efl_Ui_Textpath_Segment *seg;
    double sx, sy, csx, csy, cex, cey, ex, ey;
 
-   opos = efl_gfx_entity_position_get(obj);
+   ppos = efl_gfx_entity_position_get(obj);
+   efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), pos);
 
-   diff.x = pos.x - opos.x;
-   diff.y = pos.y - opos.y;
+   if (ppos.x == pos.x && ppos.y == pos.y) return;
 
-   efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), pos);
+   diff.x = pos.x - ppos.x;
+   diff.y = pos.y - ppos.y;
 
    EINA_INLIST_FOREACH(pd->segments, seg)
      {
         eina_bezier_values_get(&seg->bezier, &sx, &sy, &csx, &csy,
-                                             &cex, &cey, &ex, &ey);
+                               &cex, &cey, &ex, &ey);
         sx += diff.x;
         sy += diff.y;
         csx += diff.x;
@@ -778,53 +790,99 @@ _efl_ui_textpath_efl_gfx_entity_position_set(Eo *obj, 
Efl_Ui_Textpath_Data *pd,
         ey += diff.y;
 
         eina_bezier_values_set(&seg->bezier, sx, sy, csx, csy,
-                                             cex, cey, ex, ey);
+                               cex, cey, ex, ey);
      }
 
    _text_draw(pd);
 }
 
 EOLIAN static void
-_efl_ui_textpath_efl_gfx_entity_size_set(Eo *obj, Efl_Ui_Textpath_Data *pd 
EINA_UNUSED, Eina_Size2D sz)
+_efl_ui_textpath_efl_gfx_entity_size_set(Eo *obj, Efl_Ui_Textpath_Data *pd 
EINA_UNUSED, Eina_Size2D size)
 {
-   Eina_Size2D psize = efl_gfx_entity_size_get(obj);
-   efl_gfx_entity_size_set(efl_super(obj, MY_CLASS), sz);
-   if (psize.w != sz.w || psize.h != sz.h) _text_draw(pd);
+   Eina_Size2D psize, diff;
+   Efl_Ui_Textpath_Segment *seg;
+   double sx, sy, csx, csy, cex, cey, ex, ey;
+
+   psize = efl_gfx_entity_size_get(obj);
+   efl_gfx_entity_size_set(efl_super(obj, MY_CLASS), size);
+
+   if (psize.w == size.w && psize.h == size.h) return;
+
+   //TODO: Remove this condition if circle_set() is removed
+   if (pd->circle.radius > 0 && !pd->circular) return;
+
+   diff.w = (size.w - psize.w) * 0.5;
+   diff.h = (size.h - psize.h) * 0.5;
+
+   EINA_INLIST_FOREACH(pd->segments, seg)
+     {
+        eina_bezier_values_get(&seg->bezier, &sx, &sy, &csx, &csy,
+                               &cex, &cey, &ex, &ey);
+        sx += diff.w;
+        sy += diff.h;
+        csx += diff.w;
+        csy += diff.h;
+        cex += diff.w;
+        cey += diff.h;
+        ex += diff.w;
+        ey += diff.h;
+
+        eina_bezier_values_set(&seg->bezier, sx, sy, csx, csy,
+                               cex, cey, ex, ey);
+     }
+
+   _text_draw(pd);
 }
 
 EOLIAN static void
-_efl_ui_textpath_circle_set(Eo *obj, Efl_Ui_Textpath_Data *pd, double x, 
double y, double radius, double start_angle, Efl_Ui_Textpath_Direction 
direction)
+_efl_ui_textpath_circular_set(Eo *obj, Efl_Ui_Textpath_Data *pd, double 
radius, double start_angle, Efl_Ui_Textpath_Direction direction)
 {
-   double sweep_length;
+   Eina_Size2D text_size;
+   double sweep_length, x, y;
 
-   if (pd->circle.x == x && pd->circle.y == y &&
-       pd->circle.radius == radius &&
+   if (pd->circle.radius == radius &&
        pd->circle.start_angle == start_angle &&
        pd->direction == direction &&
        _map_point_calc(pd) > 0)
         return;
-   pd->circle.x = x;
-   pd->circle.y = y;
+
+   Eina_Size2D obj_size = efl_gfx_entity_size_get(obj);
+
+   //textpath min size is same to circle bounadary */
+   text_size = efl_gfx_entity_size_get(pd->text_obj);
+
+   x = (obj_size.w - text_size.h - (2 * radius)) * 0.5;
+   y = (obj_size.h - text_size.h - (2 * radius)) * 0.5;
+
+   /* User leaves center position to textpath itself.
+      Now textpath automatically updates circle text according to
+      object position. */
+   pd->circle.x = radius + x;
+   pd->circle.y = radius + y;
    pd->circle.radius = radius;
    pd->circle.start_angle = start_angle;
    pd->direction = direction;
+   pd->circular = EINA_TRUE;
 
    efl_gfx_path_reset(obj);
 
    if (direction == EFL_UI_TEXTPATH_DIRECTION_CW ||
        direction == EFL_UI_TEXTPATH_DIRECTION_CW_CENTER)
-     sweep_length = -360;
-   else
      sweep_length = 360;
+   else
+     sweep_length = -360;
 
-   efl_gfx_path_append_arc(obj, x - radius, y - radius, radius * 2,
+   efl_gfx_path_append_arc(obj,
+                           pd->circle.x - pd->circle.radius,
+                           pd->circle.y - pd->circle.radius,
+                           radius * 2,
                            radius * 2,  start_angle, sweep_length);
 
    _path_data_get(obj, pd);
    _path_start_angle_adjust(obj, pd);
    _sizing_eval(pd);
 
-   efl_gfx_hint_size_min_set(obj, EINA_SIZE2D(x * 2, y * 2));
+   efl_gfx_hint_size_min_set(obj, EINA_SIZE2D((radius * 2) + text_size.h, 
(radius * 2) + text_size.h));
 }
 
 EOLIAN static int
@@ -907,5 +965,44 @@ elm_textpath_add(Evas_Object *parent)
    return elm_legacy_add(EFL_UI_TEXTPATH_LEGACY_CLASS, parent);
 }
 
+EAPI void
+elm_textpath_circle_set(Eo *obj, double x, double y, double radius, double 
start_angle, Efl_Ui_Textpath_Direction direction)
+{
+   double sweep_length;
+
+   EFL_UI_TEXTPATH_DATA_GET(obj, pd);
+
+   if (pd->circle.x == x && pd->circle.y == y &&
+       pd->circle.radius == radius &&
+       pd->circle.start_angle == start_angle &&
+       pd->direction == direction &&
+       _map_point_calc(pd) > 0)
+        return;
+
+   pd->circle.x = x;
+   pd->circle.y = y;
+   pd->circle.radius = radius;
+   pd->circle.start_angle = start_angle;
+   pd->direction = direction;
+   pd->circular = EINA_FALSE;
+
+   efl_gfx_path_reset(obj);
+
+   if (direction == EFL_UI_TEXTPATH_DIRECTION_CW ||
+       direction == EFL_UI_TEXTPATH_DIRECTION_CW_CENTER)
+     sweep_length = - 360;
+   else
+     sweep_length = 360;
+
+   efl_gfx_path_append_arc(obj, x - radius, y - radius, radius * 2,
+                           radius * 2,  start_angle, sweep_length);
+
+   _path_data_get(obj, pd);
+   _path_start_angle_adjust(obj, pd);
+   _sizing_eval(pd);
+
+   efl_gfx_hint_size_min_set(obj, EINA_SIZE2D(x * 2, y * 2));
+}
+
 #include "efl_ui_textpath_legacy_eo.c"
 
diff --git a/src/lib/elementary/efl_ui_textpath.eo 
b/src/lib/elementary/efl_ui_textpath.eo
index 4a56b490a3..7d834a8d0a 100644
--- a/src/lib/elementary/efl_ui_textpath.eo
+++ b/src/lib/elementary/efl_ui_textpath.eo
@@ -10,11 +10,10 @@ class @beta Efl.Ui.Textpath extends Efl.Ui.Layout_Base 
implements Efl.Text, Efl.
 {
    [[Efl Ui Textpath class]]
    methods {
-      circle_set {
-         [[Set a circle with given center, radius, and start angle.]]
+      circular_set {
+         [[Set a circle with given radius and start angle.
+           The center of the circle will be decided by the object center 
position.]]
          params {
-            @in x: double; [[X coordinate of center]]
-            @in y: double; [[Y coordinate of center]]
             @in radius: double; [[Radius of the circle]]
             @in start_angle: double; [[Start angle of the circle]]
             @in direction: Efl.Ui.Textpath_Direction; [[Textpath direction]]
diff --git a/src/lib/elementary/efl_ui_textpath_eo.legacy.c 
b/src/lib/elementary/efl_ui_textpath_eo.legacy.c
index e810a856dd..1af5fdb1f8 100644
--- a/src/lib/elementary/efl_ui_textpath_eo.legacy.c
+++ b/src/lib/elementary/efl_ui_textpath_eo.legacy.c
@@ -1,8 +1,8 @@
 
 EAPI void
-elm_textpath_circle_set(Efl_Ui_Textpath *obj, double x, double y, double 
radius, double start_angle, Efl_Ui_Textpath_Direction direction)
+elm_textpath_circular_set(Efl_Ui_Textpath *obj, double radius, double 
start_angle, Efl_Ui_Textpath_Direction direction)
 {
-   efl_ui_textpath_circle_set(obj, x, y, radius, start_angle, direction);
+   efl_ui_textpath_circular_set(obj, radius, start_angle, direction);
 }
 
 EAPI void
@@ -23,6 +23,7 @@ elm_textpath_ellipsis_set(Efl_Ui_Textpath *obj, Eina_Bool 
ellipsis)
    efl_ui_textpath_ellipsis_set(obj, ellipsis);
 }
 
+
 EAPI Eina_Bool
 elm_textpath_ellipsis_get(const Efl_Ui_Textpath *obj)
 {
diff --git a/src/lib/elementary/efl_ui_textpath_eo.legacy.h 
b/src/lib/elementary/efl_ui_textpath_eo.legacy.h
index 5fe981a2d8..65e8768c12 100644
--- a/src/lib/elementary/efl_ui_textpath_eo.legacy.h
+++ b/src/lib/elementary/efl_ui_textpath_eo.legacy.h
@@ -36,10 +36,26 @@ typedef enum
  * @param[in] start_angle Start angle of the circle
  * @param[in] direction Textpath direction
  *
+ * @see elm_textpath_circluar_set()
+ *
  * @ingroup Elm_Textpath_Group
  */
 EAPI void elm_textpath_circle_set(Efl_Ui_Textpath *obj, double x, double y, 
double radius, double start_angle, Efl_Ui_Textpath_Direction direction);
 
+/**
+ * @brief Set a circle with given radius, and start angle.
+ *        The circle center will be decided by the object center position.
+ *
+ * @param[in] obj The object.
+ * @param[in] radius Radius of the circle
+ * @param[in] start_angle Start angle of the circle
+ * @param[in] direction Textpath direction
+ *
+ * @since 1.23
+ * @ingroup Elm_Textpath_Group
+ */
+EAPI void elm_textpath_circular_set(Efl_Ui_Textpath *obj, double radius, 
double start_angle, Efl_Ui_Textpath_Direction direction);
+
 /**
  * @brief The number of slices. The larger the number of slice_num is, The
  * better the text follows the path.

-- 


Reply via email to