summaryrefslogtreecommitdiff
path: root/src/lib/elementary/efl_ui_textpath.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/elementary/efl_ui_textpath.c')
-rw-r--r--src/lib/elementary/efl_ui_textpath.c253
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;
}