summaryrefslogtreecommitdiff
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-06-20 14:24:57 +0300
commit151b7616f671edc25f2a88fa1d728ea4ac71964b (patch)
treebd353371eb03fc3cd0d39f0ff16408104f07a843
parentff61edd29912a571bd10bbdc2a69e802dafc2b2b (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
-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 7900b4e2af..89397d2bf6 100644
--- a/src/lib/evas/canvas/evas_object_textblock.c
+++ b/src/lib/evas/canvas/evas_object_textblock.c
@@ -553,12 +553,18 @@ struct _Efl_Canvas_Text_Style
553{ 553{
554 const char *style_text; 554 const char *style_text;
555 char *default_tag; 555 char *default_tag;
556 Eina_Stringshare *key; /* FIXME: Very hacky. */
557 Evas_Object_Style_Tag *tags; 556 Evas_Object_Style_Tag *tags;
558 Eina_List *objects; 557 Eina_List *objects;
559 Eina_Bool delete_me : 1; 558 Eina_Bool delete_me : 1;
559 Eina_Bool legacy : 1;
560}; 560};
561 561
562typedef struct _User_Style_Entry
563{
564 Evas_Textblock_Style *st;
565 const char *key;
566} User_Style_Entry;
567
562struct _Efl_Text_Cursor_Cursor 568struct _Efl_Text_Cursor_Cursor
563{ 569{
564 Evas_Object *obj; 570 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
@@ -780,6 +787,8 @@ static void _find_layout_item_line_match(Evas_Object *eo_obj, Evas_Object_Textbl
780static Evas_Object_Textblock_Node_Format *_evas_textblock_cursor_node_format_at_pos_get(const Efl_Text_Cursor_Cursor *cur); 787static Evas_Object_Textblock_Node_Format *_evas_textblock_cursor_node_format_at_pos_get(const Efl_Text_Cursor_Cursor *cur);
781static int _evas_textblock_cursor_text_prepend(Efl_Text_Cursor_Cursor *cur, const char *_text); 788static int _evas_textblock_cursor_text_prepend(Efl_Text_Cursor_Cursor *cur, const char *_text);
782static void _evas_textblock_cursor_copy(Efl_Text_Cursor_Cursor *dst, const Efl_Text_Cursor_Cursor *src); 789static void _evas_textblock_cursor_copy(Efl_Text_Cursor_Cursor *dst, const Efl_Text_Cursor_Cursor *src);
790static void
791_textblock_style_generic_set(Evas_Object *eo_obj, Evas_Textblock_Style *ts, const char *key);
783 792
784/** selection iterator */ 793/** selection iterator */
785/** 794/**
@@ -6663,7 +6672,7 @@ _layout_setup(Ctxt *c, const Eo *eo_obj, Evas_Coord w, Evas_Coord h)
6663 /* setup default base style */ 6672 /* setup default base style */
6664 { 6673 {
6665 Eina_List *itr; 6674 Eina_List *itr;
6666 Evas_Textblock_Style *style; 6675 User_Style_Entry *use;
6667 Eina_Bool finalize = EINA_FALSE; 6676 Eina_Bool finalize = EINA_FALSE;
6668 if (!c->fmt) 6677 if (!c->fmt)
6669 { 6678 {
@@ -6676,11 +6685,11 @@ _layout_setup(Ctxt *c, const Eo *eo_obj, Evas_Coord w, Evas_Coord h)
6676 finalize = EINA_TRUE; 6685 finalize = EINA_TRUE;
6677 } 6686 }
6678 6687
6679 EINA_LIST_FOREACH(c->o->styles, itr, style) 6688 EINA_LIST_FOREACH(c->o->styles, itr, use)
6680 { 6689 {
6681 if ((style) && (style->default_tag)) 6690 if ((use->st) && (use->st->default_tag))
6682 { 6691 {
6683 _format_fill(c->obj, c->fmt, style->default_tag); 6692 _format_fill(c->obj, c->fmt, use->st->default_tag);
6684 finalize = EINA_TRUE; 6693 finalize = EINA_TRUE;
6685 } 6694 }
6686 } 6695 }
@@ -6885,6 +6894,7 @@ evas_object_textblock_add(Evas *e)
6885 efl_canvas_object_legacy_ctor(efl_added)); 6894 efl_canvas_object_legacy_ctor(efl_added));
6886 o = efl_data_scope_get(eo_obj, MY_CLASS); 6895 o = efl_data_scope_get(eo_obj, MY_CLASS);
6887 o->legacy_newline = EINA_TRUE; 6896 o->legacy_newline = EINA_TRUE;
6897 o->auto_styles = EINA_FALSE;
6888 return eo_obj; 6898 return eo_obj;
6889} 6899}
6890 6900
@@ -6925,6 +6935,8 @@ _efl_canvas_text_efl_object_constructor(Eo *eo_obj, Efl_Canvas_Text_Data *class_
6925 _FMT(ellipsis) = -1; 6935 _FMT(ellipsis) = -1;
6926 _FMT_INFO(bitmap_scalable) = EFL_TEXT_FONT_BITMAP_SCALABLE_COLOR; 6936 _FMT_INFO(bitmap_scalable) = EFL_TEXT_FONT_BITMAP_SCALABLE_COLOR;
6927 6937
6938 o->auto_styles = EINA_TRUE;
6939
6928 return eo_obj; 6940 return eo_obj;
6929} 6941}
6930 6942
@@ -6934,6 +6946,7 @@ evas_textblock_style_new(void)
6934 Evas_Textblock_Style *ts; 6946 Evas_Textblock_Style *ts;
6935 6947
6936 ts = calloc(1, sizeof(Evas_Textblock_Style)); 6948 ts = calloc(1, sizeof(Evas_Textblock_Style));
6949 ts->legacy = EINA_TRUE;
6937 return ts; 6950 return ts;
6938} 6951}
6939 6952
@@ -6947,7 +6960,7 @@ evas_textblock_style_free(Evas_Textblock_Style *ts)
6947 return; 6960 return;
6948 } 6961 }
6949 _style_clear(ts); 6962 _style_clear(ts);
6950 eina_stringshare_del(ts->key); 6963 // FIXME: free up user style entry
6951 free(ts); 6964 free(ts);
6952} 6965}
6953 6966
@@ -6999,6 +7012,7 @@ evas_textblock_style_set(Evas_Textblock_Style *ts, const char *text)
6999 Evas_Object *eo_obj; 7012 Evas_Object *eo_obj;
7000 7013
7001 if (!ts) return; 7014 if (!ts) return;
7015
7002 /* If the style wasn't really changed, abort. */ 7016 /* If the style wasn't really changed, abort. */
7003 if ((!ts->style_text && !text) || 7017 if ((!ts->style_text && !text) ||
7004 (ts->style_text && text && !strcmp(text, ts->style_text))) 7018 (ts->style_text && text && !strcmp(text, ts->style_text)))
@@ -7147,11 +7161,11 @@ static const char *
7147_textblock_format_node_from_style_tag(Efl_Canvas_Text_Data *o, Evas_Object_Textblock_Node_Format *fnode, const char *format, size_t format_len) 7161_textblock_format_node_from_style_tag(Efl_Canvas_Text_Data *o, Evas_Object_Textblock_Node_Format *fnode, const char *format, size_t format_len)
7148{ 7162{
7149 Eina_List *itr; 7163 Eina_List *itr;
7150 Evas_Textblock_Style *style;
7151 const char *match = NULL; 7164 const char *match = NULL;
7152 EINA_LIST_REVERSE_FOREACH(o->styles, itr, style) 7165 User_Style_Entry *use;
7166 EINA_LIST_REVERSE_FOREACH(o->styles, itr, use)
7153 { 7167 {
7154 match = _style_match_tag(style, format, format_len); 7168 match = _style_match_tag(use->st, format, format_len);
7155 if (match) 7169 if (match)
7156 break; 7170 break;
7157 } 7171 }
@@ -7177,32 +7191,82 @@ _textblock_format_node_from_style_tag(Efl_Canvas_Text_Data *o, Evas_Object_Textb
7177 7191
7178/* textblock styles */ 7192/* textblock styles */
7179 7193
7194static Eina_List *_style_cache = NULL;
7195
7180static void 7196static void
7181_textblock_style_generic_set(Evas_Object *eo_obj, Evas_Textblock_Style *ts, 7197_textblock_style_generic_set(Evas_Object *eo_obj, Evas_Textblock_Style *ts,
7182 Evas_Textblock_Style **obj_ts) 7198 const char *key)
7183{ 7199{
7184 TB_HEAD(); 7200 TB_HEAD();
7185 if (ts == *obj_ts) return; 7201 Eina_List *itr;
7202 Evas_Textblock_Style *old_ts = NULL;
7203
7204 if (!key)
7205 {
7206 old_ts = o->style;
7207 o->style = ts;
7208 }
7209 else
7210 {
7211 User_Style_Entry *us;
7212
7213 EINA_LIST_FOREACH(o->styles, itr, us)
7214 {
7215 if (!strcmp(us->key, key))
7216 {
7217 //us->st = ts;
7218 break;
7219 }
7220 }
7221 if (ts)
7222 {
7223 if (!us)
7224 {
7225 us = calloc(1, sizeof(*us));
7226 us->key = eina_stringshare_add(key);
7227 o->styles = eina_list_append(o->styles, us);
7228 }
7229
7230 old_ts = us->st;
7231 us->st = ts;
7232 }
7233 else if (us)
7234 {
7235 o->styles = eina_list_remove_list(o->styles, itr);
7236 free(us);
7237 }
7238 }
7239
7240 // Verify nothing has changed
7241 if (ts == old_ts) return;
7242
7186 if ((ts) && (ts->delete_me)) return; 7243 if ((ts) && (ts->delete_me)) return;
7187 if (*obj_ts) 7244
7245 if (old_ts)
7188 { 7246 {
7189 Evas_Textblock_Style *old_ts;
7190 if (o->markup_text) 7247 if (o->markup_text)
7191 { 7248 {
7192 eina_stringshare_del(o->markup_text); 7249 eina_stringshare_del(o->markup_text);
7193 o->markup_text = NULL; 7250 o->markup_text = NULL;
7194 } 7251 }
7195 7252
7196 old_ts = *obj_ts;
7197 old_ts->objects = eina_list_remove(old_ts->objects, eo_obj); 7253 old_ts->objects = eina_list_remove(old_ts->objects, eo_obj);
7198 if ((old_ts->delete_me) && (!old_ts->objects)) 7254 if (o->auto_styles && !old_ts->objects)
7199 evas_textblock_style_free(old_ts); 7255 {
7256 _style_cache = eina_list_remove(_style_cache, old_ts);
7257 evas_textblock_style_free(old_ts);
7258 }
7259 else if (!o->auto_styles && (old_ts->delete_me) && (!old_ts->objects))
7260 {
7261 // Legacy behavior ('delete_me' does not occur in new auto styles)
7262 evas_textblock_style_free(old_ts);
7263 }
7200 } 7264 }
7265
7201 if (ts) 7266 if (ts)
7202 { 7267 {
7203 ts->objects = eina_list_append(ts->objects, eo_obj); 7268 ts->objects = eina_list_append(ts->objects, eo_obj);
7204 } 7269 }
7205 *obj_ts = ts;
7206 7270
7207 _evas_textblock_update_format_nodes_from_style_tag(o); 7271 _evas_textblock_update_format_nodes_from_style_tag(o);
7208 7272
@@ -7217,36 +7281,48 @@ evas_object_textblock_style_set(Eo *eo_obj, const Evas_Textblock_Style *ts)
7217 EINA_SAFETY_ON_NULL_RETURN(eo_obj); 7281 EINA_SAFETY_ON_NULL_RETURN(eo_obj);
7218 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); 7282 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
7219 evas_object_async_block(obj); 7283 evas_object_async_block(obj);
7220 Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS); 7284 _textblock_style_generic_set(eo_obj, (Evas_Textblock_Style *) ts, NULL);
7221 _textblock_style_generic_set(eo_obj, (Evas_Textblock_Style *) ts, &(o->style));
7222} 7285}
7223 7286
7224static Evas_Textblock_Style * 7287static Evas_Textblock_Style *
7225_style_by_key_find(Efl_Canvas_Text_Data *o, const char *key) 7288_style_by_key_find(Efl_Canvas_Text_Data *o, const char *key)
7226{ 7289{
7227 Eina_List *itr; 7290 Eina_List *itr;
7228 Evas_Textblock_Style *style; 7291 User_Style_Entry *us;
7229 7292
7230 if (!key) 7293 if (!key)
7231 return o->style; 7294 return o->style;
7232 7295
7233 EINA_LIST_FOREACH(o->styles, itr, style) 7296 EINA_LIST_FOREACH(o->styles, itr, us)
7234 { 7297 {
7235 if (!strcmp(style->key, key)) 7298 if (!strcmp(us->key, key))
7236 return style; 7299 return us->st;
7237 } 7300 }
7238 7301
7239 return NULL; 7302 return NULL;
7240} 7303}
7241 7304
7242static void 7305static Evas_Textblock_Style *
7243_style_remove_from_obj(Eo *eo_obj, Efl_Canvas_Text_Data *o, Evas_Textblock_Style *ts, Eina_Bool style_free) 7306_style_fetch(const char *style)
7244{ 7307{
7245 o->styles = eina_list_remove(o->styles, ts); 7308 Evas_Textblock_Style *ts = NULL;
7246 ts->objects = eina_list_remove(ts->objects, eo_obj); 7309 Eina_List *i;
7310
7311 if (!style) return NULL;
7312
7313 EINA_LIST_FOREACH(_style_cache, i, ts)
7314 {
7315 if (ts->style_text == style) break;
7316 }
7247 7317
7248 if (style_free || (ts->delete_me && !ts->objects)) 7318 if (!ts)
7249 evas_textblock_style_free(ts); 7319 {
7320 ts = evas_textblock_style_new();
7321 ts->legacy = EINA_FALSE;
7322 evas_textblock_style_set(ts, style);
7323 _style_cache = eina_list_append(_style_cache, ts);
7324 }
7325 return ts;
7250} 7326}
7251 7327
7252EOLIAN static void 7328EOLIAN static void
@@ -7258,52 +7334,9 @@ _efl_canvas_text_style_set(Eo *eo_obj, Efl_Canvas_Text_Data *o, const char *key,
7258 7334
7259 Evas_Textblock_Style *ts; 7335 Evas_Textblock_Style *ts;
7260 7336
7261 ts = _style_by_key_find(o, key); 7337 ts = _style_fetch(style);
7262
7263 if (!ts && !style)
7264 {
7265 return;
7266 }
7267 7338
7268 if (ts && !style) 7339 _textblock_style_generic_set(eo_obj, ts, key);
7269 {
7270 // Delete the style
7271 if (!key)
7272 {
7273 evas_textblock_style_set(ts, "");
7274 }
7275 else
7276 {
7277 _style_remove_from_obj(eo_obj, o, ts, EINA_TRUE);
7278 }
7279 }
7280 else if (!ts && style)
7281 {
7282 Evas_Textblock_Style *tmp = NULL;
7283
7284 // No entry for respective key, so create one.
7285 ts = evas_textblock_style_new();
7286 evas_textblock_style_set(ts, style);
7287 ts->key = eina_stringshare_add(key);
7288
7289 /* If the given key value is NULL, newly created Evas Textblock Style
7290 * has to be assigned to o->style. */
7291 if (ts->key)
7292 o->styles = eina_list_append(o->styles, ts);
7293 else
7294 o->style = ts;
7295
7296 _textblock_style_generic_set(eo_obj, ts, &tmp);
7297 }
7298 else if (ts && style)
7299 {
7300 evas_textblock_style_set(ts, style);
7301 }
7302
7303 o->format_changed = EINA_TRUE;
7304 _evas_textblock_invalidate_all(o);
7305 _evas_textblock_changed(o, eo_obj);
7306 efl_event_callback_call(eo_obj, EFL_CANVAS_TEXT_EVENT_CHANGED, NULL);
7307} 7340}
7308 7341
7309EAPI Evas_Textblock_Style * 7342EAPI Evas_Textblock_Style *
@@ -7334,24 +7367,7 @@ evas_object_textblock_style_user_push(Eo *eo_obj, Evas_Textblock_Style *ts)
7334 Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS); 7367 Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
7335 Evas_Textblock_Style *old_ts, *tmp = NULL; 7368 Evas_Textblock_Style *old_ts, *tmp = NULL;
7336 7369
7337 old_ts = _style_by_key_find(o, _STYLE_USER); 7370 _textblock_style_generic_set(eo_obj, ts, _STYLE_USER);
7338
7339 if (old_ts == ts) return;
7340
7341 if (old_ts)
7342 _style_remove_from_obj(eo_obj, o, old_ts, EINA_FALSE);
7343
7344 if (ts)
7345 {
7346 _textblock_style_generic_set(eo_obj, ts, &tmp);
7347 ts->key = eina_stringshare_add(_STYLE_USER);
7348 o->styles = eina_list_append(o->styles, ts);
7349 }
7350
7351 o->format_changed = EINA_TRUE;
7352 _evas_textblock_invalidate_all(o);
7353 _evas_textblock_changed(o, eo_obj);
7354 efl_event_callback_call(eo_obj, EFL_CANVAS_TEXT_EVENT_CHANGED, NULL);
7355} 7371}
7356 7372
7357EAPI const Evas_Textblock_Style* 7373EAPI const Evas_Textblock_Style*
@@ -7375,15 +7391,7 @@ evas_object_textblock_style_user_pop(Eo *eo_obj)
7375 Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS); 7391 Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
7376 Evas_Textblock_Style *ts = _style_by_key_find(o, _STYLE_USER); 7392 Evas_Textblock_Style *ts = _style_by_key_find(o, _STYLE_USER);
7377 7393
7378 if (ts) 7394 _textblock_style_generic_set(eo_obj, NULL, _STYLE_USER);
7379 {
7380 _style_remove_from_obj(eo_obj, o, ts, EINA_FALSE);
7381
7382 o->format_changed = EINA_TRUE;
7383 _evas_textblock_invalidate_all(o);
7384 _evas_textblock_changed(o, eo_obj);
7385 efl_event_callback_call(eo_obj, EFL_CANVAS_TEXT_EVENT_CHANGED, NULL);
7386 }
7387} 7395}
7388 7396
7389EAPI void 7397EAPI void
@@ -13294,10 +13302,22 @@ evas_object_textblock_free(Evas_Object *eo_obj)
13294 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); 13302 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
13295 Efl_Canvas_Text_Filter_Program *prg; 13303 Efl_Canvas_Text_Filter_Program *prg;
13296 Evas_Filter_Data_Binding *db; 13304 Evas_Filter_Data_Binding *db;
13305 User_Style_Entry *use;
13297 13306
13298 _evas_object_textblock_clear(eo_obj); 13307 _evas_object_textblock_clear(eo_obj);
13299 evas_object_textblock_style_set(eo_obj, NULL); 13308 evas_object_textblock_style_set(eo_obj, NULL);
13300 13309
13310 EINA_LIST_FREE(o->styles, use)
13311 {
13312 Evas_Textblock_Style *ts = use->st;
13313 ts->objects = eina_list_remove(ts->objects, eo_obj);
13314 if (!ts->objects && (ts->delete_me || o->auto_styles))
13315 {
13316 evas_textblock_style_free(ts);
13317 }
13318 free(use);
13319 }
13320
13301 EINA_INLIST_FREE(o->gfx_filter.programs, prg) 13321 EINA_INLIST_FREE(o->gfx_filter.programs, prg)
13302 { 13322 {
13303 EINA_INLIST_REMOVE(o->gfx_filter.programs, prg); 13323 EINA_INLIST_REMOVE(o->gfx_filter.programs, prg);