summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThiep Ha <thiepha@gmail.com>2017-07-03 08:02:51 +0900
committerThiep Ha <thiepha@gmail.com>2017-07-03 08:02:51 +0900
commit94709ac65045ee0e7b9bfb1b6c19cde609541345 (patch)
tree8679640918061c4804768382a1375f196bf7dd97
parent5f2e4b9197cb96184c8e8acde10b5d8da8ac8662 (diff)
ui.textpath: first implementation
implementation for efl.ui.textpath is on going. Can run example and see textpath displayed on circle.
-rw-r--r--src/Makefile_Elementary.am2
-rw-r--r--src/bin/elementary/test_efl_ui_textpath.c38
-rw-r--r--src/lib/elementary/Elementary.h1
-rw-r--r--src/lib/elementary/efl_ui_textpath.c323
-rw-r--r--src/lib/elementary/efl_ui_textpath.eo59
5 files changed, 423 insertions, 0 deletions
diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am
index e5c6704da7..2f9a08278c 100644
--- a/src/Makefile_Elementary.am
+++ b/src/Makefile_Elementary.am
@@ -127,6 +127,7 @@ elm_public_eolian_files = \
127 lib/elementary/efl_ui_focus_manager_root_focus.eo \ 127 lib/elementary/efl_ui_focus_manager_root_focus.eo \
128 lib/elementary/efl_ui_focus_object.eo \ 128 lib/elementary/efl_ui_focus_object.eo \
129 lib/elementary/efl_ui_focus_user.eo \ 129 lib/elementary/efl_ui_focus_user.eo \
130 lib/elementary/efl_ui_textpath.eo \
130 $(NULL) 131 $(NULL)
131 132
132# Private classes (not exposed or shipped) 133# Private classes (not exposed or shipped)
@@ -682,6 +683,7 @@ lib_elementary_libelementary_la_SOURCES = \
682 lib/elementary/efl_ui_focus_manager_sub.c \ 683 lib/elementary/efl_ui_focus_manager_sub.c \
683 lib/elementary/efl_ui_focus_object.c \ 684 lib/elementary/efl_ui_focus_object.c \
684 lib/elementary/efl_ui_focus_manager_root_focus.c \ 685 lib/elementary/efl_ui_focus_manager_root_focus.c \
686 lib/elementary/efl_ui_textpath.c \
685 $(NULL) 687 $(NULL)
686 688
687 689
diff --git a/src/bin/elementary/test_efl_ui_textpath.c b/src/bin/elementary/test_efl_ui_textpath.c
new file mode 100644
index 0000000000..75b89863d0
--- /dev/null
+++ b/src/bin/elementary/test_efl_ui_textpath.c
@@ -0,0 +1,38 @@
1//FIXME: change to test style, not example style
2
3#ifndef EFL_BETA_API_SUPPORT
4# define EFL_BETA_API_SUPPORT
5#endif
6
7#ifndef EFL_EO_API_SUPPORT
8# define EFL_EO_API_SUPPORT
9#endif
10
11#include <Elementary.h>
12
13#define WIDTH 800
14#define HEIGHT 400
15
16EAPI_MAIN int
17elm_main(int argc, char *argv[])
18{
19 Evas_Object *win, *txtpath;
20
21 elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
22 win = elm_win_util_standard_add("efl.ui.textpath", "TextPath test");
23 elm_win_autodel_set(win, EINA_TRUE);
24
25 txtpath = efl_add(EFL_UI_TEXTPATH_CLASS, win);
26 efl_ui_textpath_circle_set(txtpath, 200, 200, 100, 45);
27 //efl_ui_textpath_autofit_set(txtpath, EINA_TRUE);
28 //efl_text_set(txtpath, "abcdef and more you can see from this test");
29 efl_text_set(txtpath, "abcdefghijklm");
30 efl_gfx_geometry_set(txtpath, 0, 0, 200, 200);
31 efl_gfx_visible_set(txtpath, EINA_TRUE);
32
33 elm_win_resize_object_add(win, txtpath);
34 evas_object_resize(win, WIDTH, HEIGHT);
35 evas_object_show(win);
36 elm_run();
37}
38ELM_MAIN();
diff --git a/src/lib/elementary/Elementary.h b/src/lib/elementary/Elementary.h
index 4ec11f3c2c..cf82af0a10 100644
--- a/src/lib/elementary/Elementary.h
+++ b/src/lib/elementary/Elementary.h
@@ -280,6 +280,7 @@ EAPI extern Elm_Version *elm_version;
280# include <efl_ui_text_editable.eo.h> 280# include <efl_ui_text_editable.eo.h>
281# include <efl_ui_clock.eo.h> 281# include <efl_ui_clock.eo.h>
282# include <efl_ui_image_factory.eo.h> 282# include <efl_ui_image_factory.eo.h>
283# include <efl_ui_textpath.eo.h>
283#endif 284#endif
284 285
285/* include deprecated calls last of all */ 286/* include deprecated calls last of all */
diff --git a/src/lib/elementary/efl_ui_textpath.c b/src/lib/elementary/efl_ui_textpath.c
new file mode 100644
index 0000000000..6ebc2ef75f
--- /dev/null
+++ b/src/lib/elementary/efl_ui_textpath.c
@@ -0,0 +1,323 @@
1#ifdef HAVE_CONFIG_H
2# include "elementary_config.h"
3#endif
4
5#include <Elementary.h>
6#include "elm_priv.h"
7
8#include "elm_widget_layout.h"
9
10
11#define MY_CLASS EFL_UI_TEXTPATH_CLASS
12
13#define PI 3.14159265
14#define SLICE_MAX 200
15#define SLICE_DEFAULT_NO 69
16
17typedef struct _Efl_Ui_Textpath_Data Efl_Ui_Textpath_Data;
18
19struct _Efl_Ui_Textpath_Data {
20 Evas_Object *content;
21 char *text;
22 Evas_Object *proxy;
23 Efl_Gfx_Path *path;
24 struct {
25 double x, y;
26 double radius;
27 double start_angle;
28 } circle;
29 Efl_Ui_Textpath_Orientation ori;
30 int slice_no;
31 Eina_Bool autofit;
32};
33
34static inline double
35_deg_to_rad(double angle)
36{
37 return angle / 180 * PI;
38}
39
40static inline void
41_transform_coord(double x, double y, double rad, double cx, double cy,
42 int *tx, int *ty)
43{
44 if (tx) *tx = (int)(x * cos(rad) - y * sin(rad) + cx);
45 if (ty) *ty = (int)(x * sin(rad) + y * cos(rad) + cy);
46}
47
48static void
49_circle_draw(Efl_Ui_Textpath_Data *pd)
50{
51 Evas_Coord x, y, w, h;
52 Evas_Object *proxy;
53 Evas *e;
54 Evas_Map *map;
55 int slice_no, tx, ty;
56 double total_angle, start_angle, angle, dist;
57 double u0, u1, v0, v1;
58 int i;
59
60 if (!pd->content) return;
61
62 efl_gfx_geometry_get(pd->content, &x, &y, &w, &h);
63 ERR("content geo: %d %d %d %d", x, y, w, h);
64 e = evas_object_evas_get(pd->content);
65
66 if (pd->autofit)
67 {
68 total_angle = (360 * w) / (2 * PI * (pd->circle.radius - h));
69 if (total_angle > 360) total_angle = 360;
70
71 slice_no = ((pd->slice_no * total_angle) / 360) + 1;
72 if (slice_no > pd->slice_no) slice_no = pd->slice_no;
73 }
74 else
75 {
76 slice_no = pd->slice_no;
77 total_angle = 360;
78 }
79 ERR("total angle: %.1f, slice no: %d, pd->slice_no: %d", total_angle, slice_no, pd->slice_no);
80
81 dist = (double)w / slice_no;
82 angle = _deg_to_rad(total_angle / slice_no);
83 start_angle = _deg_to_rad(pd->circle.start_angle);
84
85 if (pd->proxy)
86 efl_del(pd->proxy);
87 proxy = evas_object_image_filled_add(e);
88 pd->proxy = proxy;
89 efl_gfx_size_set(proxy, w, h);
90 evas_object_image_source_set(proxy, pd->content);
91 efl_gfx_visible_set(proxy, EINA_TRUE);
92
93 map = evas_map_new(slice_no * 4);
94
95 for (i = 0; i < slice_no; i++)
96 {
97 _transform_coord(0, -pd->circle.radius,
98 i * angle + start_angle,
99 pd->circle.x, pd->circle.y,
100 &tx, &ty);
101 evas_map_point_coord_set(map, i * 4, tx, ty, 0);
102 _transform_coord(0, -pd->circle.radius,
103 (i + 1) * angle + start_angle,
104 pd->circle.x, pd->circle.y,
105 &tx, &ty);
106 evas_map_point_coord_set(map, i * 4 + 1, tx, ty, 0);
107 _transform_coord(0, -(pd->circle.radius - h),
108 (i + 1) * angle + start_angle,
109 pd->circle.x, pd->circle.y,
110 &tx, &ty);
111 evas_map_point_coord_set(map, i * 4 + 2, tx, ty, 0);
112 _transform_coord(0, -(pd->circle.radius - h),
113 i * angle + start_angle,
114 pd->circle.x, pd->circle.y,
115 &tx, &ty);
116 evas_map_point_coord_set(map, i * 4 + 3, tx, ty, 0);
117
118 //uv
119 u0 = i * dist;
120 u1 = u0 + dist;
121 v0 = 0.0;
122 v1 = h;
123
124 evas_map_point_image_uv_set(map, i * 4, u0, v0);
125 evas_map_point_image_uv_set(map, i * 4 + 1, u1, v0);
126 evas_map_point_image_uv_set(map, i * 4 + 2, u1, v1);
127 evas_map_point_image_uv_set(map, i * 4 + 3, u0, v1);
128
129#if 0
130 if (u1 > w)
131 {
132 ERR("out of content's width");
133 break;
134 }
135#endif
136 }
137 evas_object_map_enable_set(proxy, EINA_TRUE);
138 evas_object_map_set(proxy, map);
139 evas_map_free(map);
140
141 //debug
142 x = pd->circle.x;
143 y = pd->circle.y;
144 double r = pd->circle.radius;
145 Eo *line = evas_object_line_add(e);
146 efl_gfx_color_set(line, 100, 0, 0, 100);
147 efl_gfx_visible_set(line, EINA_TRUE);
148 evas_object_line_xy_set(line, x, y - r, x, y + r);
149
150 line = evas_object_line_add(e);
151 efl_gfx_color_set(line, 100, 100, 0, 100);
152 efl_gfx_visible_set(line, EINA_TRUE);
153 evas_object_line_xy_set(line, x - r, y, x + r, y);
154}
155
156static void
157_sizing_eval(Efl_Ui_Textpath_Data *pd)
158{
159 _circle_draw(pd);
160}
161
162static void
163_content_resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
164{
165 Efl_Ui_Textpath_Data *pd = data;
166 _sizing_eval(pd);
167}
168
169//exposed API
170EOLIAN static void
171_efl_ui_textpath_elm_layout_sizing_eval(Eo *obj, Efl_Ui_Textpath_Data *pd)
172{
173 ERR("In");
174 _sizing_eval(pd);
175}
176
177EOLIAN static void
178_efl_ui_textpath_class_constructor(Eo *obj, Efl_Ui_Textpath_Data *pd)
179{
180}
181
182EOLIAN static Efl_Object *
183_efl_ui_textpath_efl_object_constructor(Eo *obj, Efl_Ui_Textpath_Data *pd)
184{
185 ERR("in");
186 obj = efl_constructor(efl_super(obj, MY_CLASS));
187 pd->autofit = EINA_TRUE;
188 pd->slice_no = 99;
189 pd->ori = EFL_UI_TEXTPATH_ORIENTATION_LEFT_TO_RIGHT;
190
191 return obj;
192}
193
194EOLIAN static void
195_efl_ui_textpath_efl_object_destructor(Eo *obj, Efl_Ui_Textpath_Data *pd)
196{
197 if (pd->content) evas_object_del(pd->content);
198 if (pd->text) free(pd->text);
199 efl_destructor(efl_super(obj, MY_CLASS));
200}
201
202EOLIAN static void
203_efl_ui_textpath_efl_text_text_set(Eo *obj, Efl_Ui_Textpath_Data *pd, const char *text)
204{
205 ERR("in: %s", text);
206 Evas_Object *content;
207 if (pd->text) free(pd->text);
208 if (pd->content)
209 {
210 //efl_del(pd->content);
211 evas_object_del(pd->content);
212 pd->content = NULL;
213 }
214 if (!text) return;
215 int len = strlen(text);
216 pd->text = malloc(sizeof(char) * (len + 1));
217 if (!pd->text) return;
218 strncpy(pd->text, text, len);
219 pd->text[len] = '\0';
220 content = evas_object_text_add(evas_object_evas_get(obj)); //efl_add(EVAS_TEXT_CLASS, obj);
221 evas_object_text_font_set(content, "century schoolbook l", 20); //FIXME: which font and size???
222 efl_text_set(content, pd->text);
223 efl_gfx_size_hint_min_set(content, 10, 50); //FIXME: remove it
224 efl_gfx_size_hint_weight_set(content, EFL_GFX_SIZE_HINT_FILL,
225 EFL_GFX_SIZE_HINT_FILL);
226 efl_gfx_position_set(content, 0, 0);
227 evas_object_event_callback_add(content, EVAS_CALLBACK_RESIZE, _content_resize_cb, pd);
228 efl_gfx_size_set(content, 2 * pd->circle.radius, 2 * pd->circle.radius);
229 evas_object_show(content);
230
231 pd->content = content;
232 ERR("show content: w h: %.0f", 2 * pd->circle.radius);
233 _sizing_eval(pd);
234}
235
236EOLIAN static const char *
237_efl_ui_textpath_efl_text_text_get(Eo *obj, Efl_Ui_Textpath_Data *pd)
238{
239 return pd->text;
240}
241
242//we cannot know the internal of efl_gfx_path
243//therefore, we cannot draw text on it.
244//cannot support this api
245EOLIAN static Efl_Gfx_Path *
246_efl_ui_textpath_path_get(Eo *obj, Efl_Ui_Textpath_Data *pd)
247{
248 return pd->path;
249}
250
251EOLIAN static void
252_efl_ui_textpath_path_set(Eo *obj, Efl_Ui_Textpath_Data *pd, Efl_Gfx_Path *path)
253{
254 pd->path = path;
255}
256//////
257
258EOLIAN static void
259_efl_ui_textpath_circle_set(Eo *obj, Efl_Ui_Textpath_Data *pd, double x, double y, double radius, double start_angle)
260{
261 if (pd->circle.x == x && pd->circle.y == y &&
262 pd->circle.radius == radius &&
263 pd->circle.start_angle == start_angle)
264 {
265 ERR("Same circle");
266 return;
267 }
268 pd->circle.x = x;
269 pd->circle.y = y;
270 pd->circle.radius = radius;
271 pd->circle.start_angle = start_angle;
272
273 if (pd->content)
274 {
275 efl_gfx_size_set(pd->content, 2 * radius, 2 * radius);
276 }
277
278 _sizing_eval(pd);
279}
280
281EOLIAN static Efl_Ui_Textpath_Orientation
282_efl_ui_textpath_orientation_get(Eo *obj, Efl_Ui_Textpath_Data *pd)
283{
284 return pd->ori;
285}
286
287EOLIAN static void
288_efl_ui_textpath_orientation_set(Eo *obj, Efl_Ui_Textpath_Data *pd, Efl_Ui_Textpath_Orientation orientation)
289{
290 if (pd->ori == orientation) return;
291 pd->ori = orientation;
292}
293
294EOLIAN static Eina_Bool
295_efl_ui_textpath_autofit_get(Eo *obj, Efl_Ui_Textpath_Data *pd)
296{
297 return pd->autofit;
298}
299
300EOLIAN static void
301_efl_ui_textpath_autofit_set(Eo *obj, Efl_Ui_Textpath_Data *pd, Eina_Bool autofit)
302{
303 if (pd->autofit == autofit) return;
304 pd->autofit = autofit;
305 _sizing_eval(pd);
306}
307
308EOLIAN static int
309_efl_ui_textpath_slice_number_get(Eo *obj, Efl_Ui_Textpath_Data *pd)
310{
311 return pd->slice_no;
312}
313
314EOLIAN static void
315_efl_ui_textpath_slice_number_set(Eo *obj, Efl_Ui_Textpath_Data *pd, int slice_no)
316{
317 if (pd->slice_no == slice_no) return;
318 pd->slice_no = slice_no;
319 _sizing_eval(pd);
320}
321
322
323#include "efl_ui_textpath.eo.c"
diff --git a/src/lib/elementary/efl_ui_textpath.eo b/src/lib/elementary/efl_ui_textpath.eo
new file mode 100644
index 0000000000..5a83b675d9
--- /dev/null
+++ b/src/lib/elementary/efl_ui_textpath.eo
@@ -0,0 +1,59 @@
1enum Efl.Ui.Textpath.Orientation {
2 left_to_right,
3 right_to_left
4}
5
6class Efl.Ui.Textpath (Elm.Layout, Efl.Object, Efl.Text)
7{
8 [[Efl Ui Textpath class]]
9 methods {
10 @property path {
11 [[The path to place text.
12 Currently, it only supports circle and points paths.]]
13 values {
14 path: Efl.Gfx.Path;
15 }
16 }
17 circle_set {
18 [[Set a circle with given center, radius, and start angle.]]
19 params {
20 @in x: double;
21 @in y: double;
22 @in radius: double;
23 @in start_angle: double;
24 }
25 }
26 @property orientation {
27 [[The orientation where text is placed:
28 left-to-right or right-to-left]]
29 values {
30 orient: Efl.Ui.Textpath.Orientation;
31 }
32 }
33 @property autofit {
34 [[The ability to fit the text within the path.
35 Set it to EINA_TRUE to let text occupy only portion
36 same as its size. Otherwise, text will occupied the whole path.
37 By default, it is EINA_TRUE.]]
38 values {
39 autofit: bool;
40 }
41 }
42 @property slice_number {
43 [[The number of slices. The larger the number of slice_num is,
44 The better the text follow the path.]]
45 values {
46 slice_no: int;
47 }
48 }
49 }
50 implements {
51 class.constructor;
52 Efl.Object.constructor;
53 Efl.Object.destructor;
54 Elm.Layout.sizing_eval;
55 Efl.Text.text {get; set;}
56 }
57 events {
58 }
59}