1 #define EFL_CANVAS_FILTER_INTERNAL_PROTECTED
2
3 #include "evas_common_private.h" /* Includes evas_bidi_utils stuff. */
4 #include "evas_private.h"
5
6 #include "../efl/interfaces/efl_gfx_filter.eo.h"
7 #include "efl_canvas_filter_internal.eo.h"
8 #include "evas_filter.h"
9
10 #define MY_CLASS EVAS_TEXT_CLASS
11
12 #define MY_CLASS_NAME "Evas_Text"
13
14 /* save typing */
15 #define COL_OBJECT(obj, sub) ARGB_JOIN(obj->sub->color.a, obj->sub->color.r, obj->sub->color.g, obj->sub->color.b)
16 #define COL_JOIN(o, sub, color) ARGB_JOIN(o->sub.color.a, o->sub.color.r, o->sub.color.g, o->sub.color.b)
17
18 /* private magic number for text objects */
19 static const char o_type[] = "text";
20
21 /* private struct for text object internal data */
22 typedef struct _Evas_Text_Data Evas_Text_Data;
23 typedef struct _Evas_Object_Text_Item Evas_Object_Text_Item;
24
25 struct _Evas_Text_Data
26 {
27 DATA32 magic;
28
29 struct {
30 // WARNING - you cannot change the below outline/shadow etc. members
31 // and their content without also updating _color_same() in this
32 // file
33 struct {
34 unsigned char r, g, b, a;
35 } outline, shadow, glow, glow2;
36
37 const char *utf8_text; /* The text exposed to the API */
38 const char *font;
39 Evas_Font_Description *fdesc;
40 const char *source;
41 Eina_Unicode *text;
42
43 double ellipsis;
44
45 Evas_Font_Size size;
46 Evas_Text_Style_Type style;
47 Efl_Text_Font_Bitmap_Scalable bitmap_scalable;
48 } cur, prev;
49
50 struct {
51 Evas_Object_Text_Item *ellipsis_start;
52 Evas_Object_Text_Item *ellipsis_end;
53 Evas_Coord w, h;
54 int advance;
55 int width_without_ellipsis;
56 Eina_Bool ellipsis;
57 } last_computed;
58
59 Evas_BiDi_Paragraph_Props *bidi_par_props;
60 const char *bidi_delimiters;
61 Evas_Object_Text_Item *items;
62
63 Evas_Font_Set *font;
64
65 float ascent, descent;
66 float max_ascent, max_descent;
67
68 Evas_BiDi_Direction bidi_dir : 2;
69 Evas_BiDi_Direction paragraph_direction : 2;
70 Eina_Bool inherit_paragraph_direction : 1;
71 Eina_Bool changed_paragraph_direction : 1;
72 Eina_Bool changed : 1;
73 Eina_Bool has_filter : 1;
74 };
75
76 struct _Evas_Object_Text_Item
77 {
78 EINA_INLIST;
79
80 size_t text_pos;
81 size_t visual_pos;
82 Evas_Text_Props text_props;
83 Evas_Coord x, w, h, adv;
84 };
85
86 /* private methods for text objects */
87 static void evas_object_text_init(Evas_Object *eo_obj);
88 static void evas_object_text_render(Evas_Object *eo_obj,
89 Evas_Object_Protected_Data *obj,
90 void *type_private_data,
91 void *engine, void *output, void *context, void *surface,
92 int x, int y, Eina_Bool do_async);
93 static void evas_object_text_free(Evas_Object *eo_obj,
94 Evas_Object_Protected_Data *obj);
95 static void evas_object_text_render_pre(Evas_Object *eo_obj,
96 Evas_Object_Protected_Data *obj,
97 void *type_private_data);
98 static void evas_object_text_render_post(Evas_Object *eo_obj,
99 Evas_Object_Protected_Data *obj,
100 void *type_private_data);
101
102 static void *evas_object_text_engine_data_get(Evas_Object *eo_obj);
103
104 static int evas_object_text_is_opaque(Evas_Object *eo_obj,
105 Evas_Object_Protected_Data *obj,
106 void *type_private_data);
107 static int evas_object_text_was_opaque(Evas_Object *eo_obj,
108 Evas_Object_Protected_Data *obj,
109 void *type_private_data);
110
111 static void _evas_object_text_recalc(Evas_Object *eo_obj, Eina_Unicode *text);
112
113 static const Evas_Object_Func object_func =
114 {
115 /* methods (compulsory) */
116 NULL,
117 evas_object_text_render,
118 evas_object_text_render_pre,
119 evas_object_text_render_post,
120 evas_object_text_engine_data_get,
121 /* these are optional. NULL = nothing */
122 NULL,
123 NULL,
124 evas_object_text_is_opaque,
125 evas_object_text_was_opaque,
126 NULL,
127 NULL,
128 NULL,
129 NULL,
130 NULL,
131 NULL,
132 NULL // render_prepare
133 };
134
135 /* the actual api call to add a rect */
136 /* it has no other api calls as all properties are standard */
137
138 static int
_evas_object_text_char_coords_get(const Evas_Object * eo_obj,const Evas_Text_Data * o,size_t pos,Evas_Coord * x,Evas_Coord * y,Evas_Coord * w,Evas_Coord * h)139 _evas_object_text_char_coords_get(const Evas_Object *eo_obj,
140 const Evas_Text_Data *o,
141 size_t pos, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
142 {
143 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
144 Evas_Object_Text_Item *it;
145
146 EINA_INLIST_FOREACH(EINA_INLIST_GET(o->items), it)
147 {
148 if ((it->text_pos <= pos) &&
149 (pos < (it->text_pos + it->text_props.text_len)))
150 {
151 int ret;
152 ret = ENFN->font_char_coords_get(ENC, o->font,
153 &it->text_props, pos - it->text_pos, x, y, w, h);
154 if (x) *x += it->x;
155 return ret;
156 }
157 }
158 return 0;
159 }
160
161 static void
_evas_object_text_item_clean(Evas_Object_Text_Item * it)162 _evas_object_text_item_clean(Evas_Object_Text_Item *it)
163 {
164 evas_common_text_props_content_unref(&it->text_props);
165 }
166
167 static void
_evas_object_text_item_del(Evas_Text_Data * o,Evas_Object_Text_Item * it)168 _evas_object_text_item_del(Evas_Text_Data *o, Evas_Object_Text_Item *it)
169 {
170 if (o->last_computed.ellipsis_start == it)
171 o->last_computed.ellipsis_start = NULL;
172 else if (o->last_computed.ellipsis_end == it)
173 o->last_computed.ellipsis_end = NULL;
174
175 if ((EINA_INLIST_GET(it)->next) ||
176 (EINA_INLIST_GET(it)->prev) ||
177 (EINA_INLIST_GET(o->items) == (EINA_INLIST_GET(it))))
178 o->items = (Evas_Object_Text_Item *)eina_inlist_remove
179 (EINA_INLIST_GET(o->items), EINA_INLIST_GET(it));
180 _evas_object_text_item_clean(it);
181 free(it);
182 }
183
184 static inline Eina_Bool
_color_same(const void * col1,const void * col2)185 _color_same(const void *col1, const void *col2)
186 {
187 const unsigned int *icol1 = col1, *icol2 = col2;
188 return (*icol1 == *icol2);
189 }
190
191 static void
_evas_object_text_items_clean(Evas_Object_Protected_Data * obj,Evas_Text_Data * o)192 _evas_object_text_items_clean(Evas_Object_Protected_Data *obj, Evas_Text_Data *o)
193 {
194 /* FIXME: also preserve item */
195 if ((o->cur.font == o->prev.font) &&
196 (o->cur.fdesc == o->prev.fdesc) &&
197 (o->cur.size == o->prev.size) &&
198 (_color_same(&o->cur.outline, &o->prev.outline)) &&
199 (_color_same(&o->cur.shadow, &o->prev.shadow)) &&
200 (_color_same(&o->cur.glow, &o->prev.glow)) &&
201 (_color_same(&o->cur.glow2, &o->prev.glow2)) &&
202 (o->cur.style == o->prev.style) &&
203 (EINA_DBL_EQ(obj->cur->scale, obj->prev->scale)))
204 {
205 if ((o->last_computed.ellipsis_start) &&
206 (o->last_computed.ellipsis_start == o->items))
207 o->items = (Evas_Object_Text_Item *) eina_inlist_remove(EINA_INLIST_GET(o->items),
208 EINA_INLIST_GET(o->last_computed.ellipsis_start));
209 if ((o->last_computed.ellipsis_end) &&
210 (EINA_INLIST_GET(o->last_computed.ellipsis_end) == EINA_INLIST_GET(o->items)->last))
211 o->items = (Evas_Object_Text_Item *) eina_inlist_remove(EINA_INLIST_GET(o->items),
212 EINA_INLIST_GET(o->last_computed.ellipsis_end));
213 }
214 else
215 {
216 /* It is not guaranteed that the ellipsis are still inside the items, so remove them by force */
217 if (o->last_computed.ellipsis_start)
218 _evas_object_text_item_del(o, o->last_computed.ellipsis_start);
219 o->last_computed.ellipsis_start = NULL;
220
221 if (o->last_computed.ellipsis_end)
222 _evas_object_text_item_del(o, o->last_computed.ellipsis_end);
223 o->last_computed.ellipsis_end = NULL;
224 }
225 while (o->items)
226 {
227 _evas_object_text_item_del(o, o->items);
228 }
229 }
230
231 static void
_evas_object_text_items_clear(Evas_Text_Data * o)232 _evas_object_text_items_clear(Evas_Text_Data *o)
233 {
234 if ((o->last_computed.ellipsis_start) &&
235 (o->last_computed.ellipsis_start != o->items))
236 {
237 _evas_object_text_item_del(o, o->last_computed.ellipsis_start);
238 }
239 o->last_computed.ellipsis_start = NULL;
240 if ((o->last_computed.ellipsis_end) &&
241 (EINA_INLIST_GET(o->last_computed.ellipsis_end) != EINA_INLIST_GET(o->items)->last))
242 {
243 _evas_object_text_item_del(o, o->last_computed.ellipsis_end);
244 }
245 o->last_computed.ellipsis_end = NULL;
246 while (o->items)
247 {
248 _evas_object_text_item_del(o, o->items);
249 }
250 }
251
252 #ifdef BIDI_SUPPORT
253 static int
_evas_object_text_it_compare_logical(const void * _it1,const void * _it2)254 _evas_object_text_it_compare_logical(const void *_it1, const void *_it2)
255 {
256 const Evas_Object_Text_Item *it1 = _it1, *it2 = _it2;
257 if (it1->text_pos < it2->text_pos)
258 return -1;
259 else if (it1->text_pos == it2->text_pos)
260 return 0;
261 else
262 return 1;
263
264 }
265 #endif
266
267 static int
_evas_object_text_last_up_to_pos(const Evas_Object * eo_obj,const Evas_Text_Data * o,Evas_Coord cx,Evas_Coord cy)268 _evas_object_text_last_up_to_pos(const Evas_Object *eo_obj,
269 const Evas_Text_Data *o, Evas_Coord cx, Evas_Coord cy)
270 {
271 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
272 Evas_Object_Text_Item *it;
273 int pos = -1;
274
275 #ifdef BIDI_SUPPORT
276 /* Reorder if it's a bidi text */
277 if (o->bidi_par_props)
278 {
279 Eina_List *logical_it = NULL;
280 Evas_Object_Text_Item *i;
281 Eina_List *itr;
282 Evas_Coord x = 0;
283 /* Insert all to the logical list */
284 EINA_INLIST_FOREACH(o->items, i)
285 {
286 logical_it = eina_list_sorted_insert(logical_it,
287 _evas_object_text_it_compare_logical, i);
288 }
289 EINA_LIST_FOREACH(logical_it, itr, it)
290 {
291 if ((x <= cx) && (cx < x + it->adv))
292 {
293 pos = it->text_pos + ENFN->font_last_up_to_pos(ENC,
294 o->font,
295 &it->text_props,
296 cx - x,
297 cy, 0);
298 break;
299 }
300 x += it->adv;
301 }
302 eina_list_free(logical_it);
303 }
304 else
305 #endif
306 {
307 EINA_INLIST_FOREACH(EINA_INLIST_GET(o->items), it)
308 {
309 if ((it->x <= cx) && (cx < it->x + it->adv))
310 {
311 return it->text_pos + ENFN->font_last_up_to_pos(ENC,
312 o->font,
313 &it->text_props,
314 cx - it->x,
315 cy, 0);
316 }
317 }
318 }
319 return pos;
320 }
321
322 static int
_evas_object_text_char_at_coords(const Evas_Object * eo_obj,const Evas_Text_Data * o,Evas_Coord cx,Evas_Coord cy,Evas_Coord * rx,Evas_Coord * ry,Evas_Coord * rw,Evas_Coord * rh)323 _evas_object_text_char_at_coords(const Evas_Object *eo_obj,
324 const Evas_Text_Data *o, Evas_Coord cx, Evas_Coord cy,
325 Evas_Coord *rx, Evas_Coord *ry, Evas_Coord *rw, Evas_Coord *rh)
326 {
327 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
328 Evas_Object_Text_Item *it;
329
330 EINA_INLIST_FOREACH(EINA_INLIST_GET(o->items), it)
331 {
332 if ((it->x <= cx) && (cx < it->x + it->adv))
333 {
334 return it->text_pos + ENFN->font_char_at_coords_get(ENC,
335 o->font,
336 &it->text_props,
337 cx - it->x,
338 cy,
339 rx, ry,
340 rw, rh);
341 }
342 }
343 return -1;
344 }
345
346 static Evas_Coord
_evas_object_text_horiz_width_without_ellipsis_get(const Evas_Text_Data * o)347 _evas_object_text_horiz_width_without_ellipsis_get(const Evas_Text_Data *o)
348 {
349 return o->last_computed.width_without_ellipsis;
350 }
351
352 static Evas_Coord
_evas_object_text_horiz_advance_get(const Evas_Text_Data * o)353 _evas_object_text_horiz_advance_get(const Evas_Text_Data *o)
354 {
355 return o->last_computed.advance;
356 }
357
358 static Evas_Coord
_evas_object_text_vert_advance_get(const Evas_Object * obj EINA_UNUSED,const Evas_Text_Data * o)359 _evas_object_text_vert_advance_get(const Evas_Object *obj EINA_UNUSED,
360 const Evas_Text_Data *o)
361 {
362 return o->max_ascent + o->max_descent;
363 }
364
365 EAPI Evas_Object *
evas_object_text_add(Evas * e)366 evas_object_text_add(Evas *e)
367 {
368 e = evas_find(e);
369 EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(e, EVAS_CANVAS_CLASS), NULL);
370 return efl_add(EVAS_TEXT_CLASS, e, efl_canvas_object_legacy_ctor(efl_added));
371 }
372
373 EOLIAN static Eo *
_evas_text_efl_object_constructor(Eo * eo_obj,Evas_Text_Data * o EINA_UNUSED)374 _evas_text_efl_object_constructor(Eo *eo_obj, Evas_Text_Data *o EINA_UNUSED)
375 {
376 eo_obj = efl_constructor(efl_super(eo_obj, MY_CLASS));
377 evas_object_text_init(eo_obj);
378
379 return eo_obj;
380 }
381
382 EOLIAN static void
_evas_text_efl_text_font_font_source_set(Eo * eo_obj,Evas_Text_Data * o,const char * font_source)383 _evas_text_efl_text_font_font_source_set(Eo *eo_obj, Evas_Text_Data *o, const char *font_source)
384 {
385 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
386 if (((o->cur.source) && (font_source) &&
387 (!strcmp(o->cur.source, font_source))) ||
388 (!o->cur.source && !font_source))
389 return;
390 evas_object_async_block(obj);
391 /*
392 if (o->cur.source) eina_stringshare_del(o->cur.source);
393 if (font_source) o->cur.source = eina_stringshare_add(font_source);
394 else o->cur.source = NULL;
395 */
396 eina_stringshare_replace(&o->cur.source, font_source);
397 }
398
399 EOLIAN static const char*
_evas_text_efl_text_font_font_source_get(const Eo * eo_obj EINA_UNUSED,Evas_Text_Data * o)400 _evas_text_efl_text_font_font_source_get(const Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o)
401 {
402 return o->cur.source;
403 }
404
405 static void
_evas_text_font_reload(Eo * eo_obj,Evas_Text_Data * o)406 _evas_text_font_reload(Eo *eo_obj, Evas_Text_Data *o)
407 {
408 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
409 Eina_Bool pass = EINA_FALSE, freeze = EINA_FALSE;
410 Eina_Bool source_invisible = EINA_FALSE;
411 Eina_List *was = NULL;
412
413 if (o->cur.size == 0 || (!o->cur.font && !o->cur.source)) return ;
414
415 if (!(obj->layer->evas->is_frozen))
416 {
417 pass = evas_event_passes_through(eo_obj, obj);
418 freeze = evas_event_freezes_through(eo_obj, obj);
419 source_invisible = evas_object_is_source_invisible(eo_obj, obj);
420 if ((!pass) && (!freeze) && (!source_invisible))
421 was = _evas_pointer_list_in_rect_get(obj->layer->evas, eo_obj, obj,
422 1, 1);
423 }
424
425 /* DO IT */
426 evas_font_free(o->font);
427 o->font = NULL;
428
429 o->font = evas_font_load(obj->layer->evas->font_path,
430 obj->layer->evas->hinting,
431 o->cur.fdesc, o->cur.source,
432 (int)(((double) o->cur.size) * obj->cur->scale),
433 o->cur.bitmap_scalable);
434 {
435 o->ascent = 0;
436 o->descent = 0;
437 o->max_ascent = 0;
438 o->max_descent = 0;
439 }
440 _evas_object_text_items_clear(o);
441 _evas_object_text_recalc(eo_obj, o->cur.text);
442 o->changed = 1;
443 if (o->has_filter)
444 evas_filter_changed_set(eo_obj, EINA_TRUE);
445 evas_object_change(eo_obj, obj);
446 evas_object_clip_dirty(eo_obj, obj);
447 evas_object_coords_recalc(eo_obj, obj);
448 if (!obj->layer->evas->is_frozen && !pass && !freeze && obj->cur->visible)
449 _evas_canvas_event_pointer_in_list_mouse_move_feed(obj->layer->evas, was, eo_obj, obj, 1, 1, EINA_TRUE, NULL);
450 eina_list_free(was);
451 evas_object_inform_call_resize(eo_obj, obj);
452 }
453
454 EOLIAN static void
_evas_text_efl_text_font_font_family_set(Eo * eo_obj,Evas_Text_Data * o,const char * font)455 _evas_text_efl_text_font_font_family_set(Eo *eo_obj, Evas_Text_Data *o, const char *font)
456 {
457 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
458 Evas_Font_Description *fdesc;
459
460 EINA_SAFETY_ON_NULL_RETURN(font);
461
462 evas_object_async_block(obj);
463 if (eina_streq(font, o->cur.font)) return;
464
465 /* We can't assume the given font is same with current fdesc by comparing string.
466 Since Evas starts to supporting "auto" for language,
467 the given font string should be parsed once before comparing it. */
468 fdesc = evas_font_desc_new();
469
470 /* Set default language according to locale. */
471 eina_stringshare_replace(&(fdesc->lang), evas_font_lang_normalize("auto"));
472 evas_font_name_parse(fdesc, font);
473
474 if (o->cur.fdesc && !evas_font_desc_cmp(fdesc, o->cur.fdesc))
475 {
476 evas_font_desc_unref(fdesc);
477 return;
478 }
479
480 if (o->cur.fdesc) evas_font_desc_unref(o->cur.fdesc);
481 o->cur.fdesc = fdesc;
482 eina_stringshare_replace(&o->cur.font, font);
483 o->prev.font = NULL;
484
485 _evas_text_font_reload(eo_obj, o);
486 }
487
488 EOLIAN static const char *
_evas_text_efl_text_font_font_family_get(const Eo * eo_obj EINA_UNUSED,Evas_Text_Data * o)489 _evas_text_efl_text_font_font_family_get(const Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o)
490 {
491 return o->cur.font;
492 }
493
494 EOLIAN static void
_evas_text_efl_text_font_font_size_set(Eo * eo_obj,Evas_Text_Data * o,Evas_Font_Size size)495 _evas_text_efl_text_font_font_size_set(Eo *eo_obj, Evas_Text_Data *o, Evas_Font_Size size)
496 {
497 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
498
499 EINA_SAFETY_ON_TRUE_RETURN(size <= 0);
500 if (size == o->cur.size) return;
501
502 evas_object_async_block(obj);
503
504 o->cur.size = size;
505
506 _evas_text_font_reload(eo_obj, o);
507 }
508
509 EOLIAN static Evas_Font_Size
_evas_text_efl_text_font_font_size_get(const Eo * eo_obj EINA_UNUSED,Evas_Text_Data * o)510 _evas_text_efl_text_font_font_size_get(const Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o)
511 {
512 return o->cur.size;
513 }
514
515 static void
_evas_object_text_item_update_sizes(Evas_Object_Protected_Data * obj,Evas_Text_Data * o,Evas_Object_Text_Item * it)516 _evas_object_text_item_update_sizes(Evas_Object_Protected_Data *obj, Evas_Text_Data *o, Evas_Object_Text_Item *it)
517 {
518 ENFN->font_string_size_get(ENC,
519 o->font,
520 &it->text_props,
521 &it->w, &it->h);
522 it->adv = ENFN->font_h_advance_get(ENC, o->font,
523 &it->text_props);
524 }
525
526 /**
527 * @internal
528 * Create a new text layout item from the string and the format.
529 *
530 * @param c the context to work on - Not NULL.
531 * @param fmt the format to use.
532 * @param str the string to use.
533 */
534 static Evas_Object_Text_Item *
_evas_object_text_item_new(Evas_Object_Protected_Data * obj,Evas_Text_Data * o,Evas_Font_Instance * fi,const Eina_Unicode * str,Evas_Script_Type script,size_t pos,size_t visual_pos,size_t len)535 _evas_object_text_item_new(Evas_Object_Protected_Data *obj,
536 Evas_Text_Data *o,
537 Evas_Font_Instance *fi, const Eina_Unicode *str,
538 Evas_Script_Type script,
539 size_t pos, size_t visual_pos, size_t len)
540 {
541 Evas_Object_Text_Item *it;
542
543 it = calloc(1, sizeof(Evas_Object_Text_Item));
544 it->text_pos = pos;
545 it->visual_pos = visual_pos;
546 evas_common_text_props_bidi_set(&it->text_props, o->bidi_par_props,
547 it->text_pos);
548 evas_common_text_props_script_set(&it->text_props, script);
549
550 if (fi)
551 {
552 ENFN->font_text_props_info_create(ENC,
553 fi, str + pos, &it->text_props,
554 o->bidi_par_props, it->text_pos, len, EVAS_TEXT_PROPS_MODE_SHAPE,
555 o->cur.fdesc->lang);
556 _evas_object_text_item_update_sizes(obj, o, it);
557 }
558 o->items = (Evas_Object_Text_Item *)
559 eina_inlist_append(EINA_INLIST_GET(o->items), EINA_INLIST_GET(it));
560 return it;
561 }
562
563 /**
564 * @internal
565 * Orders o->items according to the visual position.
566 *
567 * @param obj the evas object
568 * @param o the text object
569 */
570 static void
_evas_object_text_item_order(Evas_Object * eo_obj,Evas_Text_Data * o)571 _evas_object_text_item_order(Evas_Object *eo_obj, Evas_Text_Data *o)
572 {
573 (void) eo_obj;
574 #ifdef BIDI_SUPPORT
575 /* Reorder if it's a bidi text */
576 if (o->bidi_par_props)
577 {
578 Evas_Object_Text_Item *i, *j, *min;
579 i = o->items;
580 while (i)
581 {
582 min = i;
583 EINA_INLIST_FOREACH(i, j)
584 {
585 if (j->visual_pos < min->visual_pos)
586 {
587 min = j;
588 }
589 }
590 if (min != i)
591 {
592 o->items = (Evas_Object_Text_Item *) eina_inlist_remove(EINA_INLIST_GET(o->items), EINA_INLIST_GET(min));
593 o->items = (Evas_Object_Text_Item *) eina_inlist_prepend_relative(EINA_INLIST_GET(o->items), EINA_INLIST_GET(min), EINA_INLIST_GET(i));
594 }
595
596 i = (Evas_Object_Text_Item *) EINA_INLIST_GET(min)->next;
597 }
598 }
599 #endif
600
601 /* calculate the positions according to the order. */
602 {
603 Evas_Object_Text_Item *it = o->items;
604 Evas_Coord x = 0;
605
606 while (it)
607 {
608 it->x = x;
609 x += it->adv;
610 it = (Evas_Object_Text_Item *) EINA_INLIST_GET(it)->next;
611 }
612 }
613 }
614
615 /**
616 * Create ellipsis.
617 */
618 static const Eina_Unicode _ellip_str[2] = { 0x2026, '\0' };
619
620 /* FIXME: We currently leak ellipsis items. */
621 static Evas_Object_Text_Item *
_layout_ellipsis_item_new(Evas_Object_Protected_Data * obj,Evas_Text_Data * o)622 _layout_ellipsis_item_new(Evas_Object_Protected_Data *obj, Evas_Text_Data *o)
623 {
624 Evas_Object_Text_Item *ellip_ti = NULL;
625 Evas_Script_Type script;
626 Evas_Font_Instance *script_fi = NULL, *cur_fi = NULL;
627 size_t len = 1; /* The length of _ellip_str */
628
629 script = evas_common_language_script_type_get(_ellip_str, 1);
630
631 if (o->font)
632 {
633 (void) ENFN->font_run_end_get(ENC, o->font, &script_fi, &cur_fi,
634 script, _ellip_str, 1);
635 ellip_ti = _evas_object_text_item_new(obj, o, cur_fi,
636 _ellip_str, script, 0, 0, len);
637 }
638
639 return ellip_ti;
640 }
641
642 /* EINA_TRUE if this item is ok and should be included, false if should be
643 * discarded. */
644 static Eina_Bool
_layout_text_item_trim(Evas_Object_Protected_Data * obj,Evas_Text_Data * o,Evas_Object_Text_Item * ti,int idx,Eina_Bool want_start)645 _layout_text_item_trim(Evas_Object_Protected_Data *obj, Evas_Text_Data *o, Evas_Object_Text_Item *ti, int idx, Eina_Bool want_start)
646 {
647 Evas_Text_Props new_text_props;
648 if (idx >= (int) ti->text_props.text_len)
649 return EINA_FALSE;
650
651 memset(&new_text_props, 0, sizeof (new_text_props));
652
653 while (!evas_common_text_props_split(&ti->text_props, &new_text_props, idx))
654 idx--;
655 if (want_start)
656 {
657 evas_common_text_props_content_unref(&new_text_props);
658 }
659 else
660 {
661 evas_common_text_props_content_unref(&ti->text_props);
662 memcpy(&ti->text_props, &new_text_props, sizeof(ti->text_props));
663 ti->text_pos += idx;
664 ti->visual_pos += idx;
665 }
666 _evas_object_text_item_update_sizes(obj, o, ti);
667
668 return EINA_TRUE;
669 }
670
671 static void
_evas_object_text_pad_get(const Eo * eo_obj,Evas_Text_Data * o,int * l,int * r,int * t,int * b)672 _evas_object_text_pad_get(const Eo *eo_obj, Evas_Text_Data *o, int *l, int *r, int *t, int *b)
673 {
674 if (l) *l = 0;
675 if (r) *r = 0;
676 if (t) *t = 0;
677 if (b) *b = 0;
678 if (!o->has_filter)
679 evas_text_style_pad_get(o->cur.style, l, r, t, b);
680 else
681 efl_gfx_filter_padding_get(eo_obj, l, r, t, b);
682 }
683
684 /**
685 * @internal
686 * Populates o->items with the items of the text according to text
687 *
688 * @param obj the evas object
689 * @param o the text object
690 * @param text the text to layout
691 */
692 static void
_evas_object_text_layout(Evas_Object * eo_obj,Evas_Text_Data * o,Eina_Unicode * text)693 _evas_object_text_layout(Evas_Object *eo_obj, Evas_Text_Data *o, Eina_Unicode *text)
694 {
695 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
696 EvasBiDiStrIndex *v_to_l = NULL;
697 Evas_Coord advance = 0, width = 0;
698 size_t pos, visual_pos;
699 int len = eina_unicode_strlen(text);
700 int l = 0, r = 0;
701 #ifdef BIDI_SUPPORT
702 int par_len = len;
703 int *segment_idxs = NULL;
704 Eina_Bool is_bidi = EINA_FALSE;
705 #endif
706
707 if (o->items &&
708 !memcmp(&o->cur, &o->prev, sizeof (o->cur)) &&
709 o->cur.text == text &&
710 (EINA_DBL_EQ(obj->cur->scale, obj->prev->scale)) &&
711 ((o->last_computed.advance <= obj->cur->geometry.w && !o->last_computed.ellipsis) ||
712 (o->last_computed.w == obj->cur->geometry.w)) &&
713 !o->changed_paragraph_direction)
714 return;
715
716 o->last_computed.ellipsis = EINA_FALSE;
717 evas_object_content_change(eo_obj, obj);
718
719 if (o->items) _evas_object_text_items_clean(obj, o);
720
721 if (text && *text)
722 o->bidi_dir = EVAS_BIDI_DIRECTION_LTR;
723 else
724 o->bidi_dir = EVAS_BIDI_DIRECTION_NEUTRAL;
725
726 #ifdef BIDI_SUPPORT
727 if (text)
728 {
729 if (o->bidi_delimiters)
730 segment_idxs = evas_bidi_segment_idxs_get(text, o->bidi_delimiters);
731 }
732 evas_bidi_paragraph_props_unref(o->bidi_par_props);
733 if (text)
734 {
735 Evas_BiDi_Direction par_dir;
736 EvasBiDiParType bidi_par_type;
737
738 par_dir = o->paragraph_direction;
739
740 switch (par_dir)
741 {
742 case EVAS_BIDI_DIRECTION_LTR:
743 bidi_par_type = EVAS_BIDI_PARAGRAPH_LTR;
744 break;
745 case EVAS_BIDI_DIRECTION_RTL:
746 bidi_par_type = EVAS_BIDI_PARAGRAPH_RTL;
747 break;
748 case EVAS_BIDI_DIRECTION_NEUTRAL:
749 default:
750 bidi_par_type = EVAS_BIDI_PARAGRAPH_NEUTRAL;
751 break;
752 }
753
754 o->bidi_par_props = evas_bidi_paragraph_props_get(text, len, segment_idxs, bidi_par_type);
755 is_bidi = !!o->bidi_par_props;
756 }
757
758 if (o->bidi_par_props)
759 o->bidi_dir = EVAS_BIDI_PAR_TYPE_TO_DIRECTION(o->bidi_par_props->direction);
760
761 evas_bidi_props_reorder_line(NULL, 0, len, o->bidi_par_props, &v_to_l);
762 if (segment_idxs) free(segment_idxs);
763 #endif
764 visual_pos = pos = 0;
765
766 if (text)
767 {
768 const Evas_Object_Text_Item *last_it = NULL;
769 #ifdef BIDI_SUPPORT
770 size_t max_vpos = 0;
771 #endif
772
773 while (len > 0)
774 {
775 Evas_Font_Instance *script_fi = NULL;
776 int script_len = len, tmp_cut;
777 Evas_Script_Type script;
778 tmp_cut = evas_common_language_script_end_of_run_get
779 (text + pos,
780 o->bidi_par_props,
781 pos, len);
782 if (tmp_cut > 0) script_len = tmp_cut;
783
784 script = evas_common_language_script_type_get(text + pos, script_len);
785
786 while (script_len > 0)
787 {
788 const Evas_Object_Text_Item *it;
789 Evas_Font_Instance *cur_fi = NULL;
790 int run_len = script_len;
791 if (o->font)
792 {
793 run_len = ENFN->font_run_end_get
794 (ENC, o->font, &script_fi, &cur_fi,
795 script, text + pos, script_len);
796 }
797 #ifdef BIDI_SUPPORT
798 visual_pos = evas_bidi_position_logical_to_visual
799 (v_to_l, par_len, pos);
800 #else
801 visual_pos = pos;
802 #endif
803 it = _evas_object_text_item_new(obj, o, cur_fi, text, script,
804 pos, visual_pos, run_len);
805
806 advance += it->adv;
807 pos += run_len;
808 script_len -= run_len;
809 len -= run_len;
810
811 if (it->w > 0)
812 {
813 #ifdef BIDI_SUPPORT
814 if (is_bidi)
815 {
816 if (!last_it || (visual_pos >= max_vpos))
817 {
818 last_it = it;
819 max_vpos = visual_pos;
820 }
821 }
822 else
823 #endif
824 {
825 last_it = it;
826 }
827 }
828 }
829 }
830
831 width = advance;
832 if (last_it)
833 width += last_it->w - last_it->adv;
834 }
835 o->last_computed.width_without_ellipsis = width;
836
837 _evas_object_text_pad_get(eo_obj, o, &l, &r, NULL, NULL);
838
839 /* Handle ellipsis */
840 if (pos && (o->cur.ellipsis >= 0.0) && (width + l + r > obj->cur->geometry.w) && (obj->cur->geometry.w > 0))
841 {
842 Evas_Coord ellip_frame = obj->cur->geometry.w;
843 Evas_Object_Text_Item *start_ellip_it = NULL, *end_ellip_it = NULL;
844
845 o->last_computed.ellipsis = EINA_TRUE;
846
847 /* Account of the ellipsis item width. As long as ellipsis != 0
848 * we have a left ellipsis. And the same with 1 and right. */
849 if (!EINA_DBL_EQ(o->cur.ellipsis, 0.0))
850 {
851 if (o->last_computed.ellipsis_start)
852 {
853 start_ellip_it = o->last_computed.ellipsis_start;
854 o->items = (Evas_Object_Text_Item *)
855 eina_inlist_append(EINA_INLIST_GET(o->items), EINA_INLIST_GET(start_ellip_it));
856 }
857 else
858 {
859 start_ellip_it = _layout_ellipsis_item_new(obj, o);
860 }
861 o->last_computed.ellipsis_start = start_ellip_it;
862 ellip_frame -= start_ellip_it->w;
863 }
864 if (!EINA_DBL_EQ(o->cur.ellipsis, 1.0))
865 {
866 /* FIXME: Should take the last item's font and style and etc. *//* weird it's a text, should always have the same style/font */
867 if (o->last_computed.ellipsis_end)
868 {
869 end_ellip_it = o->last_computed.ellipsis_end;
870 o->items = (Evas_Object_Text_Item *)
871 eina_inlist_append(EINA_INLIST_GET(o->items), EINA_INLIST_GET(end_ellip_it));
872 }
873 else
874 {
875 end_ellip_it = _layout_ellipsis_item_new(obj, o);
876 }
877 o->last_computed.ellipsis_end = end_ellip_it;
878 ellip_frame -= end_ellip_it->w;
879 }
880
881 /* The point where we should start from, going for the full
882 * ellip frame. */
883 Evas_Coord ellipsis_coord = o->cur.ellipsis * (width - ellip_frame);
884 if (start_ellip_it)
885 {
886 Evas_Object_Text_Item *itr = o->items;
887 advance = 0;
888
889 while (itr && (advance + l + r + itr->w < ellipsis_coord))
890 {
891 Eina_Inlist *itrn = EINA_INLIST_GET(itr)->next;
892 if ((itr != start_ellip_it) && (itr != end_ellip_it))
893 {
894 advance += itr->adv;
895 _evas_object_text_item_del(o, itr);
896 }
897 itr = (Evas_Object_Text_Item *) itrn;
898 }
899 if (itr && (itr != start_ellip_it))
900 {
901 int cut = ENFN->font_last_up_to_pos(ENC,
902 o->font,
903 &itr->text_props,
904 ellipsis_coord - (advance + l + r),
905 0, start_ellip_it->w);
906 if (cut >= 0)
907 {
908 start_ellip_it->text_pos = itr->text_pos;
909
910 if (itr->text_props.bidi_dir == EVAS_BIDI_DIRECTION_RTL)
911 start_ellip_it->visual_pos = itr->visual_pos + cut + 1;
912 else
913 start_ellip_it->visual_pos = itr->visual_pos;
914
915 if (!_layout_text_item_trim(obj, o, itr, cut + 1, EINA_FALSE))
916 {
917 _evas_object_text_item_del(o, itr);
918 }
919 }
920 }
921
922 if (!o->bidi_par_props)
923 {
924 o->items = (Evas_Object_Text_Item *) eina_inlist_remove(EINA_INLIST_GET(o->items), EINA_INLIST_GET(start_ellip_it));
925 o->items = (Evas_Object_Text_Item *) eina_inlist_prepend(EINA_INLIST_GET(o->items), EINA_INLIST_GET(start_ellip_it));
926 }
927 }
928
929 if (end_ellip_it)
930 {
931 Evas_Object_Text_Item *itr = o->items;
932 advance = 0;
933
934 while (itr)
935 {
936 if (itr != end_ellip_it) /* was start_ellip_it */
937 {
938 if (advance + l + r + itr->w >= ellip_frame)
939 {
940 break;
941 }
942 advance += itr->adv;
943 }
944 itr = (Evas_Object_Text_Item *) EINA_INLIST_GET(itr)->next;
945 }
946
947 if (itr == end_ellip_it)
948 {
949 /* FIXME: We shouldn't do anything. */
950 }
951
952 /* In case when we reach end of itr list, and have NULL */
953 int cut = -1;
954 if (itr && (itr != end_ellip_it))
955 {
956 cut = ENFN->font_last_up_to_pos(ENC,
957 o->font,
958 &itr->text_props,
959 ellip_frame - (advance + l + r),
960 0, end_ellip_it->w);
961 if (cut >= 0)
962 {
963 end_ellip_it->text_pos = itr->text_pos + cut;
964
965 if (itr->text_props.bidi_dir == EVAS_BIDI_DIRECTION_RTL)
966 end_ellip_it->visual_pos = itr->visual_pos - 1;
967 else
968 end_ellip_it->visual_pos = itr->visual_pos + cut;
969
970 if (_layout_text_item_trim(obj, o, itr, cut, EINA_TRUE))
971 {
972 itr = (Evas_Object_Text_Item *) EINA_INLIST_GET(itr)->next;
973 }
974 }
975 }
976
977
978 /* Remove the rest of the items */
979 while (itr)
980 {
981 Eina_Inlist *itrn = EINA_INLIST_GET(itr)->next;
982 if ((itr != start_ellip_it) && (itr != end_ellip_it))
983 {
984 _evas_object_text_item_del(o, itr);
985 }
986 itr = (Evas_Object_Text_Item *) itrn;
987 }
988 }
989 }
990 if (o->cur.text != text) free(o->cur.text);
991 o->cur.text = text;
992 o->prev = o->cur;
993
994 {
995 Evas_Object_Text_Item *itr = o->items;
996 advance = 0;
997
998 while (itr)
999 {
1000 advance += itr->adv;
1001 itr = (Evas_Object_Text_Item *) EINA_INLIST_GET(itr)->next;
1002 }
1003 o->last_computed.advance = advance;
1004 }
1005
1006 _evas_object_text_item_order(eo_obj, o);
1007
1008 if (v_to_l) free(v_to_l);
1009 }
1010
1011 EOLIAN static void
_evas_text_efl_gfx_entity_size_set(Eo * eo_obj,Evas_Text_Data * o,Eina_Size2D sz)1012 _evas_text_efl_gfx_entity_size_set(Eo *eo_obj, Evas_Text_Data *o, Eina_Size2D sz)
1013 {
1014 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1015
1016 if (_evas_object_intercept_call_evas(obj, EVAS_OBJECT_INTERCEPT_CB_RESIZE, 0, sz.w, sz.h))
1017 return;
1018
1019 EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur)
1020 {
1021 state_write->geometry.w = sz.w;
1022 state_write->geometry.h = sz.h;
1023 }
1024 EINA_COW_STATE_WRITE_END(obj, state_write, cur);
1025
1026 _evas_object_text_recalc(eo_obj, o->cur.text);
1027 }
1028
1029 EOLIAN static void
_evas_text_ellipsis_set(Eo * eo_obj,Evas_Text_Data * o,double ellipsis)1030 _evas_text_ellipsis_set(Eo *eo_obj, Evas_Text_Data *o, double ellipsis)
1031 {
1032 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1033
1034 if (EINA_DBL_EQ(o->cur.ellipsis, ellipsis)) return;
1035
1036 evas_object_async_block(obj);
1037 o->prev.ellipsis = o->cur.ellipsis;
1038 o->cur.ellipsis = ellipsis;
1039 o->changed = 1;
1040 if (o->has_filter)
1041 evas_filter_changed_set(eo_obj, EINA_TRUE);
1042 evas_object_change(eo_obj, obj);
1043 evas_object_clip_dirty(eo_obj, obj);
1044 }
1045
1046 EOLIAN static double
_evas_text_ellipsis_get(const Eo * eo_obj EINA_UNUSED,Evas_Text_Data * o)1047 _evas_text_ellipsis_get(const Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o)
1048 {
1049 return o->cur.ellipsis;
1050 }
1051
1052 EOLIAN static void
_evas_text_efl_object_dbg_info_get(Eo * eo_obj,Evas_Text_Data * o EINA_UNUSED,Efl_Dbg_Info * root)1053 _evas_text_efl_object_dbg_info_get(Eo *eo_obj, Evas_Text_Data *o EINA_UNUSED, Efl_Dbg_Info *root)
1054 {
1055 efl_dbg_info_get(efl_super(eo_obj, MY_CLASS), root);
1056 Efl_Dbg_Info *group = EFL_DBG_INFO_LIST_APPEND(root, MY_CLASS_NAME);
1057
1058 const char *text;
1059 int size;
1060 text = efl_text_font_family_get(eo_obj);
1061 size = efl_text_font_size_get(eo_obj);
1062 EFL_DBG_INFO_APPEND(group, "Font", EINA_VALUE_TYPE_STRING, text);
1063 EFL_DBG_INFO_APPEND(group, "Text size", EINA_VALUE_TYPE_INT, size);
1064
1065 text = efl_text_font_source_get(eo_obj);
1066 EFL_DBG_INFO_APPEND(group, "Font source", EINA_VALUE_TYPE_STRING, text);
1067
1068 text = efl_text_get(eo_obj);
1069 EFL_DBG_INFO_APPEND(group, "Text", EINA_VALUE_TYPE_STRING, text);
1070 }
1071
1072 EOLIAN static void
_evas_text_efl_text_text_set(Eo * eo_obj,Evas_Text_Data * o,const char * _text)1073 _evas_text_efl_text_text_set(Eo *eo_obj, Evas_Text_Data *o, const char *_text)
1074 {
1075 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1076 int len;
1077 Eina_Unicode *text;
1078 Eina_List *was = NULL;
1079
1080 if ((o->cur.utf8_text) && (_text) && (!strcmp(o->cur.utf8_text, _text)))
1081 return;
1082 evas_object_async_block(obj);
1083 text = eina_unicode_utf8_to_unicode(_text, &len);
1084
1085 if (!text) text = eina_unicode_strdup(EINA_UNICODE_EMPTY_STRING);
1086 was = _evas_pointer_list_in_rect_get(obj->layer->evas, eo_obj, obj, 1, 1);
1087 /* DO II */
1088 /*Update bidi_props*/
1089
1090 _evas_object_text_items_clear(o);
1091
1092 _evas_object_text_recalc(eo_obj, text);
1093 eina_stringshare_replace(&o->cur.utf8_text, _text);
1094 o->prev.utf8_text = NULL;
1095
1096 if (o->cur.text != text) free(text);
1097
1098 o->changed = 1;
1099 if (o->has_filter)
1100 evas_filter_changed_set(eo_obj, EINA_TRUE);
1101 evas_object_change(eo_obj, obj);
1102 evas_object_clip_dirty(eo_obj, obj);
1103 evas_object_coords_recalc(eo_obj, obj);
1104 if (obj->cur->visible)
1105 _evas_canvas_event_pointer_in_list_mouse_move_feed(obj->layer->evas, was, eo_obj, obj, 1, 1, EINA_FALSE, NULL);
1106 eina_list_free(was);
1107 evas_object_inform_call_resize(eo_obj, obj);
1108 }
1109
1110 EOLIAN static void
_evas_text_bidi_delimiters_set(Eo * eo_obj,Evas_Text_Data * o,const char * delim)1111 _evas_text_bidi_delimiters_set(Eo *eo_obj, Evas_Text_Data *o, const char *delim)
1112 {
1113 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1114 evas_object_async_block(obj);
1115 eina_stringshare_replace(&o->bidi_delimiters, delim);
1116 }
1117
1118 EOLIAN static const char*
_evas_text_bidi_delimiters_get(const Eo * eo_obj EINA_UNUSED,Evas_Text_Data * o)1119 _evas_text_bidi_delimiters_get(const Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o)
1120 {
1121 return o->bidi_delimiters;
1122 }
1123
1124 EOLIAN static const char*
_evas_text_efl_text_text_get(const Eo * eo_obj EINA_UNUSED,Evas_Text_Data * o)1125 _evas_text_efl_text_text_get(const Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o)
1126 {
1127 return o->cur.utf8_text;
1128 }
1129
1130 EOLIAN static Efl_Text_Bidirectional_Type
_evas_text_direction_get(const Eo * eo_obj,Evas_Text_Data * o)1131 _evas_text_direction_get(const Eo *eo_obj, Evas_Text_Data *o)
1132 {
1133 #ifdef BIDI_SUPPORT
1134 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1135
1136 if (o->inherit_paragraph_direction)
1137 {
1138 Evas_BiDi_Direction parent_dir = EVAS_BIDI_DIRECTION_NEUTRAL;
1139
1140 if (obj->smart.parent)
1141 parent_dir = evas_object_paragraph_direction_get(obj->smart.parent);
1142
1143 if (parent_dir != o->paragraph_direction)
1144 {
1145 o->paragraph_direction = parent_dir;
1146 o->changed_paragraph_direction = EINA_TRUE;
1147 }
1148 }
1149
1150 if (o->changed_paragraph_direction)
1151 {
1152 /* XXX const? */
1153 _evas_object_text_recalc((Evas_Object *)eo_obj, o->cur.text);
1154 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes,
1155 (Evas_Object *)eo_obj, obj);
1156 }
1157 #else
1158 (void)eo_obj;
1159 #endif
1160
1161 return (Efl_Text_Bidirectional_Type)o->bidi_dir;
1162 }
1163
1164 EOLIAN static Evas_Coord
_evas_text_ascent_get(const Eo * eo_obj EINA_UNUSED,Evas_Text_Data * o)1165 _evas_text_ascent_get(const Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o)
1166 {
1167 return o->ascent;
1168 }
1169
1170 EOLIAN static Evas_Coord
_evas_text_descent_get(const Eo * eo_obj EINA_UNUSED,Evas_Text_Data * o)1171 _evas_text_descent_get(const Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o)
1172 {
1173 return o->descent;
1174 }
1175
1176 EOLIAN static Evas_Coord
_evas_text_max_ascent_get(const Eo * eo_obj EINA_UNUSED,Evas_Text_Data * o)1177 _evas_text_max_ascent_get(const Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o)
1178 {
1179 return o->max_ascent;
1180 }
1181
1182 EOLIAN static Evas_Coord
_evas_text_max_descent_get(const Eo * eo_obj EINA_UNUSED,Evas_Text_Data * o)1183 _evas_text_max_descent_get(const Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o)
1184 {
1185 return o->max_descent;
1186 }
1187
1188 EOLIAN static Evas_Coord
_evas_text_inset_get(const Eo * eo_obj,Evas_Text_Data * o)1189 _evas_text_inset_get(const Eo *eo_obj, Evas_Text_Data *o)
1190 {
1191 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1192 Evas_Coord inset = 0;
1193 if (!o->font) return inset;
1194 if (!o->items) return inset;
1195 inset = ENFN->font_inset_get(ENC, o->font, &o->items->text_props);
1196
1197 return inset;
1198 }
1199
1200 EOLIAN static Evas_Coord
_evas_text_horiz_advance_get(const Eo * eo_obj EINA_UNUSED,Evas_Text_Data * o)1201 _evas_text_horiz_advance_get(const Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o)
1202 {
1203 Evas_Coord horiz = 0;
1204 if (!o->font) return horiz;
1205 if (!o->items) return horiz;
1206 horiz = _evas_object_text_horiz_advance_get(o);
1207
1208 return horiz;
1209 }
1210
1211 EOLIAN static Evas_Coord
_evas_text_vert_advance_get(const Eo * eo_obj,Evas_Text_Data * o)1212 _evas_text_vert_advance_get(const Eo *eo_obj, Evas_Text_Data *o)
1213 {
1214 Evas_Coord vert;
1215 vert = 0;
1216 if (!o->font) return vert;
1217 if (!o->items)
1218 {
1219 vert = o->max_ascent + o->max_descent;
1220 return vert;
1221 }
1222 vert = _evas_object_text_vert_advance_get(eo_obj, o);
1223
1224 return vert;
1225 }
1226
1227 EOLIAN static Eina_Bool
_evas_text_char_pos_get(const Eo * eo_obj,Evas_Text_Data * o,int pos,Evas_Coord * cx,Evas_Coord * cy,Evas_Coord * cw,Evas_Coord * ch)1228 _evas_text_char_pos_get(const Eo *eo_obj, Evas_Text_Data *o, int pos, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
1229 {
1230 Eina_Bool ret;
1231 ret = EINA_FALSE;
1232
1233 int l = 0, r = 0, t = 0, b = 0;
1234 int x = 0, y = 0, w = 0, h = 0;
1235
1236 if (!o->font) return ret;
1237 if (!o->items || (pos < 0)) return ret;
1238
1239 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1240
1241 Eina_Bool int_ret = _evas_object_text_char_coords_get(eo_obj, o, (size_t) pos,
1242 &x, &y, &w, &h);
1243
1244 _evas_object_text_pad_get(eo_obj, o, &l, &r, &t, &b);
1245 y += o->max_ascent - t;
1246 x -= l;
1247 if (x < 0)
1248 {
1249 w += x;
1250 x = 0;
1251 }
1252 if ((x + w) > obj->cur->geometry.w) w = obj->cur->geometry.w - x;
1253 if (w < 0) w = 0;
1254 if (y < 0)
1255 {
1256 h += y;
1257 y = 0;
1258 }
1259 if ((y + h) > obj->cur->geometry.h) h = obj->cur->geometry.h - y;
1260 if (h < 0) h = 0;
1261 if (cx) *cx = x;
1262 if (cy) *cy = y;
1263 if (cw) *cw = w + l + r;
1264 if (ch) *ch = h + t + b;
1265 ret = int_ret;
1266
1267 return ret;
1268 }
1269
1270 EOLIAN static int
_evas_text_last_up_to_pos(const Eo * eo_obj,Evas_Text_Data * o,Evas_Coord x,Evas_Coord y)1271 _evas_text_last_up_to_pos(const Eo *eo_obj, Evas_Text_Data *o, Evas_Coord x, Evas_Coord y)
1272 {
1273 int ret;
1274 ret = -1;
1275
1276 if (!o->font) return ret;
1277 if (!o->items) return ret;
1278 int int_ret = _evas_object_text_last_up_to_pos(eo_obj, o, x, y - o->max_ascent);
1279 ret = int_ret;
1280
1281 return ret;
1282 }
1283
1284 EOLIAN static int
_evas_text_char_coords_get(const Eo * eo_obj,Evas_Text_Data * o,Evas_Coord x,Evas_Coord y,Evas_Coord * cx,Evas_Coord * cy,Evas_Coord * cw,Evas_Coord * ch)1285 _evas_text_char_coords_get(const Eo *eo_obj, Evas_Text_Data *o, Evas_Coord x, Evas_Coord y, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
1286 {
1287 int ret;
1288 ret = -1;
1289
1290 int l = 0, r = 0, t = 0, b = 0;
1291 int rx = 0, ry = 0, rw = 0, rh = 0;
1292
1293 if (!o->font) return ret;
1294 if (!o->items) return ret;
1295
1296 int int_ret = _evas_object_text_char_at_coords(eo_obj, o, x, y - o->max_ascent,
1297 &rx, &ry, &rw, &rh);
1298 _evas_object_text_pad_get(eo_obj, o, &l, &r, &t, &b);
1299 ry += o->max_ascent - t;
1300 rx -= l;
1301 if (rx < 0)
1302 {
1303 rw += rx;
1304 rx = 0;
1305 }
1306 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1307 if ((rx + rw) > obj->cur->geometry.w) rw = obj->cur->geometry.w - rx;
1308 if (rw < 0) rw = 0;
1309 if (ry < 0)
1310 {
1311 rh += ry;
1312 ry = 0;
1313 }
1314 if ((ry + rh) > obj->cur->geometry.h) rh = obj->cur->geometry.h - ry;
1315 if (rh < 0) rh = 0;
1316 if (cx) *cx = rx;
1317 if (cy) *cy = ry;
1318 if (cw) *cw = rw + l + r;
1319 if (ch) *ch = rh + t + b;
1320 ret = int_ret;
1321
1322 return ret;
1323 }
1324
1325 EOLIAN static void
_evas_text_style_set(Eo * eo_obj,Evas_Text_Data * o,Evas_Text_Style_Type style)1326 _evas_text_style_set(Eo *eo_obj, Evas_Text_Data *o, Evas_Text_Style_Type style)
1327 {
1328 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1329 int pl = 0, pr = 0, pt = 0, pb = 0, l = 0, r = 0, t = 0, b = 0;
1330 int w = 0, h = 0;
1331
1332 if (o->cur.style == style) return;
1333 evas_object_async_block(obj);
1334
1335 _evas_object_text_pad_get(eo_obj, o, &pl, &pr, &pt, &pb);
1336 //evas_text_style_pad_get(o->cur.style, &pl, &pr, &pt, &pb);
1337 o->cur.style = style;
1338 _evas_object_text_pad_get(eo_obj, o, &l, &r, &t, &b);
1339 //evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b);
1340
1341 if (o->items) w = obj->cur->geometry.w + (l - pl) + (r - pr);
1342 h = obj->cur->geometry.h + (t - pt) + (b - pb);
1343
1344 efl_gfx_entity_size_set(efl_super(eo_obj, MY_CLASS), EINA_SIZE2D(w, h));
1345 evas_object_change(eo_obj, obj);
1346 }
1347
1348 EOLIAN static Evas_Text_Style_Type
_evas_text_style_get(const Eo * eo_obj EINA_UNUSED,Evas_Text_Data * o)1349 _evas_text_style_get(const Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o)
1350 {
1351 return o->cur.style;
1352 }
1353
1354 EOLIAN static void
_evas_text_shadow_color_set(Eo * eo_obj,Evas_Text_Data * o,int r,int g,int b,int a)1355 _evas_text_shadow_color_set(Eo *eo_obj, Evas_Text_Data *o, int r, int g, int b, int a)
1356 {
1357 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1358 if ((o->cur.shadow.r == r) && (o->cur.shadow.g == g) &&
1359 (o->cur.shadow.b == b) && (o->cur.shadow.a == a))
1360 return;
1361 evas_object_async_block(obj);
1362 o->cur.shadow.r = r;
1363 o->cur.shadow.g = g;
1364 o->cur.shadow.b = b;
1365 o->cur.shadow.a = a;
1366 o->changed = 1;
1367 evas_object_change(eo_obj, obj);
1368 }
1369
1370 EOLIAN static void
_evas_text_shadow_color_get(const Eo * eo_obj EINA_UNUSED,Evas_Text_Data * o,int * r,int * g,int * b,int * a)1371 _evas_text_shadow_color_get(const Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o, int *r, int *g, int *b, int *a)
1372 {
1373 if (r) *r = o->cur.shadow.r;
1374 if (g) *g = o->cur.shadow.g;
1375 if (b) *b = o->cur.shadow.b;
1376 if (a) *a = o->cur.shadow.a;
1377 }
1378
1379 EOLIAN static void
_evas_text_glow_color_set(Eo * eo_obj,Evas_Text_Data * o,int r,int g,int b,int a)1380 _evas_text_glow_color_set(Eo *eo_obj, Evas_Text_Data *o, int r, int g, int b, int a)
1381 {
1382 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1383 if ((o->cur.glow.r == r) && (o->cur.glow.g == g) &&
1384 (o->cur.glow.b == b) && (o->cur.glow.a == a))
1385 return;
1386 evas_object_async_block(obj);
1387 o->cur.glow.r = r;
1388 o->cur.glow.g = g;
1389 o->cur.glow.b = b;
1390 o->cur.glow.a = a;
1391 o->changed = 1;
1392 evas_object_change(eo_obj, obj);
1393 }
1394
1395 EOLIAN static void
_evas_text_glow_color_get(const Eo * eo_obj EINA_UNUSED,Evas_Text_Data * o,int * r,int * g,int * b,int * a)1396 _evas_text_glow_color_get(const Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o, int *r, int *g, int *b, int *a)
1397 {
1398 if (r) *r = o->cur.glow.r;
1399 if (g) *g = o->cur.glow.g;
1400 if (b) *b = o->cur.glow.b;
1401 if (a) *a = o->cur.glow.a;
1402 }
1403
1404 EOLIAN static void
_evas_text_glow2_color_set(Eo * eo_obj,Evas_Text_Data * o,int r,int g,int b,int a)1405 _evas_text_glow2_color_set(Eo *eo_obj, Evas_Text_Data *o, int r, int g, int b, int a)
1406 {
1407 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1408 if ((o->cur.glow2.r == r) && (o->cur.glow2.g == g) &&
1409 (o->cur.glow2.b == b) && (o->cur.glow2.a == a))
1410 return;
1411 evas_object_async_block(obj);
1412 o->cur.glow2.r = r;
1413 o->cur.glow2.g = g;
1414 o->cur.glow2.b = b;
1415 o->cur.glow2.a = a;
1416 o->changed = 1;
1417 evas_object_change(eo_obj, obj);
1418 }
1419
1420 EOLIAN static void
_evas_text_glow2_color_get(const Eo * eo_obj EINA_UNUSED,Evas_Text_Data * o,int * r,int * g,int * b,int * a)1421 _evas_text_glow2_color_get(const Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o, int *r, int *g, int *b, int *a)
1422 {
1423 if (r) *r = o->cur.glow2.r;
1424 if (g) *g = o->cur.glow2.g;
1425 if (b) *b = o->cur.glow2.b;
1426 if (a) *a = o->cur.glow2.a;
1427 }
1428
1429 EOLIAN static void
_evas_text_outline_color_set(Eo * eo_obj,Evas_Text_Data * o,int r,int g,int b,int a)1430 _evas_text_outline_color_set(Eo *eo_obj, Evas_Text_Data *o, int r, int g, int b, int a)
1431 {
1432 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1433 if ((o->cur.outline.r == r) && (o->cur.outline.g == g) &&
1434 (o->cur.outline.b == b) && (o->cur.outline.a == a))
1435 return;
1436 evas_object_async_block(obj);
1437 o->cur.outline.r = r;
1438 o->cur.outline.g = g;
1439 o->cur.outline.b = b;
1440 o->cur.outline.a = a;
1441 o->changed = 1;
1442 evas_object_change(eo_obj, obj);
1443 }
1444
1445 EOLIAN static void
_evas_text_outline_color_get(const Eo * eo_obj EINA_UNUSED,Evas_Text_Data * o,int * r,int * g,int * b,int * a)1446 _evas_text_outline_color_get(const Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o, int *r, int *g, int *b, int *a)
1447 {
1448 if (r) *r = o->cur.outline.r;
1449 if (g) *g = o->cur.outline.g;
1450 if (b) *b = o->cur.outline.b;
1451 if (a) *a = o->cur.outline.a;
1452 }
1453
1454 EOLIAN static void
_evas_text_style_pad_get(const Eo * eo_obj,Evas_Text_Data * o,int * l,int * r,int * t,int * b)1455 _evas_text_style_pad_get(const Eo *eo_obj, Evas_Text_Data *o, int *l, int *r, int *t, int *b)
1456 {
1457 _evas_object_text_pad_get(eo_obj, o, l, r, t, b);
1458 }
1459
1460 EAPI int
evas_string_char_next_get(const char * str,int pos,int * decoded)1461 evas_string_char_next_get(const char *str, int pos, int *decoded)
1462 {
1463 int p, d;
1464
1465 if ((!str) || (pos < 0))
1466 {
1467 if (decoded) *decoded = 0;
1468 return 0;
1469 }
1470 p = pos;
1471 d = eina_unicode_utf8_next_get(str, &p);
1472 if (decoded) *decoded = d;
1473 return p;
1474 }
1475
1476 EAPI int
evas_string_char_prev_get(const char * str,int pos,int * decoded)1477 evas_string_char_prev_get(const char *str, int pos, int *decoded)
1478 {
1479 int p, d;
1480
1481 if (decoded) *decoded = 0;
1482 if ((!str) || (pos < 1)) return 0;
1483 p = pos;
1484 d = eina_unicode_utf8_get_prev(str, &p);
1485 if (decoded) *decoded = d;
1486 return p;
1487 }
1488
1489 EAPI int
evas_string_char_len_get(const char * str)1490 evas_string_char_len_get(const char *str)
1491 {
1492 if (!str) return 0;
1493 return eina_unicode_utf8_get_len(str);
1494 }
1495
1496 void
evas_text_style_pad_get(Evas_Text_Style_Type style,int * l,int * r,int * t,int * b)1497 evas_text_style_pad_get(Evas_Text_Style_Type style, int *l, int *r, int *t, int *b)
1498 {
1499 int sl = 0, sr = 0, st = 0, sb = 0;
1500
1501 /* Don't calc anything if there's no style. */
1502 if (style != EVAS_TEXT_STYLE_PLAIN)
1503 {
1504 int shad_sz = 0, shad_dst = 0, out_sz = 0;
1505 int dx = 0, minx = 0, maxx = 0;
1506 int dy = 0, miny = 0, maxy = 0;
1507 Eina_Bool have_shadow = EINA_FALSE;
1508
1509 switch (style & EVAS_TEXT_STYLE_MASK_BASIC)
1510 {
1511 case EVAS_TEXT_STYLE_SHADOW:
1512 shad_dst = 1;
1513 have_shadow = EINA_TRUE;
1514 break;
1515 case EVAS_TEXT_STYLE_OUTLINE_SHADOW:
1516 case EVAS_TEXT_STYLE_FAR_SHADOW:
1517 shad_dst = 2;
1518 out_sz = 1;
1519 have_shadow = EINA_TRUE;
1520 break;
1521 case EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW:
1522 shad_dst = 1;
1523 shad_sz = 2;
1524 out_sz = 1;
1525 have_shadow = EINA_TRUE;
1526 break;
1527 case EVAS_TEXT_STYLE_FAR_SOFT_SHADOW:
1528 shad_dst = 2;
1529 shad_sz = 2;
1530 have_shadow = EINA_TRUE;
1531 break;
1532 case EVAS_TEXT_STYLE_SOFT_SHADOW:
1533 shad_dst = 1;
1534 shad_sz = 2;
1535 have_shadow = EINA_TRUE;
1536 break;
1537 case EVAS_TEXT_STYLE_GLOW:
1538 case EVAS_TEXT_STYLE_SOFT_OUTLINE:
1539 out_sz = 2;
1540 break;
1541 case EVAS_TEXT_STYLE_OUTLINE:
1542 out_sz = 1;
1543 break;
1544 default:
1545 break;
1546 }
1547
1548 minx = -out_sz;
1549 maxx = out_sz;
1550 miny = -out_sz;
1551 maxy = out_sz;
1552 if (have_shadow)
1553 {
1554 int shx1, shx2, shy1, shy2;
1555 switch (style & EVAS_TEXT_STYLE_MASK_SHADOW_DIRECTION)
1556 {
1557 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM_RIGHT:
1558 dx = 1;
1559 dy = 1;
1560 break;
1561 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM:
1562 dx = 0;
1563 dy = 1;
1564 break;
1565 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM_LEFT:
1566 dx = -1;
1567 dy = 1;
1568 break;
1569 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_LEFT:
1570 dx = -1;
1571 dy = 0;
1572 break;
1573 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP_LEFT:
1574 dx = -1;
1575 dy = -1;
1576 break;
1577 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP:
1578 dx = 0;
1579 dy = -1;
1580 break;
1581 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP_RIGHT:
1582 dx = 1;
1583 dy = -1;
1584 break;
1585 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_RIGHT:
1586 dx = 1;
1587 dy = 0;
1588 default:
1589 break;
1590 }
1591 shx1 = dx * shad_dst;
1592 shx1 -= shad_sz;
1593 shx2 = dx * shad_dst;
1594 shx2 += shad_sz;
1595 if (shx1 < minx) minx = shx1;
1596 if (shx2 > maxx) maxx = shx2;
1597
1598 shy1 = dy * shad_dst;
1599 shy1 -= shad_sz;
1600 shy2 = dy * shad_dst;
1601 shy2 += shad_sz;
1602 if (shy1 < miny) miny = shy1;
1603 if (shy2 > maxy) maxy = shy2;
1604 }
1605
1606 if (l) sl = *l;
1607 if (r) sr = *r;
1608 if (t) st = *t;
1609 if (b) sb = *b;
1610
1611 if (sr < maxx) sr = maxx;
1612 if (sl < -minx) sl = -minx;
1613 if (sb < maxy) sb = maxy;
1614 if (st < -miny) st = -miny;
1615 }
1616
1617 if (l) *l = sl;
1618 if (r) *r = sr;
1619 if (t) *t = st;
1620 if (b) *b = sb;
1621 }
1622
1623 /* all nice and private */
1624 static void
evas_object_text_init(Evas_Object * eo_obj)1625 evas_object_text_init(Evas_Object *eo_obj)
1626 {
1627 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1628 /* set up methods (compulsory) */
1629 obj->func = &object_func;
1630 obj->private_data = efl_data_ref(eo_obj, MY_CLASS);
1631 obj->type = o_type;
1632
1633 Evas_Text_Data *o = obj->private_data;
1634 /* alloc obj private data */
1635 o->prev.ellipsis = o->cur.ellipsis = -1.0;
1636 o->prev.bitmap_scalable = o->cur.bitmap_scalable = EFL_TEXT_FONT_BITMAP_SCALABLE_COLOR;
1637 o->prev = o->cur;
1638 #ifdef BIDI_SUPPORT
1639 o->bidi_par_props = evas_bidi_paragraph_props_new();
1640 o->inherit_paragraph_direction = EINA_TRUE;
1641 #endif
1642 }
1643
1644 EOLIAN static void
_evas_text_efl_object_destructor(Eo * eo_obj,Evas_Text_Data * o EINA_UNUSED)1645 _evas_text_efl_object_destructor(Eo *eo_obj, Evas_Text_Data *o EINA_UNUSED)
1646 {
1647 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1648 evas_object_text_free(eo_obj, obj);
1649 efl_destructor(efl_super(eo_obj, MY_CLASS));
1650 }
1651
1652 static void
evas_object_text_free(Evas_Object * eo_obj,Evas_Object_Protected_Data * obj)1653 evas_object_text_free(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj)
1654 {
1655 Evas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
1656
1657 /* free obj */
1658 _evas_object_text_items_clear(o);
1659 if (o->cur.utf8_text) eina_stringshare_del(o->cur.utf8_text);
1660 if (o->cur.font) eina_stringshare_del(o->cur.font);
1661 if (o->cur.fdesc) evas_font_desc_unref(o->cur.fdesc);
1662 if (o->cur.source) eina_stringshare_del(o->cur.source);
1663 if (o->bidi_delimiters) eina_stringshare_del(o->bidi_delimiters);
1664 if (o->cur.text) free(o->cur.text);
1665 if (obj->layer && obj->layer->evas)
1666 evas_font_free(o->font);
1667 o->font = NULL;
1668 o->cur.utf8_text = NULL;
1669 o->cur.font = NULL;
1670 o->cur.fdesc = NULL;
1671 o->cur.source = NULL;
1672 o->bidi_delimiters = NULL;
1673 o->cur.text = NULL;
1674 o->prev = o->cur;
1675 #ifdef BIDI_SUPPORT
1676 evas_bidi_paragraph_props_unref(o->bidi_par_props);
1677 o->bidi_par_props = NULL;
1678 #endif
1679 }
1680
1681 void
evas_font_draw_async_check(Evas_Object_Protected_Data * obj,void * engine,void * data,void * context,void * surface,Evas_Font_Set * font,int x,int y,int w,int h,int ow,int oh,Evas_Text_Props * intl_props,Eina_Bool do_async)1682 evas_font_draw_async_check(Evas_Object_Protected_Data *obj,
1683 void *engine, void *data, void *context, void *surface,
1684 Evas_Font_Set *font,
1685 int x, int y, int w, int h, int ow, int oh,
1686 Evas_Text_Props *intl_props, Eina_Bool do_async)
1687 {
1688 Eina_Bool async_unref;
1689
1690 async_unref = obj->layer->evas->engine.func->font_draw(engine, data, context, surface,
1691 font, x, y, w, h, ow, oh,
1692 intl_props, do_async);
1693 if (do_async && async_unref)
1694 {
1695 evas_common_font_glyphs_ref(intl_props->glyphs);
1696 evas_unref_queue_glyph_put(obj->layer->evas, intl_props->glyphs);
1697 }
1698 }
1699
1700 /* ugly binding between evas_fitler_mixin.c and this object */
1701
1702 EOLIAN static void
_evas_text_efl_canvas_filter_internal_filter_dirty(Eo * eo_obj,Evas_Text_Data * o)1703 _evas_text_efl_canvas_filter_internal_filter_dirty(Eo *eo_obj, Evas_Text_Data *o)
1704 {
1705 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1706
1707 _evas_object_text_items_clear(o);
1708 o->changed = 1;
1709 evas_object_change(eo_obj, obj);
1710 _evas_object_text_recalc(eo_obj, o->cur.text);
1711 }
1712
1713 EOLIAN static Eina_Bool
_evas_text_efl_canvas_filter_internal_filter_input_alpha(Eo * eo_obj EINA_UNUSED,Evas_Text_Data * o EINA_UNUSED)1714 _evas_text_efl_canvas_filter_internal_filter_input_alpha(Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o EINA_UNUSED)
1715 {
1716 return EINA_TRUE;
1717 }
1718
1719 EOLIAN static void
_evas_text_efl_canvas_filter_internal_filter_state_prepare(Eo * eo_obj,Evas_Text_Data * o,Efl_Canvas_Filter_State * state,void * data EINA_UNUSED)1720 _evas_text_efl_canvas_filter_internal_filter_state_prepare(Eo *eo_obj, Evas_Text_Data *o,
1721 Efl_Canvas_Filter_State *state, void *data EINA_UNUSED)
1722 {
1723 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1724
1725 #define STATE_COLOR(dst, src) dst.r = src.r; dst.g = src.g; dst.b = src.b; dst.a = src.a
1726 STATE_COLOR(state->color, obj->cur->color);
1727 STATE_COLOR(state->text.glow, o->cur.glow);
1728 STATE_COLOR(state->text.glow2, o->cur.glow2);
1729 STATE_COLOR(state->text.shadow, o->cur.shadow);
1730 STATE_COLOR(state->text.outline, o->cur.outline);
1731 #undef STATE_COLOR
1732
1733 state->w = obj->cur->geometry.w;
1734 state->h = obj->cur->geometry.h;
1735 state->scale = obj->cur->scale;
1736 }
1737
1738 EOLIAN static Eina_Bool
_evas_text_efl_canvas_filter_internal_filter_input_render(Eo * eo_obj EINA_UNUSED,Evas_Text_Data * o,void * _filter,void * engine,void * output,void * drawctx,void * draw EINA_UNUSED,int l,int r EINA_UNUSED,int t,int b EINA_UNUSED,int x,int y,Eina_Bool do_async)1739 _evas_text_efl_canvas_filter_internal_filter_input_render(Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o,
1740 void *_filter, void *engine, void *output, void *drawctx, void *draw EINA_UNUSED,
1741 int l, int r EINA_UNUSED, int t, int b EINA_UNUSED,
1742 int x, int y,
1743 Eina_Bool do_async)
1744 {
1745 Evas_Filter_Context *filter = _filter;
1746 Evas_Object_Text_Item *it;
1747
1748 EINA_INLIST_FOREACH(EINA_INLIST_GET(o->items), it)
1749 if ((o->font) && (it->text_props.len > 0))
1750 {
1751 if (!evas_filter_font_draw(filter, engine, output, drawctx,
1752 EVAS_FILTER_BUFFER_INPUT_ID, o->font,
1753 x + l + it->x,
1754 y + t + (int) o->max_ascent,
1755 &it->text_props,
1756 do_async))
1757 return EINA_FALSE;
1758 }
1759
1760 return EINA_TRUE;
1761 }
1762
1763 static void
evas_object_text_render(Evas_Object * eo_obj,Evas_Object_Protected_Data * obj,void * type_private_data,void * engine,void * output,void * context,void * surface,int x,int y,Eina_Bool do_async)1764 evas_object_text_render(Evas_Object *eo_obj,
1765 Evas_Object_Protected_Data *obj,
1766 void *type_private_data,
1767 void *engine, void *output, void *context, void *surface,
1768 int x, int y, Eina_Bool do_async)
1769 {
1770 int i, j;
1771 Evas_Text_Data *o = type_private_data;
1772 Evas_Object_Text_Item *it;
1773 const char vals[5][5] =
1774 {
1775 {0, 1, 2, 1, 0},
1776 {1, 3, 4, 3, 1},
1777 {2, 4, 5, 4, 2},
1778 {1, 3, 4, 3, 1},
1779 {0, 1, 2, 1, 0}
1780 };
1781 int sl = 0, st = 0;
1782 int shad_dst = 0, shad_sz = 0, dx = 0, dy = 0, haveshad = 0;
1783
1784 /* render object to surface with context, and offxet by x,y */
1785 _evas_object_text_pad_get(eo_obj, o, &sl, NULL, &st, NULL);
1786 ENFN->context_multiplier_unset(engine, context);
1787 ENFN->context_render_op_set(engine, context, obj->cur->render_op);
1788 /* FIXME: This clipping is just until we fix inset handling correctly. */
1789 ENFN->context_clip_clip(engine, context,
1790 obj->cur->geometry.x + x,
1791 obj->cur->geometry.y + y,
1792 obj->cur->geometry.w,
1793 obj->cur->geometry.h);
1794
1795 /*
1796 ENFN->context_color_set(output,
1797 context,
1798 230, 160, 30, 100);
1799 ENFN->rectangle_draw(output,
1800 context,
1801 surface,
1802 obj->cur->geometry.x + x,
1803 obj->cur->geometry.y + y,
1804 obj->cur->geometry.w,
1805 obj->cur->geometry.h);
1806 */
1807 #define COLOR_ONLY_SET(object, sub, col) \
1808 ENFN->context_color_set(engine, context, \
1809 object->sub.col.r, \
1810 object->sub.col.g, \
1811 object->sub.col.b, \
1812 object->sub.col.a);
1813
1814 #define COLOR_SET(object, sub, col) \
1815 if (obj->cur->clipper)\
1816 { \
1817 ENFN->context_color_set(engine, context, \
1818 ((int)object->sub.col.r * ((int)obj->cur->clipper->cur->cache.clip.r + 1)) >> 8, \
1819 ((int)object->sub.col.g * ((int)obj->cur->clipper->cur->cache.clip.g + 1)) >> 8, \
1820 ((int)object->sub.col.b * ((int)obj->cur->clipper->cur->cache.clip.b + 1)) >> 8, \
1821 ((int)object->sub.col.a * ((int)obj->cur->clipper->cur->cache.clip.a + 1)) >> 8); \
1822 } \
1823 else\
1824 ENFN->context_color_set(engine, context, \
1825 object->sub.col.r, \
1826 object->sub.col.g, \
1827 object->sub.col.b, \
1828 object->sub.col.a);
1829
1830 #define COLOR_SET_AMUL(object, sub, col, amul) \
1831 if (obj->cur->clipper) \
1832 { \
1833 ENFN->context_color_set(engine, context, \
1834 (((int)object->sub.col.r) * ((int)obj->cur->clipper->cur->cache.clip.r) * (amul)) / 65025, \
1835 (((int)object->sub.col.g) * ((int)obj->cur->clipper->cur->cache.clip.g) * (amul)) / 65025, \
1836 (((int)object->sub.col.b) * ((int)obj->cur->clipper->cur->cache.clip.b) * (amul)) / 65025, \
1837 (((int)object->sub.col.a) * ((int)obj->cur->clipper->cur->cache.clip.a) * (amul)) / 65025); \
1838 } \
1839 else \
1840 ENFN->context_color_set(engine, context, \
1841 (((int)object->sub.col.r) * (amul)) / 255, \
1842 (((int)object->sub.col.g) * (amul)) / 255, \
1843 (((int)object->sub.col.b) * (amul)) / 255, \
1844 (((int)object->sub.col.a) * (amul)) / 255);
1845
1846 #define DRAW_TEXT(ox, oy) \
1847 if ((o->font) && (it->text_props.len > 0)) { \
1848 ENFN->context_cutout_target(engine, context, \
1849 obj->cur->geometry.x + x + sl + ox + it->x, \
1850 obj->cur->geometry.y + y + st + oy, \
1851 it->w, it->h); \
1852 evas_font_draw_async_check(obj, engine, \
1853 output, \
1854 context, \
1855 surface, \
1856 o->font, \
1857 obj->cur->geometry.x + x + sl + ox + it->x, \
1858 obj->cur->geometry.y + y + st + oy + \
1859 (int)o->max_ascent, \
1860 obj->cur->geometry.w, \
1861 obj->cur->geometry.h, \
1862 obj->cur->geometry.w, \
1863 obj->cur->geometry.h, \
1864 &it->text_props, \
1865 do_async); \
1866 }
1867
1868 if (o->has_filter)
1869 {
1870 if (evas_filter_object_render(eo_obj, obj,
1871 engine, output, context, surface,
1872 x, y, do_async, EINA_TRUE))
1873 return;
1874 }
1875
1876 /* shadows */
1877 switch (o->cur.style & EVAS_TEXT_STYLE_MASK_BASIC)
1878 {
1879 case EVAS_TEXT_STYLE_SHADOW:
1880 shad_dst = 1;
1881 haveshad = 1;
1882 break;
1883 case EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW:
1884 shad_dst = 1;
1885 shad_sz = 2;
1886 haveshad = 1;
1887 break;
1888 case EVAS_TEXT_STYLE_OUTLINE_SHADOW:
1889 case EVAS_TEXT_STYLE_FAR_SHADOW:
1890 shad_dst = 2;
1891 haveshad = 1;
1892 break;
1893 case EVAS_TEXT_STYLE_FAR_SOFT_SHADOW:
1894 shad_dst = 2;
1895 shad_sz = 2;
1896 haveshad = 1;
1897 break;
1898 case EVAS_TEXT_STYLE_SOFT_SHADOW:
1899 shad_dst = 1;
1900 shad_sz = 2;
1901 haveshad = 1;
1902 break;
1903 default:
1904 break;
1905 }
1906 if (haveshad)
1907 {
1908 if (shad_dst > 0)
1909 {
1910 switch (o->cur.style & EVAS_TEXT_STYLE_MASK_SHADOW_DIRECTION)
1911 {
1912 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM_RIGHT:
1913 dx = 1;
1914 dy = 1;
1915 break;
1916 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM:
1917 dx = 0;
1918 dy = 1;
1919 break;
1920 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM_LEFT:
1921 dx = -1;
1922 dy = 1;
1923 break;
1924 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_LEFT:
1925 dx = -1;
1926 dy = 0;
1927 break;
1928 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP_LEFT:
1929 dx = -1;
1930 dy = -1;
1931 break;
1932 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP:
1933 dx = 0;
1934 dy = -1;
1935 break;
1936 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP_RIGHT:
1937 dx = 1;
1938 dy = -1;
1939 break;
1940 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_RIGHT:
1941 dx = 1;
1942 dy = 0;
1943 default:
1944 break;
1945 }
1946 dx *= shad_dst;
1947 dy *= shad_dst;
1948 }
1949 }
1950 EINA_INLIST_FOREACH(EINA_INLIST_GET(o->items), it)
1951 {
1952 ENFN->context_multiplier_set(engine, context, 0, 0, 0, 0);
1953 /* Shadows */
1954 if (haveshad)
1955 {
1956 switch (shad_sz)
1957 {
1958 case 0:
1959 COLOR_SET(o, cur, shadow);
1960 DRAW_TEXT(dx, dy);
1961 break;
1962 case 2:
1963 for (j = 0; j < 5; j++)
1964 {
1965 for (i = 0; i < 5; i++)
1966 {
1967 if (vals[i][j] != 0)
1968 {
1969 COLOR_SET_AMUL(o, cur, shadow, vals[i][j] * 50);
1970 DRAW_TEXT(i - 2 + dx, j - 2 + dy);
1971 }
1972 }
1973 }
1974 break;
1975 default:
1976 break;
1977 }
1978 }
1979
1980 /* glows */
1981 if (o->cur.style == EVAS_TEXT_STYLE_GLOW)
1982 {
1983 for (j = 0; j < 5; j++)
1984 {
1985 for (i = 0; i < 5; i++)
1986 {
1987 if (vals[i][j] != 0)
1988 {
1989 COLOR_SET_AMUL(o, cur, glow, vals[i][j] * 50);
1990 DRAW_TEXT(i - 2, j - 2);
1991 }
1992 }
1993 }
1994 COLOR_SET(o, cur, glow2);
1995 DRAW_TEXT(-1, 0);
1996 DRAW_TEXT(1, 0);
1997 DRAW_TEXT(0, -1);
1998 DRAW_TEXT(0, 1);
1999 }
2000
2001 /* outlines */
2002 if (((o->cur.style & EVAS_TEXT_STYLE_MASK_BASIC) == EVAS_TEXT_STYLE_OUTLINE) ||
2003 ((o->cur.style & EVAS_TEXT_STYLE_MASK_BASIC) == EVAS_TEXT_STYLE_OUTLINE_SHADOW) ||
2004 ((o->cur.style & EVAS_TEXT_STYLE_MASK_BASIC) == EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW))
2005 {
2006 COLOR_SET(o, cur, outline);
2007 DRAW_TEXT(-1, 0);
2008 DRAW_TEXT(1, 0);
2009 DRAW_TEXT(0, -1);
2010 DRAW_TEXT(0, 1);
2011 }
2012 else if (o->cur.style == EVAS_TEXT_STYLE_SOFT_OUTLINE)
2013 {
2014 for (j = 0; j < 5; j++)
2015 {
2016 for (i = 0; i < 5; i++)
2017 {
2018 if (((i != 2) || (j != 2)) && (vals[i][j] != 0))
2019 {
2020 COLOR_SET_AMUL(o, cur, outline, vals[i][j] * 50);
2021 DRAW_TEXT(i - 2, j - 2);
2022 }
2023 }
2024 }
2025 }
2026
2027 /* normal text */
2028 ENFN->context_multiplier_unset(engine, context);
2029
2030 if (obj->cur->clipper)
2031 ENFN->context_multiplier_set(engine, context,
2032 obj->cur->clipper->cur->cache.clip.r,
2033 obj->cur->clipper->cur->cache.clip.g,
2034 obj->cur->clipper->cur->cache.clip.b,
2035 obj->cur->clipper->cur->cache.clip.a);
2036
2037 COLOR_ONLY_SET(obj, cur->cache, clip);
2038 DRAW_TEXT(0, 0);
2039 ENFN->context_multiplier_unset(engine, context);
2040 }
2041 }
2042
2043 static void
evas_object_text_render_pre(Evas_Object * eo_obj,Evas_Object_Protected_Data * obj,void * type_private_data)2044 evas_object_text_render_pre(Evas_Object *eo_obj,
2045 Evas_Object_Protected_Data *obj,
2046 void *type_private_data)
2047 {
2048 Evas_Text_Data *o = type_private_data;
2049 int is_v = 0, was_v = 0;
2050 /* dont pre-render the obj twice! */
2051 if (obj->pre_render_done) return;
2052 obj->pre_render_done = EINA_TRUE;
2053 /* pre-render phase. this does anything an object needs to do just before
2054 rendering. This could mean loading the image data, retrieving it from
2055 elsewhere, decoding video etc.
2056 Then when this is done the object needs to figure if it changed and
2057 if so what and where and add the appropriate redraw rectangles */
2058 /* if someone is clipping this obj - go calculate the clipper */
2059 if (obj->cur->clipper)
2060 {
2061 if (obj->cur->cache.clip.dirty)
2062 {
2063 evas_object_clip_recalc(obj->cur->clipper);
2064 }
2065 obj->cur->clipper->func->render_pre(obj->cur->clipper->object,
2066 obj->cur->clipper,
2067 obj->cur->clipper->private_data);
2068 }
2069
2070 /* If object size changed and ellipsis is set */
2071 if (((o->cur.ellipsis >= 0.0) &&
2072 ((obj->cur->geometry.w != o->last_computed.w) ||
2073 (obj->cur->geometry.h != o->last_computed.h))) ||
2074 (!EINA_DBL_EQ(o->cur.ellipsis, o->prev.ellipsis)) ||
2075 (!EINA_DBL_EQ(obj->cur->scale, obj->prev->scale)) ||
2076 (o->changed_paragraph_direction))
2077 {
2078 _evas_object_text_recalc(eo_obj, o->cur.text);
2079 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes,
2080 eo_obj, obj);
2081 goto done;
2082 }
2083 /* now figure what changed and add draw rects
2084 if it just became visible or invisible */
2085 is_v = evas_object_is_visible(obj);
2086 was_v = evas_object_was_visible(obj);
2087 if (is_v != was_v)
2088 {
2089 evas_object_render_pre_visible_change(&obj->layer->evas->clip_changes,
2090 eo_obj, is_v, was_v);
2091 goto done;
2092 }
2093 if (obj->changed_map || obj->changed_src_visible)
2094 {
2095 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes,
2096 eo_obj, obj);
2097 goto done;
2098 }
2099 /* its not visible - we accounted for it appearing or not so just abort */
2100 if (!is_v) goto done;
2101 /* clipper changed this is in addition to anything else for obj */
2102 evas_object_render_pre_clipper_change(&obj->layer->evas->clip_changes, eo_obj);
2103 /* if we restacked (layer or just within a layer) and dont clip anyone */
2104 if (obj->restack)
2105 {
2106 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes,
2107 eo_obj, obj);
2108 goto done;
2109 }
2110 /* if it changed color */
2111 if ((obj->cur->color.r != obj->prev->color.r) ||
2112 (obj->cur->color.g != obj->prev->color.g) ||
2113 (obj->cur->color.b != obj->prev->color.b) ||
2114 (obj->cur->color.a != obj->prev->color.a))
2115 {
2116 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes,
2117 eo_obj, obj);
2118 goto done;
2119 }
2120 /* if it changed geometry - and obviously not visibility or color
2121 calculate differences since we have a constant color fill
2122 we really only need to update the differences */
2123 if ((obj->cur->geometry.x != obj->prev->geometry.x) ||
2124 (obj->cur->geometry.y != obj->prev->geometry.y) ||
2125 (obj->cur->geometry.w != obj->prev->geometry.w) ||
2126 (obj->cur->geometry.h != obj->prev->geometry.h))
2127 {
2128 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes,
2129 eo_obj, obj);
2130 goto done;
2131 }
2132 if (obj->cur->render_op != obj->prev->render_op)
2133 {
2134 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes,
2135 eo_obj, obj);
2136 goto done;
2137 }
2138 if (o->changed)
2139 {
2140 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes,
2141 eo_obj, obj);
2142 goto done;
2143 }
2144 done:
2145 evas_object_render_pre_effect_updates(&obj->layer->evas->clip_changes,
2146 eo_obj, is_v, was_v);
2147 }
2148
2149 static void
evas_object_text_render_post(Evas_Object * eo_obj EINA_UNUSED,Evas_Object_Protected_Data * obj,void * type_private_data EINA_UNUSED)2150 evas_object_text_render_post(Evas_Object *eo_obj EINA_UNUSED,
2151 Evas_Object_Protected_Data *obj,
2152 void *type_private_data EINA_UNUSED)
2153 {
2154 /* this moves the current data to the previous state parts of the object
2155 in whatever way is safest for the object. also if we don't need object
2156 data anymore we can free it if the object deems this is a good idea */
2157 /* remove those pesky changes */
2158 evas_object_clip_changes_clean(obj);
2159 /* move cur to prev safely for object data */
2160 evas_object_cur_prev(obj);
2161 }
2162
2163 static void *
evas_object_text_engine_data_get(Evas_Object * eo_obj)2164 evas_object_text_engine_data_get(Evas_Object *eo_obj)
2165 {
2166 Evas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
2167 if (!o) return NULL;
2168 return o->font;
2169 }
2170
2171 static int
evas_object_text_is_opaque(Evas_Object * eo_obj EINA_UNUSED,Evas_Object_Protected_Data * obj EINA_UNUSED,void * type_private_data EINA_UNUSED)2172 evas_object_text_is_opaque(Evas_Object *eo_obj EINA_UNUSED,
2173 Evas_Object_Protected_Data *obj EINA_UNUSED,
2174 void *type_private_data EINA_UNUSED)
2175 {
2176 /* this returns 1 if the internal object data implies that the object is
2177 currently fully opaque over the entire gradient it occupies */
2178 return 0;
2179 }
2180
2181 static int
evas_object_text_was_opaque(Evas_Object * eo_obj EINA_UNUSED,Evas_Object_Protected_Data * obj EINA_UNUSED,void * type_private_data EINA_UNUSED)2182 evas_object_text_was_opaque(Evas_Object *eo_obj EINA_UNUSED,
2183 Evas_Object_Protected_Data *obj EINA_UNUSED,
2184 void *type_private_data EINA_UNUSED)
2185 {
2186 /* this returns 1 if the internal object data implies that the object was
2187 currently fully opaque over the entire gradient it occupies */
2188 return 0;
2189 }
2190
2191 EOLIAN static void
_evas_text_efl_gfx_entity_scale_set(Evas_Object * eo_obj,Evas_Text_Data * o,double scale)2192 _evas_text_efl_gfx_entity_scale_set(Evas_Object *eo_obj, Evas_Text_Data *o,
2193 double scale)
2194 {
2195 int size;
2196 const char *font;
2197
2198 if (EINA_DBL_EQ(efl_gfx_entity_scale_get(eo_obj), scale)) return;
2199 efl_gfx_entity_scale_set(efl_super(eo_obj, MY_CLASS), scale);
2200
2201 font = eina_stringshare_add(o->cur.font);
2202 size = o->cur.size;
2203 if (o->cur.font) eina_stringshare_del(o->cur.font);
2204 if (o->cur.fdesc) evas_font_desc_unref(o->cur.fdesc);
2205 o->cur.fdesc = NULL;
2206 o->cur.font = NULL;
2207 o->prev.font = NULL;
2208 o->cur.size = 0;
2209 o->prev.size = 0;
2210 evas_object_text_font_set(eo_obj, font, size);
2211 }
2212
2213 void
_evas_object_text_rehint(Evas_Object * eo_obj)2214 _evas_object_text_rehint(Evas_Object *eo_obj)
2215 {
2216 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
2217 Evas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
2218 Eina_List *was = NULL;
2219
2220 if (!o->font) return;
2221 evas_font_load_hinting_set(o->font, obj->layer->evas->hinting);
2222 was = _evas_pointer_list_in_rect_get(obj->layer->evas, eo_obj, obj, 1, 1);
2223 /* DO II */
2224 _evas_object_text_recalc(eo_obj, o->cur.text);
2225 o->changed = 1;
2226 if (o->has_filter)
2227 evas_filter_changed_set(eo_obj, EINA_TRUE);
2228 evas_object_change(eo_obj, obj);
2229 evas_object_clip_dirty(eo_obj, obj);
2230 evas_object_coords_recalc(eo_obj, obj);
2231 if (obj->cur->visible)
2232 _evas_canvas_event_pointer_in_list_mouse_move_feed(obj->layer->evas, was, eo_obj, obj, 1, 1, EINA_FALSE, NULL);
2233 eina_list_free(was);
2234 evas_object_inform_call_resize(eo_obj, obj);
2235 }
2236
2237 static void
_evas_object_text_recalc(Evas_Object * eo_obj,Eina_Unicode * text)2238 _evas_object_text_recalc(Evas_Object *eo_obj, Eina_Unicode *text)
2239 {
2240 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
2241 Evas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
2242
2243 if (!text) text = eina_unicode_strdup(EINA_UNICODE_EMPTY_STRING);
2244
2245 _evas_object_text_layout(eo_obj, o, text);
2246
2247 /* Calc ascent/descent. */
2248 if (o->items)
2249 {
2250 /*
2251 Evas_Object_Text_Item *item;
2252
2253 for (item = o->items ; item ;
2254 item = EINA_INLIST_CONTAINER_GET(
2255 EINA_INLIST_GET(item)->next, Evas_Object_Text_Item))
2256 {
2257 int asc = 0, desc = 0;
2258
2259 // Skip items without meaning full information.
2260 if (!item->text_props.font_instance) continue;
2261
2262 asc = evas_common_font_instance_ascent_get(item->text_props.font_instance);
2263 desc = evas_common_font_instance_descent_get(item->text_props.font_instance);
2264 if (asc > o->ascent) o->ascent = asc;
2265 if (desc > o->descent) o->descent = desc;
2266
2267 asc = evas_common_font_instance_max_ascent_get(item->text_props.font_instance);
2268 desc = evas_common_font_instance_max_descent_get(item->text_props.font_instance);
2269 if (asc > o->max_ascent) o->max_ascent = asc;
2270 if (desc > o->max_descent) o->max_descent = desc;
2271 }
2272 */
2273 if (o->font)
2274 {
2275 o->ascent = ENFN->font_ascent_get(ENC, o->font);
2276 o->descent = ENFN->font_descent_get(ENC, o->font);
2277 o->max_ascent = ENFN->font_max_ascent_get(ENC, o->font);
2278 o->max_descent = ENFN->font_max_descent_get(ENC, o->font);
2279 }
2280 }
2281 else if (o->font)
2282 {
2283 o->ascent = ENFN->font_ascent_get(ENC, o->font);
2284 o->descent = ENFN->font_descent_get(ENC, o->font);
2285 o->max_ascent = ENFN->font_max_ascent_get(ENC, o->font);
2286 o->max_descent = ENFN->font_max_descent_get(ENC, o->font);
2287 }
2288
2289 if ((o->font) && (o->items))
2290 {
2291 int w, h;
2292 int l = 0, r = 0, t = 0, b = 0;
2293
2294 w = _evas_object_text_horiz_width_without_ellipsis_get(o);
2295 h = _evas_object_text_vert_advance_get(eo_obj, o);
2296 _evas_object_text_pad_get(eo_obj, o, &l, &r, &t, &b);
2297
2298 if (o->cur.ellipsis >= 0.0)
2299 {
2300 int min;
2301
2302 min = w + l + r < obj->cur->geometry.w || obj->cur->geometry.w == 0 ? w + l + r : obj->cur->geometry.w;
2303 efl_gfx_entity_size_set(efl_super(eo_obj, MY_CLASS), EINA_SIZE2D(min, h + t + b));
2304 }
2305 else
2306 {
2307 efl_gfx_entity_size_set(efl_super(eo_obj, MY_CLASS), EINA_SIZE2D(w + l + r, h + t + b));
2308 }
2309 //// obj->cur->cache.geometry.validity = 0;
2310 }
2311 else
2312 {
2313 int t = 0, b = 0, l = 0, r = 0;
2314 _evas_object_text_pad_get(eo_obj, o, &l, &r, &t, &b);
2315 efl_gfx_entity_size_set(efl_super(eo_obj, MY_CLASS), EINA_SIZE2D(0, o->max_ascent + o->max_descent + t + b));
2316 //// obj->cur->cache.geometry.validity = 0;
2317 }
2318 o->last_computed.w = obj->cur->geometry.w;
2319 o->last_computed.h = obj->cur->geometry.h;
2320 #ifdef BIDI_SUPPORT
2321 o->changed_paragraph_direction = EINA_FALSE;
2322 #endif
2323 }
2324
2325 EAPI void
evas_object_text_font_source_set(Eo * obj,const char * font_source)2326 evas_object_text_font_source_set(Eo *obj, const char *font_source)
2327 {
2328 efl_text_font_source_set((Eo *) obj, font_source);
2329 }
2330
2331 EAPI const char *
evas_object_text_font_source_get(const Eo * obj)2332 evas_object_text_font_source_get(const Eo *obj)
2333 {
2334 const char *font_source = 0;
2335 font_source = efl_text_font_source_get((Eo *) obj);
2336 return font_source;
2337 }
2338
2339 EAPI void
evas_object_text_font_set(Eo * obj,const char * font,Evas_Font_Size size)2340 evas_object_text_font_set(Eo *obj, const char *font, Evas_Font_Size size)
2341 {
2342 if (!font || size <= 0) return; /*Condition for legacy object*/
2343
2344 efl_text_font_family_set((Eo *) obj, font);
2345 efl_text_font_size_set((Eo *) obj, size);
2346 }
2347
2348 EAPI void
evas_object_text_font_get(const Eo * obj,const char ** font,Evas_Font_Size * size)2349 evas_object_text_font_get(const Eo *obj, const char **font, Evas_Font_Size *size)
2350 {
2351 if (font) *font = efl_text_font_family_get((Eo *) obj);
2352 if (size) *size = efl_text_font_size_get((Eo *) obj);
2353 }
2354
2355 EAPI void
evas_object_text_text_set(Eo * obj,const char * text)2356 evas_object_text_text_set(Eo *obj, const char *text)
2357 {
2358 efl_text_set((Eo *) obj, text);
2359 }
2360
2361 EAPI const char *
evas_object_text_text_get(const Eo * obj)2362 evas_object_text_text_get(const Eo *obj)
2363 {
2364 return efl_text_get((Eo *) obj);
2365 }
2366
2367 EOLIAN static void
_evas_text_efl_gfx_filter_filter_program_set(Eo * obj,Evas_Text_Data * pd EINA_UNUSED,const char * code,const char * name)2368 _evas_text_efl_gfx_filter_filter_program_set(Eo *obj, Evas_Text_Data *pd EINA_UNUSED, const char *code, const char *name)
2369 {
2370 pd->has_filter = (code != NULL);
2371 efl_gfx_filter_program_set(efl_super(obj, MY_CLASS), code, name);
2372 }
2373
2374 /* deprecated */
2375 EAPI void
evas_object_text_filter_program_set(Evas_Object * obj,const char * code)2376 evas_object_text_filter_program_set(Evas_Object *obj, const char *code)
2377 {
2378 efl_gfx_filter_program_set(obj, code, NULL);
2379 }
2380
2381 /* deprecated */
2382 EAPI void
evas_object_text_filter_source_set(Evas_Object * obj,const char * name,Evas_Object * source)2383 evas_object_text_filter_source_set(Evas_Object *obj, const char *name, Evas_Object *source)
2384 {
2385 efl_gfx_filter_source_set(obj, name, source);
2386 }
2387
2388 EOLIAN static void
_evas_text_efl_canvas_object_paragraph_direction_set(Eo * eo_obj,Evas_Text_Data * o,Efl_Text_Bidirectional_Type dir)2389 _evas_text_efl_canvas_object_paragraph_direction_set(Eo *eo_obj, Evas_Text_Data *o,
2390 Efl_Text_Bidirectional_Type dir)
2391 {
2392 #ifdef BIDI_SUPPORT
2393 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
2394
2395 if ((!(o->inherit_paragraph_direction) && (o->paragraph_direction == (Evas_BiDi_Direction)dir)) ||
2396 (o->inherit_paragraph_direction && ((Evas_BiDi_Direction)dir == EVAS_BIDI_DIRECTION_INHERIT)))
2397 return;
2398
2399 if (dir == (Efl_Text_Bidirectional_Type)EVAS_BIDI_DIRECTION_INHERIT)
2400 {
2401 o->inherit_paragraph_direction = EINA_TRUE;
2402 Evas_BiDi_Direction parent_dir = EVAS_BIDI_DIRECTION_NEUTRAL;
2403
2404 if (obj->smart.parent)
2405 parent_dir = evas_object_paragraph_direction_get(obj->smart.parent);
2406
2407 if (parent_dir != o->paragraph_direction)
2408 {
2409 o->paragraph_direction = parent_dir;
2410 o->changed_paragraph_direction = EINA_TRUE;
2411 evas_object_change(eo_obj, obj);
2412 }
2413 }
2414 else
2415 {
2416 o->inherit_paragraph_direction = EINA_FALSE;
2417 o->paragraph_direction = dir;
2418 o->changed_paragraph_direction = EINA_TRUE;
2419 evas_object_change(eo_obj, obj);
2420 }
2421 #else
2422 (void) eo_obj;
2423 (void) o;
2424 (void) dir;
2425 #endif
2426 }
2427
2428 EOLIAN static Efl_Text_Bidirectional_Type
_evas_text_efl_canvas_object_paragraph_direction_get(const Eo * eo_obj EINA_UNUSED,Evas_Text_Data * o)2429 _evas_text_efl_canvas_object_paragraph_direction_get(const Eo *eo_obj EINA_UNUSED,
2430 Evas_Text_Data *o)
2431 {
2432 return (Efl_Text_Bidirectional_Type)o->paragraph_direction;
2433 }
2434
2435 EOLIAN static void
_evas_text_efl_text_font_font_bitmap_scalable_set(Eo * eo_obj,Evas_Text_Data * o,Efl_Text_Font_Bitmap_Scalable bitmap_scalable)2436 _evas_text_efl_text_font_font_bitmap_scalable_set(Eo *eo_obj, Evas_Text_Data *o, Efl_Text_Font_Bitmap_Scalable bitmap_scalable)
2437 {
2438 if (o->cur.bitmap_scalable == bitmap_scalable) return;
2439 o->prev.bitmap_scalable = o->cur.bitmap_scalable;
2440 o->cur.bitmap_scalable = bitmap_scalable;
2441 _evas_text_font_reload(eo_obj, o);
2442 }
2443
2444 EOLIAN static Efl_Text_Font_Bitmap_Scalable
_evas_text_efl_text_font_font_bitmap_scalable_get(const Eo * eo_obj EINA_UNUSED,Evas_Text_Data * o)2445 _evas_text_efl_text_font_font_bitmap_scalable_get(const Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o)
2446 {
2447 return o->cur.bitmap_scalable;
2448 }
2449
2450 #define EVAS_TEXT_EXTRA_OPS \
2451 EFL_OBJECT_OP_FUNC(efl_dbg_info_get, _evas_text_efl_object_dbg_info_get)
2452
2453 #include "canvas/evas_text_eo.c"
2454