textpath: update map when object's position is updated
[platform/upstream/elementary.git] / src / lib / efl_ui_textpath.c
1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4
5 #define ELM_LAYOUT_PROTECTED
6
7 #include <Elementary.h>
8 #include "elm_priv.h"
9
10 #include "elm_widget_layout.h"
11 //#include "efl_ui_textpath_internal_part.eo.h"
12 //#include "elm_part_helper.h"
13
14
15 #define MY_CLASS EFL_UI_TEXTPATH_CLASS
16
17 #define MY_CLASS_NAME "Efl.Ui.Textpath"
18 #define MY_CLASS_NAME_LEGACY "elm_textpath"
19
20 #define SLICE_DEFAULT_NO 99
21
22 typedef struct _Efl_Ui_Textpath_Point Efl_Ui_Textpath_Point;
23 typedef struct _Efl_Ui_Textpath_Line Efl_Ui_Textpath_Line;
24 typedef struct _Efl_Ui_Textpath_Segment Efl_Ui_Textpath_Segment;
25 typedef struct _Efl_Ui_Textpath_Data Efl_Ui_Textpath_Data;
26
27 struct _Efl_Ui_Textpath_Point
28 {
29    double x;
30    double y;
31 };
32
33 struct _Efl_Ui_Textpath_Line
34 {
35    Efl_Ui_Textpath_Point start;
36    Efl_Ui_Textpath_Point end;
37 };
38
39 struct _Efl_Ui_Textpath_Segment
40 {
41    EINA_INLIST;
42    int length;
43    Efl_Gfx_Path_Command type;
44    union
45      {
46         Eina_Bezier bezier;
47         Efl_Ui_Textpath_Line line;
48      };
49 };
50
51 struct _Efl_Ui_Textpath_Data
52 {
53    Evas_Object *text_obj;
54    char *text;
55    Efl_Gfx_Shape *path;
56    struct {
57         double x, y;
58         double radius;
59         double start_angle;
60    } circle;
61    Efl_Ui_Textpath_Direction direction;
62    int slice_no;
63    Eina_Bool autofit;
64    Eina_Bool ellipsis;
65
66    Eina_Inlist *segments;
67    int total_length;
68 };
69
70 #define EFL_UI_TEXTPATH_DATA_GET(o, sd) \
71    Efl_Ui_Textpath_Data *sd = eo_data_scope_get(o, EFL_UI_TEXTPATH_CLASS)
72
73 static inline double
74 _deg_to_rad(double angle)
75 {
76    return angle / 180 * M_PI;
77 }
78
79 static void
80 _segment_draw(Efl_Ui_Textpath_Data *pd, int slice_no, int w1, int w2, int cmp, Evas_Map *map, Eina_Bezier bezier)
81 {
82    int x = 0, y = 0, w = 0, h = 0;
83    int i, len, seg_len;
84    double u0, u1, v0, v1;
85    double dist, t, dt;
86    double px, py, px2, py2;
87    double rad;
88    Eina_Vector2 vec, nvec, vec0, vec1, vec2, vec3;
89    Eina_Matrix2 mat;
90
91    len = w2 - w1;
92    evas_object_geometry_get(pd->text_obj, NULL, NULL, &w, &h);
93    seg_len = eina_bezier_length_get(&bezier);
94    if (pd->autofit)
95      dt = len / (seg_len * (double) slice_no);
96    else
97      dt = 1.0 / (double) slice_no;
98    dist = len / (double)slice_no;
99    rad = _deg_to_rad(90);
100    eina_matrix2_values_set(&mat, cos(rad), -sin(rad), sin(rad), cos(rad));
101
102    eina_bezier_values_get(&bezier, NULL, NULL, NULL, NULL, NULL, NULL, &px2, &py2);
103    t = 0;
104    eina_bezier_point_at(&bezier, t, &px, &py);
105    eina_bezier_point_at(&bezier, t + dt, &px2, &py2);
106
107    vec.x = (px2 - px);
108    vec.y = (py2 - py);
109    eina_vector2_normalize(&nvec, &vec);
110
111    eina_vector2_transform(&vec, &mat, &nvec);
112    eina_vector2_normalize(&nvec, &vec);
113    eina_vector2_scale(&vec, &nvec, ((double) h) * 0.5);
114
115    vec1.x = (vec.x + px);
116    vec1.y = (vec.y + py);
117    vec2.x = (-vec.x + px);
118    vec2.y = (-vec.y + py);
119
120    //add points to map
121    for (i = 0; i < slice_no; i++)
122      {
123         //v0, v3
124         vec0.x = vec1.x;
125         vec0.y = vec1.y;
126         vec3.x = vec2.x;
127         vec3.y = vec2.y;
128
129         //v1, v2
130         t = ((double) (i + 1) * dt);
131         eina_bezier_point_at(&bezier, t, &px, &py);
132         eina_bezier_point_at(&bezier, t + dt, &px2, &py2);
133
134         vec.x = (px2 - px);
135         vec.y = (py2 - py);
136         eina_vector2_normalize(&nvec, &vec);
137         eina_vector2_transform(&vec, &mat, &nvec);
138         eina_vector2_normalize(&nvec, &vec);
139         eina_vector2_scale(&vec, &nvec, ((double) h) * 0.5);
140
141         vec1.x = (vec.x + px);
142         vec1.y = (vec.y + py);
143         vec2.x = (-vec.x + px);
144         vec2.y = (-vec.y + py);
145
146         evas_map_point_coord_set(map, cmp + i * 4, (int) vec0.x + x, (int) vec0.y + y, 0);
147         evas_map_point_coord_set(map, cmp + i * 4 + 1, (int) vec1.x + x, (int) vec1.y + y, 0);
148         evas_map_point_coord_set(map, cmp + i * 4 + 2, (int) vec2.x + x, (int) vec2.y + y, 0);
149         evas_map_point_coord_set(map, cmp + i * 4 + 3, (int) vec3.x + x, (int) vec3.y + y, 0);
150
151         //UV
152         u0 = w1 + i * dist;
153         u1 = u0 + dist;
154         v0 = (double) 0;
155         v1 = (double) h;
156
157         evas_map_point_image_uv_set(map, cmp + i * 4, u0, v0);
158         evas_map_point_image_uv_set(map, cmp + i * 4 + 1, u1, v0);
159         evas_map_point_image_uv_set(map, cmp + i * 4 + 2, u1, v1);
160         evas_map_point_image_uv_set(map, cmp + i * 4 + 3, u0, v1);
161      }
162 }
163
164 static void
165 _text_on_line_draw(Efl_Ui_Textpath_Data *pd, int w1, int w2, int cmp, Evas_Map *map, Efl_Ui_Textpath_Line line)
166 {
167    double x1, x2, y1, y2;
168    Evas_Coord x, y, w, h;
169    double line_len, len, sina, cosa;
170
171    x1 = line.start.x;
172    y1 = line.start.y;
173    x2 = line.end.x;
174    y2 = line.end.y;
175
176    line_len = sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
177    len = w2 - w1;
178    if (line_len > len)
179      {
180         x2 = x1 + len * (x2 - x1) / line_len;
181         y2 = y1 + len * (y2 - y1) / line_len;
182      }
183
184    evas_object_geometry_get(pd->text_obj, &x, &y, &w, &h);
185
186    len = sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
187    sina = (y2 - y1) / len;
188    cosa = (x2 - x1) / len;
189
190    h = h / 2;
191    evas_map_point_coord_set(map, cmp + 3, x1 - h * sina, y1 + h * cosa, 0);
192    evas_map_point_coord_set(map, cmp + 2, x2 - h * sina, y2 + h * cosa, 0);
193    evas_map_point_coord_set(map, cmp + 1, x2 + h * sina, y2 - h * cosa, 0);
194    evas_map_point_coord_set(map, cmp + 0, x1 + h * sina, y1 - h * cosa, 0);
195
196    h *= 2;
197    evas_map_point_image_uv_set(map, cmp + 0, w1, 0);
198    evas_map_point_image_uv_set(map, cmp + 1, w2, 0);
199    evas_map_point_image_uv_set(map, cmp + 2, w2, h);
200    evas_map_point_image_uv_set(map, cmp + 3, w1, h);
201 }
202
203 static int
204 _map_point_calc(Efl_Ui_Textpath_Data *pd)
205 {
206    int map_no = 0;
207    Efl_Ui_Textpath_Segment *seg;
208
209    EINA_INLIST_FOREACH(pd->segments, seg)
210      {
211         if (seg->type == EFL_GFX_PATH_COMMAND_TYPE_LINE_TO)
212           {
213              map_no++;
214           }
215         else if (seg->type == EFL_GFX_PATH_COMMAND_TYPE_CUBIC_TO)
216           {
217              int no = pd->slice_no * seg->length / (double)pd->total_length;
218              map_no += no;
219           }
220      }
221    map_no *= 4;
222
223    return map_no;
224 }
225
226 static void
227 _text_draw(Efl_Ui_Textpath_Data *pd)
228 {
229    Efl_Ui_Textpath_Segment *seg;
230    Evas_Map *map;
231    double slice_unit, slice_len;
232    int w, h, w1, w2;
233    int remained_w;
234    int total_slice, drawn_slice = 0;
235    int cur_map_point = 0, map_point_no;
236
237    evas_object_geometry_get(pd->text_obj, NULL, NULL, &w, &h);
238    if (pd->autofit)
239      remained_w = w;
240    else
241      remained_w = pd->total_length;
242    slice_unit = (double)pd->slice_no / pd->total_length;
243
244    slice_len = 1.0 / slice_unit;
245    total_slice = w / slice_len + 1;
246
247    map_point_no = _map_point_calc(pd);
248    if (map_point_no == 0)
249      {
250         ERR("no map point");
251         evas_object_map_enable_set(pd->text_obj, EINA_FALSE);
252         return;
253      }
254    map = evas_map_new(map_point_no);
255    /* TIZEN_ONLY(20180302): update map when object's position is updated */
256    evas_map_util_object_move_sync_set(map, EINA_TRUE);
257    /* END */
258
259    w1 = w2 = 0;
260    EINA_INLIST_FOREACH(pd->segments, seg)
261      {
262         int len = seg->length;
263         if (!pd->autofit)
264           len = (double)seg->length * w / (double)pd->total_length;
265         if (remained_w <= 0)
266           break;
267         w2 = w1 + len;
268         if (w2 > w)
269           w2 = w;
270         if (seg->type == EFL_GFX_PATH_COMMAND_TYPE_LINE_TO)
271           {
272              drawn_slice += 1;
273              _text_on_line_draw(pd, w1, w2, cur_map_point, map, seg->line);
274              cur_map_point += 4;
275           }
276         else
277           {
278              int slice_no;
279              slice_no = pd->slice_no * seg->length / (double)pd->total_length;
280              if (slice_no == 0)
281                slice_no = len * slice_unit + 1;
282              if (remained_w == 0)
283                slice_no = total_slice - drawn_slice;
284              drawn_slice += slice_no;
285              _segment_draw(pd, slice_no, w1, w2, cur_map_point, map, seg->bezier);
286              cur_map_point += slice_no * 4;
287           }
288         w1 = w2;
289         remained_w -= len;
290      }
291    evas_object_map_enable_set(pd->text_obj, EINA_TRUE);
292    evas_object_map_set(pd->text_obj, map);
293    evas_map_free(map);
294 }
295
296 static void
297 _path_data_get(Eo *obj, Efl_Ui_Textpath_Data *pd, Eina_Bool set_min)
298 {
299    const Efl_Gfx_Path_Command *cmd;
300    const double *points;
301    Efl_Ui_Textpath_Segment *seg;
302
303    EINA_INLIST_FREE(pd->segments, seg)
304      {
305         pd->segments = eina_inlist_remove(pd->segments, EINA_INLIST_GET(seg));
306         free(seg);
307      }
308
309    Evas_Coord x, y;
310    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
311
312    pd->total_length = 0;
313    eo_do(obj, efl_gfx_shape_path_get(&cmd, &points));
314    if (cmd)
315      {
316         int pos = -1;
317         Eina_Rectangle *rect = eina_rectangle_new(0, 0, 0, 0);
318         double px0 = 0.0, py0 = 0.0, ctrl_x0, ctrl_y0, ctrl_x1, ctrl_y1, px1, py1;
319
320         while (*cmd != EFL_GFX_PATH_COMMAND_TYPE_END)
321           {
322
323              if (*cmd == EFL_GFX_PATH_COMMAND_TYPE_MOVE_TO)
324                {
325                   pos++;
326                   px0 = points[pos] + x;
327                   pos++;
328                   py0 = points[pos] + y;
329                }
330              else if (*cmd == EFL_GFX_PATH_COMMAND_TYPE_CUBIC_TO)
331                {
332                   Eina_Bezier bz;
333                   double bx, by, bw, bh;
334                   Eina_Rectangle *brect;
335
336                   pos++;
337                   ctrl_x0 = points[pos] + x;
338                   pos++;
339                   ctrl_y0 = points[pos] + y;
340                   pos++;
341                   ctrl_x1 = points[pos] + x;
342                   pos++;
343                   ctrl_y1 = points[pos] + y;
344                   pos++;
345                   px1 = points[pos] + x;
346                   pos++;
347                   py1 = points[pos] + y;
348
349                   eina_bezier_values_set(&bz, px0, py0, ctrl_x0, ctrl_y0, ctrl_x1, ctrl_y1, px1, py1);
350                   seg = malloc(sizeof(Efl_Ui_Textpath_Segment));
351                   if (!seg)
352                     {
353                        ERR("Failed to allocate segment");
354                        px0 = px1;
355                        py0 = py1;
356                        continue;
357                     }
358                   seg->length = eina_bezier_length_get(&bz);
359                   seg->bezier = bz;
360                   seg->type = EFL_GFX_PATH_COMMAND_TYPE_CUBIC_TO;
361                   pd->segments = eina_inlist_append(pd->segments, EINA_INLIST_GET(seg));
362                   pd->total_length += seg->length;
363
364                   //move points
365                   px0 = px1;
366                   py0 = py1;
367
368                   eina_bezier_bounds_get(&bz, &bx, &by, &bw, &bh);
369                   brect = eina_rectangle_new(bx, by, bw, bh);
370                   eina_rectangle_union(rect, brect);
371                   eina_rectangle_free(brect);
372                }
373              else if (*cmd == EFL_GFX_PATH_COMMAND_TYPE_LINE_TO)
374                {
375                   Eina_Rectangle *lrect;
376
377                   pos++;
378                   px1 = points[pos] + x;
379                   pos++;
380                   py1 = points[pos] + y;
381
382                   seg = malloc(sizeof(Efl_Ui_Textpath_Segment));
383                   if (!seg)
384                     {
385                        ERR("Failed to allocate segment");
386                        px0 = px1;
387                        py0 = py1;
388                     }
389                   seg->type = EFL_GFX_PATH_COMMAND_TYPE_LINE_TO;
390                   seg->line.start.x = px0;
391                   seg->line.start.y = py0;
392                   seg->line.end.x = px1;
393                   seg->line.end.y = py1;
394                   seg->length = sqrt((px1 - px0)*(px1 - px0) + (py1 - py0)*(py1 - py0));
395                   pd->segments = eina_inlist_append(pd->segments, EINA_INLIST_GET(seg));
396                   pd->total_length += seg->length;
397
398                   lrect = eina_rectangle_new(px0, py0, px1 - px0, py1 - py0);
399                   eina_rectangle_union(rect, lrect);
400                   eina_rectangle_free(lrect);
401                }
402              cmd++;
403           }
404         if (set_min)
405           {
406              evas_object_size_hint_min_set(obj, rect->w, rect->h);
407           }
408         eina_rectangle_free(rect);
409      }
410 }
411
412 static void
413 _sizing_eval(Efl_Ui_Textpath_Data *pd)
414 {
415    _text_draw(pd);
416 }
417
418 static void
419 _textpath_ellipsis_set(Efl_Ui_Textpath_Data *pd, Eina_Bool enabled)
420 {
421    const char *format;
422
423    edje_object_part_text_style_user_pop(pd->text_obj, "elm.text");
424    if (enabled)
425      {
426         Eina_Strbuf *buf = eina_strbuf_new();
427
428         eina_strbuf_append_printf(buf, "DEFAULT='ellipsis=1.0'");
429         format = eina_stringshare_add(eina_strbuf_string_get(buf));
430         eina_strbuf_free(buf);
431         edje_object_part_text_style_user_push(pd->text_obj, "elm.text", format);
432      }
433 }
434
435 static void
436 _ellipsis_set(Efl_Ui_Textpath_Data *pd)
437 {
438    if (!pd->text_obj) return;
439
440    Evas_Coord w = 0, h = 0;
441    Eina_Bool is_ellipsis = EINA_FALSE;
442    const Evas_Object *tb;
443
444    tb = edje_object_part_object_get(pd->text_obj, "elm.text");
445    evas_object_textblock_size_native_get(tb, &w, &h);
446    evas_object_size_hint_min_set(pd->text_obj, w, h);
447    if (pd->ellipsis)
448      {
449         if (w > pd->total_length)
450           {
451              is_ellipsis = EINA_TRUE;
452              w = pd->total_length;
453           }
454      }
455    evas_object_resize(pd->text_obj, w, h);
456    _textpath_ellipsis_set(pd, is_ellipsis);
457 }
458
459 static Eina_Bool
460 //_path_changed_cb(void *data, const Efl_Event *event EINA_UNUSED)
461 _path_changed_cb(void *data,
462                     Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED,
463                     void *event_info EINA_UNUSED)
464 {
465    EFL_UI_TEXTPATH_DATA_GET(data, sd);
466
467    _path_data_get(data, sd, EINA_TRUE);
468    _sizing_eval(sd);
469
470    return EINA_TRUE;
471 }
472
473 static Eina_Bool
474 _textpath_text_set_internal(Eo *obj, Efl_Ui_Textpath_Data *pd, const char *part EINA_UNUSED, const char *text)
475 {
476    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
477    Eina_Bool ret = EINA_TRUE;
478
479    if (!text) text = "";
480    //ret = edje_object_part_text_set(pd->text_obj, part, text);
481    ret = edje_object_part_text_set(pd->text_obj, "elm.text", text);
482    _ellipsis_set(pd);
483
484    return ret;
485 }
486
487 /*EOLIAN static void
488 _efl_ui_textpath_efl_canvas_group_group_calculate(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd)
489 {
490    _sizing_eval(pd);
491 }*/
492
493
494 EOLIAN static void
495 _efl_ui_textpath_elm_layout_sizing_eval(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd)
496 {
497    _sizing_eval(pd);
498 }
499
500 EOLIAN static void
501 _efl_ui_textpath_evas_object_smart_calculate(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd)
502 {
503     _sizing_eval(pd);
504 }
505
506 EOLIAN static void
507 //_efl_ui_textpath_efl_canvas_group_group_add(Eo *obj, Efl_Ui_Textpath_Data *priv)
508 _efl_ui_textpath_evas_object_smart_add(Eo *obj, Efl_Ui_Textpath_Data *priv)
509 {
510    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
511
512    eo_do_super(obj, MY_CLASS, evas_obj_smart_add());
513    elm_widget_sub_object_parent_add(obj);
514
515    priv->text_obj = edje_object_add(evas_object_evas_get(obj));
516    elm_widget_theme_object_set(obj, priv->text_obj, "textpath", "base",
517                                elm_widget_style_get(obj));
518    evas_object_size_hint_weight_set(priv->text_obj, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
519    evas_object_size_hint_align_set(priv->text_obj, EVAS_HINT_FILL, EVAS_HINT_FILL);
520    evas_object_show(priv->text_obj);
521
522    evas_object_smart_member_add(priv->text_obj, obj);
523    elm_widget_sub_object_add(obj, priv->text_obj);
524
525    //efl_event_callback_add(obj, EFL_GFX_PATH_EVENT_CHANGED, _path_changed_cb, obj);
526    eo_do(obj, eo_event_callback_add
527          (EFL_GFX_PATH_CHANGED, _path_changed_cb, obj));
528 }
529
530 EOLIAN static void
531 _efl_ui_textpath_class_constructor(Eo_Class *klass)
532 {
533    evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
534 }
535
536 //EOLIAN static Efl_Object *
537 //_efl_ui_textpath_efl_object_constructor(Eo *obj, Efl_Ui_Textpath_Data *pd)
538 EOLIAN static Eo*
539 _efl_ui_textpath_eo_base_constructor(Eo *obj, Efl_Ui_Textpath_Data *pd)
540 {
541    //obj = efl_constructor(efl_super(obj, MY_CLASS));
542    obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
543    pd->autofit = EINA_TRUE;
544    pd->slice_no = SLICE_DEFAULT_NO;
545    pd->direction = EFL_UI_TEXTPATH_DIRECTION_CW;
546
547    return obj;
548 }
549
550 EOLIAN static void
551 //_efl_ui_textpath_efl_object_destructor(Eo *obj, Efl_Ui_Textpath_Data *pd)
552 _efl_ui_textpath_eo_base_destructor(Eo *obj, Efl_Ui_Textpath_Data *pd)
553 {
554    Efl_Ui_Textpath_Segment *seg;
555
556    if (pd->text) free(pd->text);
557    if (pd->text_obj) evas_object_del(pd->text_obj);
558    EINA_INLIST_FREE(pd->segments, seg)
559      {
560         pd->segments = eina_inlist_remove(pd->segments, EINA_INLIST_GET(seg));
561         free(seg);
562      }
563
564    //efl_destructor(efl_super(obj, MY_CLASS));
565    eo_do_super(obj, MY_CLASS, eo_destructor());
566 }
567
568 EOLIAN static Eina_Bool
569 _efl_ui_textpath_elm_layout_text_set(Eo *obj, Efl_Ui_Textpath_Data *pd, const char *part, const char *text)
570 {
571    return _textpath_text_set_internal(obj, pd, part, text);
572 }
573
574 EOLIAN static const char *
575 _efl_ui_textpath_elm_layout_text_get(const Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd, const char *part)
576 {
577    return edje_object_part_text_get(pd->text_obj, part);
578 }
579
580 /*
581 EOLIAN static Eina_Bool
582 _efl_ui_textpath_text_set(Eo *obj, Efl_Ui_Textpath_Data *pd, const char *part, const char *text)
583 {
584    return _textpath_text_set_internal(obj, pd, part, text);
585 }
586
587 EOLIAN static const char *
588 _efl_ui_textpath_text_get(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd, const char *part)
589 {
590    return edje_object_part_text_get(pd->text_obj, part);
591 }
592
593 EOLIAN static void
594 _efl_ui_textpath_efl_text_text_set(Eo *obj, Efl_Ui_Textpath_Data *pd, const char *text)
595 {
596    _textpath_text_set_internal(obj, pd, "elm.text", text);
597 }
598
599 EOLIAN static const char *
600 _efl_ui_textpath_efl_text_text_get(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd)
601 {
602    return edje_object_part_text_get(pd->text_obj, "elm.text");
603 }*/
604
605 //EOLIAN static Efl_Ui_Theme_Apply
606 EOLIAN static Elm_Theme_Apply
607 _efl_ui_textpath_elm_widget_theme_apply(Eo *obj, Efl_Ui_Textpath_Data *pd)
608 {
609    Elm_Theme_Apply ret = ELM_THEME_APPLY_FAILED;
610
611    eo_do_super(obj, MY_CLASS, ret = elm_obj_widget_theme_apply());
612    if (!ret) return ELM_THEME_APPLY_FAILED;
613
614    elm_widget_theme_object_set(obj, pd->text_obj, "textpath", "base",
615                                elm_widget_style_get(obj));
616    _ellipsis_set(pd);
617
618    return ret;
619 }
620
621
622 EOLIAN static void
623 //_efl_ui_textpath_evas_object_position_set(Eo *obj, Efl_Ui_Textpath_Data *pd, Evas_Coord x, Evas_Coord y)
624 _efl_ui_textpath_evas_object_smart_move(Eo *obj, Efl_Ui_Textpath_Data *pd, Evas_Coord x, Evas_Coord y)
625 {
626    eo_do_super(obj, MY_CLASS, evas_obj_smart_move(x, y));
627
628    /* TIZEN_ONLY(20180302): update map when object's position is updated
629     * Do Nothing. The position is not updated to the object in this function.
630     * Test with evas_object_geometry_get().
631    _path_data_get(obj, pd, EINA_FALSE);
632    _text_draw(pd);
633     */
634    /* END */
635 }
636
637 /*
638 EOLIAN static void
639 _efl_ui_textpath_evas_object_resize(Eo *obj, Efl_Ui_Textpath_Data *pd EINA_UNUSED, Evas_Coord w, Evas_Coord h)
640 {
641    eo_do_super(obj, MY_CLASS, evas_object_resize(w, h));
642 }*/
643
644 EOLIAN static void
645 _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)
646 {
647    if (pd->circle.x == x && pd->circle.y == y &&
648        pd->circle.radius == radius &&
649        pd->circle.start_angle == start_angle &&
650        pd->direction == direction &&
651        _map_point_calc(pd) > 0)
652      {
653         ERR("Same circle");
654         return;
655      }
656    pd->circle.x = x;
657    pd->circle.y = y;
658    pd->circle.radius = radius;
659    pd->circle.start_angle = start_angle;
660    pd->direction = direction;
661
662    eo_do(obj, efl_gfx_shape_reset());
663    if (direction == EFL_UI_TEXTPATH_DIRECTION_CW)
664      {
665         eo_do(obj, efl_gfx_shape_append_arc(x - radius, y - radius, radius * 2,
666                                 radius * 2,  start_angle, -360));
667      }
668    else
669      {
670         eo_do(obj, efl_gfx_shape_append_arc(x - radius, y - radius, radius * 2,
671                                 radius * 2,  start_angle, 360));
672      }
673
674    _sizing_eval(pd);
675 }
676
677 EOLIAN static Eina_Bool
678 _efl_ui_textpath_autofit_get(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd)
679 {
680    return pd->autofit;
681 }
682
683 EOLIAN static void
684 _efl_ui_textpath_autofit_set(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd, Eina_Bool autofit)
685 {
686    if (pd->autofit == autofit) return;
687    pd->autofit = autofit;
688    _sizing_eval(pd);
689 }
690
691 EOLIAN static int
692 _efl_ui_textpath_slice_number_get(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd)
693 {
694    return pd->slice_no;
695 }
696
697 EOLIAN static void
698 _efl_ui_textpath_slice_number_set(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd, int slice_no)
699 {
700    if (pd->slice_no == slice_no) return;
701    pd->slice_no = slice_no;
702    _sizing_eval(pd);
703 }
704
705 EOLIAN static void
706 _efl_ui_textpath_ellipsis_set(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd, Eina_Bool ellipsis)
707 {
708    if (pd->ellipsis == ellipsis) return;
709    pd->ellipsis = ellipsis;
710
711    _ellipsis_set(pd);
712    _sizing_eval(pd);
713 }
714
715 EOLIAN static Eina_Bool
716 _efl_ui_textpath_ellipsis_get(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd)
717 {
718    return pd->ellipsis;
719 }
720
721 /* Efl.Part begin */
722 //ELM_PART_OVERRIDE(efl_ui_textpath, EFL_UI_TEXTPATH, EFL_UI_LAYOUT, Efl_Ui_Textpath_Data, Elm_Part_Data)
723 //ELM_PART_OVERRIDE_TEXT_SET(efl_ui_textpath, EFL_UI_TEXTPATH, EFL_UI_LAYOUT, Efl_Ui_Textpath_Data, Elm_Part_Data)
724 //ELM_PART_OVERRIDE_TEXT_GET(efl_ui_textpath, EFL_UI_TEXTPATH, EFL_UI_LAYOUT, Efl_Ui_Textpath_Data, Elm_Part_Data)
725 //#include "efl_ui_textpath_internal_part.eo.c"
726 /* Efl.Part end */
727
728 EAPI Evas_Object *
729 elm_textpath_add(Evas_Object *parent)
730 {
731    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
732    Evas_Object *obj = eo_add(MY_CLASS, parent);
733
734    return obj;
735 }
736
737 #define EFL_UI_TEXTPATH_EXTRA_OPS \
738       EFL_CANVAS_GROUP_ADD_OPS(efl_ui_textpath)
739
740 #include "efl_ui_textpath.eo.c"