summaryrefslogtreecommitdiff
path: root/src/lib/evas/canvas/evas_object_textblock.c
diff options
context:
space:
mode:
authorDaniel Hirt <hirt.danny@gmail.com>2018-06-05 21:02:37 +0300
committerDaniel Hirt <hirt.danny@gmail.com>2018-11-06 00:54:10 +0200
commite1fc2ea48f14cb56548bfef9b972854ac5957110 (patch)
tree9d03b0e3405dcbc2c544031c30d997579e1f611b /src/lib/evas/canvas/evas_object_textblock.c
parentd50bc7f8855414c0e86058bb0fb39236f302c534 (diff)
Canvas text: share common style strings in style_set
Style strings will now be implicitly handled and shared by the object. Also, some of the code was simplified for better readability. @optimize
Diffstat (limited to 'src/lib/evas/canvas/evas_object_textblock.c')
-rw-r--r--src/lib/evas/canvas/evas_object_textblock.c222
1 files changed, 121 insertions, 101 deletions
diff --git a/src/lib/evas/canvas/evas_object_textblock.c b/src/lib/evas/canvas/evas_object_textblock.c
index fbd2360..e028f31 100644
--- a/src/lib/evas/canvas/evas_object_textblock.c
+++ b/src/lib/evas/canvas/evas_object_textblock.c
@@ -554,12 +554,18 @@ struct _Efl_Canvas_Text_Style
554{ 554{
555 const char *style_text; 555 const char *style_text;
556 char *default_tag; 556 char *default_tag;
557 Eina_Stringshare *key; /* FIXME: Very hacky. */
558 Evas_Object_Style_Tag *tags; 557 Evas_Object_Style_Tag *tags;
559 Eina_List *objects; 558 Eina_List *objects;
560 Eina_Bool delete_me : 1; 559 Eina_Bool delete_me : 1;
560 Eina_Bool legacy : 1;
561}; 561};
562 562
563typedef struct _User_Style_Entry
564{
565 Evas_Textblock_Style *st;
566 const char *key;
567} User_Style_Entry;
568
563struct _Efl_Text_Cursor_Cursor 569struct _Efl_Text_Cursor_Cursor
564{ 570{
565 Evas_Object *obj; 571 Evas_Object *obj;
@@ -662,6 +668,7 @@ struct _Evas_Object_Textblock
662 Eina_Bool changed_paragraph_direction : 1; 668 Eina_Bool changed_paragraph_direction : 1;
663 Eina_Bool multiline : 1; 669 Eina_Bool multiline : 1;
664 Eina_Bool wrap_changed : 1; 670 Eina_Bool wrap_changed : 1;
671 Eina_Bool auto_styles : 1;
665}; 672};
666 673
667struct _Evas_Textblock_Selection_Iterator 674struct _Evas_Textblock_Selection_Iterator
@@ -773,6 +780,8 @@ static void _find_layout_item_line_match(Evas_Object *eo_obj, Evas_Object_Textbl
773static Evas_Object_Textblock_Node_Format *_evas_textblock_cursor_node_format_at_pos_get(const Efl_Text_Cursor_Cursor *cur); 780static Evas_Object_Textblock_Node_Format *_evas_textblock_cursor_node_format_at_pos_get(const Efl_Text_Cursor_Cursor *cur);
774static int _evas_textblock_cursor_text_prepend(Efl_Text_Cursor_Cursor *cur, const char *_text); 781static int _evas_textblock_cursor_text_prepend(Efl_Text_Cursor_Cursor *cur, const char *_text);
775static void _evas_textblock_cursor_copy(Efl_Text_Cursor_Cursor *dst, const Efl_Text_Cursor_Cursor *src); 782static void _evas_textblock_cursor_copy(Efl_Text_Cursor_Cursor *dst, const Efl_Text_Cursor_Cursor *src);
783static void
784_textblock_style_generic_set(Evas_Object *eo_obj, Evas_Textblock_Style *ts, const char *key);
776 785
777/** selection iterator */ 786/** selection iterator */
778/** 787/**
@@ -6658,7 +6667,7 @@ _layout_setup(Ctxt *c, const Eo *eo_obj, Evas_Coord w, Evas_Coord h)
6658 /* setup default base style */ 6667 /* setup default base style */
6659 { 6668 {
6660 Eina_List *itr; 6669 Eina_List *itr;
6661 Evas_Textblock_Style *style; 6670 User_Style_Entry *use;
6662 Eina_Bool finalize = EINA_FALSE; 6671 Eina_Bool finalize = EINA_FALSE;
6663 if (!c->fmt) 6672 if (!c->fmt)
6664 { 6673 {
@@ -6671,11 +6680,11 @@ _layout_setup(Ctxt *c, const Eo *eo_obj, Evas_Coord w, Evas_Coord h)
6671 finalize = EINA_TRUE; 6680 finalize = EINA_TRUE;
6672 } 6681 }
6673 6682
6674 EINA_LIST_FOREACH(c->o->styles, itr, style) 6683 EINA_LIST_FOREACH(c->o->styles, itr, use)
6675 { 6684 {
6676 if ((style) && (style->default_tag)) 6685 if ((use->st) && (use->st->default_tag))
6677 { 6686 {
6678 _format_fill(c->obj, c->fmt, style->default_tag); 6687 _format_fill(c->obj, c->fmt, use->st->default_tag);
6679 finalize = EINA_TRUE; 6688 finalize = EINA_TRUE;
6680 } 6689 }
6681 } 6690 }
@@ -6880,6 +6889,7 @@ evas_object_textblock_add(Evas *e)
6880 efl_canvas_object_legacy_ctor(efl_added)); 6889 efl_canvas_object_legacy_ctor(efl_added));
6881 o = efl_data_scope_get(eo_obj, MY_CLASS); 6890 o = efl_data_scope_get(eo_obj, MY_CLASS);
6882 o->legacy_newline = EINA_TRUE; 6891 o->legacy_newline = EINA_TRUE;
6892 o->auto_styles = EINA_FALSE;
6883 return eo_obj; 6893 return eo_obj;
6884} 6894}
6885 6895
@@ -6920,6 +6930,8 @@ _efl_canvas_text_efl_object_constructor(Eo *eo_obj, Efl_Canvas_Text_Data *class_
6920 _FMT(ellipsis) = -1; 6930 _FMT(ellipsis) = -1;
6921 _FMT_INFO(bitmap_scalable) = EFL_TEXT_FONT_BITMAP_SCALABLE_COLOR; 6931 _FMT_INFO(bitmap_scalable) = EFL_TEXT_FONT_BITMAP_SCALABLE_COLOR;
6922 6932
6933 o->auto_styles = EINA_TRUE;
6934
6923 return eo_obj; 6935 return eo_obj;
6924} 6936}
6925 6937
@@ -6929,6 +6941,7 @@ evas_textblock_style_new(void)
6929 Evas_Textblock_Style *ts; 6941 Evas_Textblock_Style *ts;
6930 6942
6931 ts = calloc(1, sizeof(Evas_Textblock_Style)); 6943 ts = calloc(1, sizeof(Evas_Textblock_Style));
6944 ts->legacy = EINA_TRUE;
6932 return ts; 6945 return ts;
6933} 6946}
6934 6947
@@ -6942,7 +6955,7 @@ evas_textblock_style_free(Evas_Textblock_Style *ts)
6942 return; 6955 return;
6943 } 6956 }
6944 _style_clear(ts); 6957 _style_clear(ts);
6945 eina_stringshare_del(ts->key); 6958 // FIXME: free up user style entry
6946 free(ts); 6959 free(ts);
6947} 6960}
6948 6961
@@ -6994,6 +7007,7 @@ evas_textblock_style_set(Evas_Textblock_Style *ts, const char *text)
6994 Evas_Object *eo_obj; 7007 Evas_Object *eo_obj;
6995 7008
6996 if (!ts) return; 7009 if (!ts) return;
7010
6997 /* If the style wasn't really changed, abort. */ 7011 /* If the style wasn't really changed, abort. */
6998 if ((!ts->style_text && !text) || 7012 if ((!ts->style_text && !text) ||
6999 (ts->style_text && text && !strcmp(text, ts->style_text))) 7013 (ts->style_text && text && !strcmp(text, ts->style_text)))
@@ -7142,11 +7156,11 @@ static const char *
7142_textblock_format_node_from_style_tag(Efl_Canvas_Text_Data *o, Evas_Object_Textblock_Node_Format *fnode, const char *format, size_t format_len) 7156_textblock_format_node_from_style_tag(Efl_Canvas_Text_Data *o, Evas_Object_Textblock_Node_Format *fnode, const char *format, size_t format_len)
7143{ 7157{
7144 Eina_List *itr; 7158 Eina_List *itr;
7145 Evas_Textblock_Style *style;
7146 const char *match = NULL; 7159 const char *match = NULL;
7147 EINA_LIST_REVERSE_FOREACH(o->styles, itr, style) 7160 User_Style_Entry *use;
7161 EINA_LIST_REVERSE_FOREACH(o->styles, itr, use)
7148 { 7162 {
7149 match = _style_match_tag(style, format, format_len); 7163 match = _style_match_tag(use->st, format, format_len);
7150 if (match) 7164 if (match)
7151 break; 7165 break;
7152 } 7166 }
@@ -7172,32 +7186,82 @@ _textblock_format_node_from_style_tag(Efl_Canvas_Text_Data *o, Evas_Object_Textb
7172 7186
7173/* textblock styles */ 7187/* textblock styles */
7174 7188
7189static Eina_List *_style_cache = NULL;
7190
7175static void 7191static void
7176_textblock_style_generic_set(Evas_Object *eo_obj, Evas_Textblock_Style *ts, 7192_textblock_style_generic_set(Evas_Object *eo_obj, Evas_Textblock_Style *ts,
7177 Evas_Textblock_Style **obj_ts) 7193 const char *key)
7178{ 7194{
7179 TB_HEAD(); 7195 TB_HEAD();
7180 if (ts == *obj_ts) return; 7196 Eina_List *itr;
7197 Evas_Textblock_Style *old_ts = NULL;
7198
7199 if (!key)
7200 {
7201 old_ts = o->style;
7202 o->style = ts;
7203 }
7204 else
7205 {
7206 User_Style_Entry *us;
7207
7208 EINA_LIST_FOREACH(o->styles, itr, us)
7209 {
7210 if (!strcmp(us->key, key))
7211 {
7212 //us->st = ts;
7213 break;
7214 }
7215 }
7216 if (ts)
7217 {
7218 if (!us)
7219 {
7220 us = calloc(1, sizeof(*us));
7221 us->key = eina_stringshare_add(key);
7222 o->styles = eina_list_append(o->styles, us);
7223 }
7224
7225 old_ts = us->st;
7226 us->st = ts;
7227 }
7228 else if (us)
7229 {
7230 o->styles = eina_list_remove_list(o->styles, itr);
7231 free(us);
7232 }
7233 }
7234
7235 // Verify nothing has changed
7236 if (ts == old_ts) return;
7237
7181 if ((ts) && (ts->delete_me)) return; 7238 if ((ts) && (ts->delete_me)) return;
7182 if (*obj_ts) 7239
7240 if (old_ts)
7183 { 7241 {
7184 Evas_Textblock_Style *old_ts;
7185 if (o->markup_text) 7242 if (o->markup_text)
7186 { 7243 {
7187 eina_stringshare_del(o->markup_text); 7244 eina_stringshare_del(o->markup_text);
7188 o->markup_text = NULL; 7245 o->markup_text = NULL;
7189 } 7246 }
7190 7247
7191 old_ts = *obj_ts;
7192 old_ts->objects = eina_list_remove(old_ts->objects, eo_obj); 7248 old_ts->objects = eina_list_remove(old_ts->objects, eo_obj);
7193 if ((old_ts->delete_me) && (!old_ts->objects)) 7249 if (o->auto_styles && !old_ts->objects)
7194 evas_textblock_style_free(old_ts); 7250 {
7251 _style_cache = eina_list_remove(_style_cache, old_ts);
7252 evas_textblock_style_free(old_ts);
7253 }
7254 else if (!o->auto_styles && (old_ts->delete_me) && (!old_ts->objects))
7255 {
7256 // Legacy behavior ('delete_me' does not occur in new auto styles)
7257 evas_textblock_style_free(old_ts);
7258 }
7195 } 7259 }
7260
7196 if (ts) 7261 if (ts)
7197 { 7262 {
7198 ts->objects = eina_list_append(ts->objects, eo_obj); 7263 ts->objects = eina_list_append(ts->objects, eo_obj);
7199 } 7264 }
7200 *obj_ts = ts;
7201 7265
7202 _evas_textblock_update_format_nodes_from_style_tag(o); 7266 _evas_textblock_update_format_nodes_from_style_tag(o);
7203 7267
@@ -7212,36 +7276,48 @@ evas_object_textblock_style_set(Eo *eo_obj, const Evas_Textblock_Style *ts)
7212 EINA_SAFETY_ON_NULL_RETURN(eo_obj); 7276 EINA_SAFETY_ON_NULL_RETURN(eo_obj);
7213 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); 7277 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
7214 evas_object_async_block(obj); 7278 evas_object_async_block(obj);
7215 Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS); 7279 _textblock_style_generic_set(eo_obj, (Evas_Textblock_Style *) ts, NULL);
7216 _textblock_style_generic_set(eo_obj, (Evas_Textblock_Style *) ts, &(o->style));
7217} 7280}
7218 7281
7219static Evas_Textblock_Style * 7282static Evas_Textblock_Style *
7220_style_by_key_find(Efl_Canvas_Text_Data *o, const char *key) 7283_style_by_key_find(Efl_Canvas_Text_Data *o, const char *key)
7221{ 7284{
7222 Eina_List *itr; 7285 Eina_List *itr;
7223 Evas_Textblock_Style *style; 7286 User_Style_Entry *us;
7224 7287
7225 if (!key) 7288 if (!key)
7226 return o->style; 7289 return o->style;
7227 7290
7228 EINA_LIST_FOREACH(o->styles, itr, style) 7291 EINA_LIST_FOREACH(o->styles, itr, us)
7229 { 7292 {
7230 if (!strcmp(style->key, key)) 7293 if (!strcmp(us->key, key))
7231 return style; 7294 return us->st;
7232 } 7295 }
7233 7296
7234 return NULL; 7297 return NULL;
7235} 7298}
7236 7299
7237static void 7300static Evas_Textblock_Style *
7238_style_remove_from_obj(Eo *eo_obj, Efl_Canvas_Text_Data *o, Evas_Textblock_Style *ts, Eina_Bool style_free) 7301_style_fetch(const char *style)
7239{ 7302{
7240 o->styles = eina_list_remove(o->styles, ts); 7303 Evas_Textblock_Style *ts = NULL;
7241 ts->objects = eina_list_remove(ts->objects, eo_obj); 7304 Eina_List *i;
7305
7306 if (!style) return NULL;
7307
7308 EINA_LIST_FOREACH(_style_cache, i, ts)
7309 {
7310 if (ts->style_text == style) break;
7311 }
7242 7312
7243 if (style_free || (ts->delete_me && !ts->objects)) 7313 if (!ts)
7244 evas_textblock_style_free(ts); 7314 {
7315 ts = evas_textblock_style_new();
7316 ts->legacy = EINA_FALSE;
7317 evas_textblock_style_set(ts, style);
7318 _style_cache = eina_list_append(_style_cache, ts);
7319 }
7320 return ts;
7245} 7321}
7246 7322
7247EOLIAN static void 7323EOLIAN static void
@@ -7253,52 +7329,9 @@ _efl_canvas_text_style_set(Eo *eo_obj, Efl_Canvas_Text_Data *o, const char *key,
7253 7329
7254 Evas_Textblock_Style *ts; 7330 Evas_Textblock_Style *ts;
7255 7331
7256 ts = _style_by_key_find(o, key); 7332 ts = _style_fetch(style);
7257
7258 if (!ts && !style)
7259 {
7260 return;
7261 }
7262 7333
7263 if (ts && !style) 7334 _textblock_style_generic_set(eo_obj, ts, key);
7264 {
7265 // Delete the style
7266 if (!key)
7267 {
7268 evas_textblock_style_set(ts, "");
7269 }
7270 else
7271 {
7272 _style_remove_from_obj(eo_obj, o, ts, EINA_TRUE);
7273 }
7274 }
7275 else if (!ts && style)
7276 {
7277 Evas_Textblock_Style *tmp = NULL;
7278
7279 // No entry for respective key, so create one.
7280 ts = evas_textblock_style_new();
7281 evas_textblock_style_set(ts, style);
7282 ts->key = eina_stringshare_add(key);
7283
7284 /* If the given key value is NULL, newly created Evas Textblock Style
7285 * has to be assigned to o->style. */
7286 if (ts->key)
7287 o->styles = eina_list_append(o->styles, ts);
7288 else
7289 o->style = ts;
7290
7291 _textblock_style_generic_set(eo_obj, ts, &tmp);
7292 }
7293 else if (ts && style)
7294 {
7295 evas_textblock_style_set(ts, style);
7296 }
7297
7298 o->format_changed = EINA_TRUE;
7299 _evas_textblock_invalidate_all(o);
7300 _evas_textblock_changed(o, eo_obj);
7301 efl_event_callback_call(eo_obj, EFL_CANVAS_TEXT_EVENT_CHANGED, NULL);
7302} 7335}
7303 7336
7304EAPI Evas_Textblock_Style * 7337EAPI Evas_Textblock_Style *
@@ -7329,24 +7362,7 @@ evas_object_textblock_style_user_push(Eo *eo_obj, Evas_Textblock_Style *ts)
7329 Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS); 7362 Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
7330 Evas_Textblock_Style *old_ts, *tmp = NULL; 7363 Evas_Textblock_Style *old_ts, *tmp = NULL;
7331 7364
7332 old_ts = _style_by_key_find(o, _STYLE_USER); 7365 _textblock_style_generic_set(eo_obj, ts, _STYLE_USER);
7333
7334 if (old_ts == ts) return;
7335
7336 if (old_ts)
7337 _style_remove_from_obj(eo_obj, o, old_ts, EINA_FALSE);
7338
7339 if (ts)
7340 {
7341 _textblock_style_generic_set(eo_obj, ts, &tmp);
7342 ts->key = eina_stringshare_add(_STYLE_USER);
7343 o->styles = eina_list_append(o->styles, ts);
7344 }
7345
7346 o->format_changed = EINA_TRUE;
7347 _evas_textblock_invalidate_all(o);
7348 _evas_textblock_changed(o, eo_obj);
7349 efl_event_callback_call(eo_obj, EFL_CANVAS_TEXT_EVENT_CHANGED, NULL);
7350} 7366}
7351 7367
7352EAPI const Evas_Textblock_Style* 7368EAPI const Evas_Textblock_Style*
@@ -7370,15 +7386,7 @@ evas_object_textblock_style_user_pop(Eo *eo_obj)
7370 Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS); 7386 Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
7371 Evas_Textblock_Style *ts = _style_by_key_find(o, _STYLE_USER); 7387 Evas_Textblock_Style *ts = _style_by_key_find(o, _STYLE_USER);
7372 7388
7373 if (ts) 7389 _textblock_style_generic_set(eo_obj, NULL, _STYLE_USER);
7374 {
7375 _style_remove_from_obj(eo_obj, o, ts, EINA_FALSE);
7376
7377 o->format_changed = EINA_TRUE;
7378 _evas_textblock_invalidate_all(o);
7379 _evas_textblock_changed(o, eo_obj);
7380 efl_event_callback_call(eo_obj, EFL_CANVAS_TEXT_EVENT_CHANGED, NULL);
7381 }
7382} 7390}
7383 7391
7384EAPI void 7392EAPI void
@@ -13547,10 +13555,22 @@ evas_object_textblock_free(Evas_Object *eo_obj)
13547 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); 13555 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
13548 Efl_Canvas_Text_Filter_Program *prg; 13556 Efl_Canvas_Text_Filter_Program *prg;
13549 Evas_Filter_Data_Binding *db; 13557 Evas_Filter_Data_Binding *db;
13558 User_Style_Entry *use;
13550 13559
13551 _evas_object_textblock_clear(eo_obj); 13560 _evas_object_textblock_clear(eo_obj);
13552 evas_object_textblock_style_set(eo_obj, NULL); 13561 evas_object_textblock_style_set(eo_obj, NULL);
13553 13562
13563 EINA_LIST_FREE(o->styles, use)
13564 {
13565 Evas_Textblock_Style *ts = use->st;
13566 ts->objects = eina_list_remove(ts->objects, eo_obj);
13567 if (!ts->objects && (ts->delete_me || o->auto_styles))
13568 {
13569 evas_textblock_style_free(ts);
13570 }
13571 free(use);
13572 }
13573
13554 EINA_INLIST_FREE(o->gfx_filter.programs, prg) 13574 EINA_INLIST_FREE(o->gfx_filter.programs, prg)
13555 { 13575 {
13556 EINA_INLIST_REMOVE(o->gfx_filter.programs, prg); 13576 EINA_INLIST_REMOVE(o->gfx_filter.programs, prg);