diff options
Diffstat (limited to 'src/lib/elementary/efl_ui_textpath.c')
-rw-r--r-- | src/lib/elementary/efl_ui_textpath.c | 253 |
1 files changed, 176 insertions, 77 deletions
diff --git a/src/lib/elementary/efl_ui_textpath.c b/src/lib/elementary/efl_ui_textpath.c index 9a64896521..20b04092b0 100644 --- a/src/lib/elementary/efl_ui_textpath.c +++ b/src/lib/elementary/efl_ui_textpath.c @@ -3,6 +3,7 @@ #endif #define ELM_LAYOUT_PROTECTED +#define EFL_PART_PROTECTED #include <Elementary.h> #include "elm_priv.h" @@ -46,6 +47,10 @@ struct _Efl_Ui_Textpath_Segment }; }; +/* If you need to draw slices using Evas Line, + * define the following debug flag manually. */ +//#define EFL_UI_TEXTPATH_LINE_DEBUG + struct _Efl_Ui_Textpath_Data { Evas_Object *text_obj; @@ -58,11 +63,14 @@ struct _Efl_Ui_Textpath_Data } circle; Efl_Ui_Textpath_Direction direction; int slice_no; - Eina_Bool autofit; Eina_Bool ellipsis; Eina_Inlist *segments; int total_length; + Ecore_Job *draw_text_job; +#ifdef EFL_UI_TEXTPATH_LINE_DEBUG + Eina_List *lines; +#endif }; #define EFL_UI_TEXTPATH_DATA_GET(o, sd) \ @@ -75,26 +83,25 @@ _deg_to_rad(double angle) } static void -_segment_draw(Efl_Ui_Textpath_Data *pd, int slice_no, int w1, int w2, int cmp, Evas_Map *map, Eina_Bezier bezier) +_segment_draw(Efl_Ui_Textpath_Data *pd, int slice_no, double dt, double dist, + int w1, int cmp, Evas_Map *map, Eina_Bezier bezier, + int *last_x1, int *last_y1, int *last_x2, int *last_y2) { - int i, len, seg_len; + int i; double u0, u1, v0, v1; - double dist, t, dt; + double t; double px, py, px2, py2; double rad; Eina_Rect r; Eina_Vector2 vec, nvec, vec0, vec1, vec2, vec3; Eina_Matrix2 mat; +#ifdef EFL_UI_TEXTPATH_LINE_DEBUG + static Eina_Bool yello_color_flag = EINA_FALSE; + yello_color_flag = !yello_color_flag; +#endif - len = w2 - w1; - r = efl_gfx_geometry_get(pd->text_obj); + r = efl_gfx_entity_geometry_get(pd->text_obj); - seg_len = eina_bezier_length_get(&bezier); - if (pd->autofit) - dt = len / (seg_len * (double) slice_no); - else - dt = 1.0 / (double) slice_no; - dist = len / (double)slice_no; rad = _deg_to_rad(90); eina_matrix2_values_set(&mat, cos(rad), -sin(rad), sin(rad), cos(rad)); @@ -116,19 +123,46 @@ _segment_draw(Efl_Ui_Textpath_Data *pd, int slice_no, int w1, int w2, int cmp, E vec2.x = (-vec.x + px); vec2.y = (-vec.y + py); + if (cmp == 0) + { + *last_x1 = (int) round(vec1.x + r.x); + *last_y1 = (int) round(vec1.y + r.y); + *last_x2 = (int) round(vec2.x + r.x); + *last_y2 = (int) round(vec2.y + r.y); + } + //add points to map for (i = 0; i < slice_no; i++) { + int mp0_x, mp0_y; + int mp1_x, mp1_y; + int mp2_x, mp2_y; + int mp3_x, mp3_y; + double next_dt = dt; + //v0, v3 vec0.x = vec1.x; vec0.y = vec1.y; vec3.x = vec2.x; vec3.y = vec2.y; + //UV + u0 = w1 + i * dist; + u1 = u0 + dist; + if (u1 > r.w) + u1 = r.w; + v0 = (double) 0; + v1 = (double) r.h; + + /* If u1 is modified not to exceed its end, + * modify next_dt according to changes of dist. */ + if (u1 < u0 + dist) + next_dt = dt * (u1 - u0) / dist; + //v1, v2 - t = ((double) (i + 1) * dt); + t = (double) (i * dt) + next_dt; eina_bezier_point_at(&bezier, t, &px, &py); - eina_bezier_point_at(&bezier, t + dt, &px2, &py2); + eina_bezier_point_at(&bezier, t + next_dt, &px2, &py2); vec.x = (px2 - px); vec.y = (py2 - py); @@ -142,21 +176,80 @@ _segment_draw(Efl_Ui_Textpath_Data *pd, int slice_no, int w1, int w2, int cmp, E vec2.x = (-vec.x + px); vec2.y = (-vec.y + py); - evas_map_point_coord_set(map, cmp + i * 4, (int) vec0.x + r.x, (int) vec0.y + r.y, 0); - evas_map_point_coord_set(map, cmp + i * 4 + 1, (int) vec1.x + r.x, (int) vec1.y + r.y, 0); - evas_map_point_coord_set(map, cmp + i * 4 + 2, (int) vec2.x + r.x, (int) vec2.y + r.y, 0); - evas_map_point_coord_set(map, cmp + i * 4 + 3, (int) vec3.x + r.x, (int) vec3.y + r.y, 0); - - //UV - u0 = w1 + i * dist; - u1 = u0 + dist; - v0 = (double) 0; - v1 = (double) r.h; + /* Set mp1, mp2 position according to difference between + * previous points and next points. + * It improves smoothness of curve's slope changing. */ + mp0_x = *last_x1; + mp0_y = *last_y1; + mp1_x = *last_x1 + (int) round(vec1.x - vec0.x); + mp1_y = *last_y1 + (int) round(vec1.y - vec0.y); + mp2_x = *last_x2 + (int) round(vec2.x - vec3.x); + mp2_y = *last_y2 + (int) round(vec2.y - vec3.y); + mp3_x = *last_x2; + mp3_y = *last_y2; + + evas_map_point_coord_set(map, cmp + i * 4, mp0_x, mp0_y, 0); + evas_map_point_coord_set(map, cmp + i * 4 + 1, mp1_x, mp1_y, 0); + evas_map_point_coord_set(map, cmp + i * 4 + 2, mp2_x, mp2_y, 0); + evas_map_point_coord_set(map, cmp + i * 4 + 3, mp3_x, mp3_y, 0); evas_map_point_image_uv_set(map, cmp + i * 4, u0, v0); evas_map_point_image_uv_set(map, cmp + i * 4 + 1, u1, v0); evas_map_point_image_uv_set(map, cmp + i * 4 + 2, u1, v1); evas_map_point_image_uv_set(map, cmp + i * 4 + 3, u0, v1); + + *last_x1 = mp1_x; + *last_y1 = mp1_y; + *last_x2 = mp2_x; + *last_y2 = mp2_y; + +#ifdef EFL_UI_TEXTPATH_LINE_DEBUG + Evas_Object *line = evas_object_line_add(evas_object_evas_get(pd->text_obj)); + pd->lines = eina_list_append(pd->lines, line); + if (yello_color_flag) + evas_object_color_set(line, 255, 255, 0, 255); + else + evas_object_color_set(line, 255, 0, 0, 255); + evas_object_line_xy_set(line, + mp0_x, mp0_y, + mp1_x, mp1_y); + evas_object_show(line); + + line = evas_object_line_add(evas_object_evas_get(pd->text_obj)); + pd->lines = eina_list_append(pd->lines, line); + if (yello_color_flag) + evas_object_color_set(line, 255, 255, 0, 255); + else + evas_object_color_set(line, 255, 0, 0, 255); + evas_object_line_xy_set(line, + mp1_x, mp1_y, + mp2_x, mp2_y); + evas_object_show(line); + + line = evas_object_line_add(evas_object_evas_get(pd->text_obj)); + pd->lines = eina_list_append(pd->lines, line); + if (yello_color_flag) + evas_object_color_set(line, 255, 255, 0, 255); + else + evas_object_color_set(line, 255, 0, 0, 255); + evas_object_line_xy_set(line, + mp2_x, mp2_y, + mp3_x, mp3_y); + evas_object_show(line); + + line = evas_object_line_add(evas_object_evas_get(pd->text_obj)); + pd->lines = eina_list_append(pd->lines, line); + if (yello_color_flag) + evas_object_color_set(line, 255, 255, 0, 255); + else + evas_object_color_set(line, 255, 0, 0, 255); + evas_object_line_xy_set(line, + mp3_x, mp3_y, + mp0_x, mp0_y); + evas_object_show(line); +#endif + + if (u1 >= r.w) break; } } @@ -184,7 +277,7 @@ _text_on_line_draw(Efl_Ui_Textpath_Data *pd, int w1, int w2, int cmp, Evas_Map * sina = (y2 - y1) / len; cosa = (x2 - x1) / len; - r = efl_gfx_geometry_get(pd->text_obj); + r = efl_gfx_entity_geometry_get(pd->text_obj); r.h /= 2; evas_map_point_coord_set(map, cmp + 3, x1 - r.h * sina, y1 + r.h * cosa, 0); evas_map_point_coord_set(map, cmp + 2, x2 - r.h * sina, y2 + r.h * cosa, 0); @@ -212,7 +305,7 @@ _map_point_calc(Efl_Ui_Textpath_Data *pd) } else if (seg->type == EFL_GFX_PATH_COMMAND_TYPE_CUBIC_TO) { - int no = pd->slice_no * seg->length / (double)pd->total_length; + int no = (int)ceil(pd->slice_no * seg->length / (double)pd->total_length); if (no == 0) no = 1; map_no += no; } @@ -223,23 +316,21 @@ _map_point_calc(Efl_Ui_Textpath_Data *pd) } static void -_text_draw(Efl_Ui_Textpath_Data *pd) +_text_draw(void *data) { + Efl_Ui_Textpath_Data *pd = data; Efl_Ui_Textpath_Segment *seg; Evas_Map *map; - double slice_unit; int w1, w2; int remained_w; - int drawn_slice = 0; int cur_map_point = 0, map_point_no; Eina_Size2D sz; + int last_x1, last_y1, last_x2, last_y2; - sz = efl_gfx_size_get(pd->text_obj); - if (pd->autofit) - remained_w = sz.w; - else - remained_w = pd->total_length; - slice_unit = (double)pd->slice_no / pd->total_length; + last_x1 = last_y1 = last_x2 = last_y2 = 0; + + sz = efl_gfx_entity_size_get(pd->text_obj); + remained_w = sz.w; map_point_no = _map_point_calc(pd); if (map_point_no == 0) @@ -248,13 +339,18 @@ _text_draw(Efl_Ui_Textpath_Data *pd) return; } map = evas_map_new(map_point_no); + evas_map_util_object_move_sync_set(map, EINA_TRUE); + +#ifdef EFL_UI_TEXTPATH_LINE_DEBUG + Evas_Object *line; + EINA_LIST_FREE(pd->lines, line) + evas_object_del(line); +#endif w1 = w2 = 0; EINA_INLIST_FOREACH(pd->segments, seg) { int len = seg->length; - if (!pd->autofit) - len = (double)seg->length * sz.w / (double)pd->total_length; if (remained_w <= 0) break; w2 = w1 + len; @@ -262,26 +358,35 @@ _text_draw(Efl_Ui_Textpath_Data *pd) w2 = sz.w; if (seg->type == EFL_GFX_PATH_COMMAND_TYPE_LINE_TO) { - drawn_slice += 1; _text_on_line_draw(pd, w1, w2, cur_map_point, map, seg->line); cur_map_point += 4; } else { + double slice_value, dt, dist; int slice_no; - slice_no = pd->slice_no * seg->length / (double)pd->total_length; - if (slice_no == 0) - slice_no = len * slice_unit + 1; - drawn_slice += slice_no; - _segment_draw(pd, slice_no, w1, w2, cur_map_point, map, seg->bezier); + + slice_value = pd->slice_no * seg->length / (double)pd->total_length; + dt = (double)pd->total_length / (pd->slice_no * seg->length); + dist = (double)pd->total_length / (double)pd->slice_no; + + slice_no = (int)ceil(slice_value); + dt = (double)slice_value * dt / (double)slice_no; + dist = (double)slice_value * dist / (double)slice_no; + + _segment_draw(pd, slice_no, dt, dist, + w1, cur_map_point, map, seg->bezier, + &last_x1, &last_y1, &last_x2, &last_y2); cur_map_point += slice_no * 4; } w1 = w2; - remained_w -= len; + remained_w -= seg->length; } evas_object_map_enable_set(pd->text_obj, EINA_TRUE); evas_object_map_set(pd->text_obj, map); evas_map_free(map); + + pd->draw_text_job = NULL; } static void @@ -298,7 +403,7 @@ _path_data_get(Eo *obj, Efl_Ui_Textpath_Data *pd, Eina_Bool set_min) free(seg); } - opos = efl_gfx_position_get(obj); + opos = efl_gfx_entity_position_get(obj); pd->total_length = 0; efl_gfx_path_get(obj, &cmd, &points); @@ -400,16 +505,17 @@ _path_data_get(Eo *obj, Efl_Ui_Textpath_Data *pd, Eina_Bool set_min) static void _sizing_eval(Efl_Ui_Textpath_Data *pd) { - _text_draw(pd); + ecore_job_del(pd->draw_text_job); + pd->draw_text_job = ecore_job_add(_text_draw, pd); } static void _textpath_ellipsis_set(Efl_Ui_Textpath_Data *pd, Eina_Bool enabled) { - edje_object_part_text_style_user_pop(pd->text_obj, "elm.text"); + edje_object_part_text_style_user_pop(pd->text_obj, "efl.text"); if (enabled) - edje_object_part_text_style_user_push(pd->text_obj, "elm.text", + edje_object_part_text_style_user_push(pd->text_obj, "efl.text", "DEFAULT='ellipsis=1.0'"); } @@ -422,7 +528,7 @@ _ellipsis_set(Efl_Ui_Textpath_Data *pd) Eina_Bool is_ellipsis = EINA_FALSE; const Evas_Object *tb; - tb = edje_object_part_object_get(pd->text_obj, "elm.text"); + tb = edje_object_part_object_get(pd->text_obj, "efl.text"); evas_object_textblock_size_native_get(tb, &w, &h); evas_object_size_hint_min_set(pd->text_obj, w, h); if (pd->ellipsis) @@ -433,7 +539,7 @@ _ellipsis_set(Efl_Ui_Textpath_Data *pd) w = pd->total_length; } } - efl_gfx_size_set(pd->text_obj, EINA_SIZE2D(w, h)); + efl_gfx_entity_size_set(pd->text_obj, EINA_SIZE2D(w, h)); _textpath_ellipsis_set(pd, is_ellipsis); } @@ -460,6 +566,7 @@ _textpath_text_set_internal(Eo *obj, Efl_Ui_Textpath_Data *pd, const char *part, if (!text) text = ""; ret = edje_object_part_text_set(pd->text_obj, part, text); _ellipsis_set(pd); + _sizing_eval(pd); return ret; } @@ -483,7 +590,7 @@ _efl_ui_textpath_efl_canvas_group_group_add(Eo *obj, Efl_Ui_Textpath_Data *priv) elm_widget_style_get(obj)); efl_gfx_size_hint_weight_set(priv->text_obj, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); efl_gfx_size_hint_align_set(priv->text_obj, EVAS_HINT_FILL, EVAS_HINT_FILL); - efl_gfx_visible_set(priv->text_obj, EINA_TRUE); + efl_gfx_entity_visible_set(priv->text_obj, EINA_TRUE); evas_object_smart_member_add(priv->text_obj, obj); elm_widget_sub_object_add(obj, priv->text_obj); @@ -495,7 +602,6 @@ EOLIAN static Efl_Object * _efl_ui_textpath_efl_object_constructor(Eo *obj, Efl_Ui_Textpath_Data *pd) { obj = efl_constructor(efl_super(obj, MY_CLASS)); - pd->autofit = EINA_TRUE; pd->slice_no = SLICE_DEFAULT_NO; pd->direction = EFL_UI_TEXTPATH_DIRECTION_CW; @@ -514,6 +620,13 @@ _efl_ui_textpath_efl_object_destructor(Eo *obj, Efl_Ui_Textpath_Data *pd) pd->segments = eina_inlist_remove(pd->segments, EINA_INLIST_GET(seg)); free(seg); } + ecore_job_del(pd->draw_text_job); + +#ifdef EFL_UI_TEXTPATH_LINE_DEBUG + Evas_Object *line; + EINA_LIST_FREE(pd->lines, line) + evas_object_del(line); +#endif efl_destructor(efl_super(obj, MY_CLASS)); } @@ -533,17 +646,17 @@ _efl_ui_textpath_text_get(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd, const c EOLIAN static void _efl_ui_textpath_efl_text_text_set(Eo *obj, Efl_Ui_Textpath_Data *pd, const char *text) { - _textpath_text_set_internal(obj, pd, "elm.text", text); + _textpath_text_set_internal(obj, pd, "efl.text", text); } EOLIAN static const char * -_efl_ui_textpath_efl_text_text_get(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd) +_efl_ui_textpath_efl_text_text_get(const Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd) { - return edje_object_part_text_get(pd->text_obj, "elm.text"); + return edje_object_part_text_get(pd->text_obj, "efl.text"); } EOLIAN static Efl_Ui_Theme_Apply -_efl_ui_textpath_elm_widget_theme_apply(Eo *obj, Efl_Ui_Textpath_Data *pd) +_efl_ui_textpath_efl_ui_widget_theme_apply(Eo *obj, Efl_Ui_Textpath_Data *pd) { Efl_Ui_Theme_Apply ret = EFL_UI_THEME_APPLY_FAILED; @@ -558,17 +671,17 @@ _efl_ui_textpath_elm_widget_theme_apply(Eo *obj, Efl_Ui_Textpath_Data *pd) } EOLIAN static void -_efl_ui_textpath_efl_gfx_position_set(Eo *obj, Efl_Ui_Textpath_Data *pd, Eina_Position2D pos) +_efl_ui_textpath_efl_gfx_entity_position_set(Eo *obj, Efl_Ui_Textpath_Data *pd, Eina_Position2D pos) { - efl_gfx_position_set(efl_super(obj, MY_CLASS), pos); + efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), pos); _path_data_get(obj, pd, EINA_FALSE); - _text_draw(pd); + _sizing_eval(pd); } EOLIAN static void -_efl_ui_textpath_efl_gfx_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 sz) { - efl_gfx_size_set(efl_super(obj, MY_CLASS), sz); + efl_gfx_entity_size_set(efl_super(obj, MY_CLASS), sz); } EOLIAN static void @@ -604,22 +717,8 @@ _efl_ui_textpath_circle_set(Eo *obj, Efl_Ui_Textpath_Data *pd, double x, double _sizing_eval(pd); } -EOLIAN static Eina_Bool -_efl_ui_textpath_autofit_get(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd) -{ - return pd->autofit; -} - -EOLIAN static void -_efl_ui_textpath_autofit_set(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd, Eina_Bool autofit) -{ - if (pd->autofit == autofit) return; - pd->autofit = autofit; - _sizing_eval(pd); -} - EOLIAN static int -_efl_ui_textpath_slice_number_get(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd) +_efl_ui_textpath_slice_number_get(const Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd) { return pd->slice_no; } @@ -643,7 +742,7 @@ _efl_ui_textpath_ellipsis_set(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd, Ein } EOLIAN static Eina_Bool -_efl_ui_textpath_ellipsis_get(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd) +_efl_ui_textpath_ellipsis_get(const Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd) { return pd->ellipsis; } |