summaryrefslogtreecommitdiff
path: root/src/lib/evas/canvas
diff options
context:
space:
mode:
authorThiep Ha <thiepha@gmail.com>2014-11-26 11:29:08 +0000
committerTom Hacohen <tom@stosb.com>2014-11-26 11:29:09 +0000
commitc30303d7e8dd92763298156d9bcaee2b1b1d5d86 (patch)
tree66f7497d9d50c091300a2def60ebbfce6ad2b403 /src/lib/evas/canvas
parentf6a5ada4a215b93bb65be44ea04856c528c82ba7 (diff)
edje entry: improve selection performance
Summary: The selection performance is slow if we select large chunk of text. This is caused by many rectangles created and deleted. This patch provides a way to improve it by combine selection rectangles of line in middle into one rectangles (i.e, if we have N lines, the selection rectangle for lines 2 to N-1 will be combined into one.) @feature Reviewers: raster, cedric, tasn Subscribers: herdsman, woohyun, cedric Differential Revision: https://phab.enlightenment.org/D1508
Diffstat (limited to 'src/lib/evas/canvas')
-rw-r--r--src/lib/evas/canvas/evas_object_textblock.c186
1 files changed, 185 insertions, 1 deletions
diff --git a/src/lib/evas/canvas/evas_object_textblock.c b/src/lib/evas/canvas/evas_object_textblock.c
index 9b9a9eea58..35e3da550c 100644
--- a/src/lib/evas/canvas/evas_object_textblock.c
+++ b/src/lib/evas/canvas/evas_object_textblock.c
@@ -199,7 +199,12 @@ typedef struct _Evas_Object_Textblock_Format_Item Evas_Object_Textblock_Format_I
199 * A textblock format. 199 * A textblock format.
200 */ 200 */
201typedef struct _Evas_Object_Textblock_Format Evas_Object_Textblock_Format; 201typedef struct _Evas_Object_Textblock_Format Evas_Object_Textblock_Format;
202 202/**
203 * @internal
204 * @typedef Evas_Textblock_Selection_Iterator
205 * A textblock selection iterator.
206 */
207typedef struct _Evas_Textblock_Selection_Iterator Evas_Textblock_Selection_Iterator;
203/** 208/**
204 * @internal 209 * @internal
205 * @def IS_AT_END(ti, ind) 210 * @def IS_AT_END(ti, ind)
@@ -513,6 +518,13 @@ struct _Evas_Object_Textblock
513 Eina_Bool legacy_newline : 1; 518 Eina_Bool legacy_newline : 1;
514}; 519};
515 520
521struct _Evas_Textblock_Selection_Iterator
522{
523 Eina_Iterator iterator; /**< Eina Iterator. */
524 Eina_List *list; /**< Head of list. */
525 Eina_List *current; /**< Current node in loop. */
526};
527
516/* private methods for textblock objects */ 528/* private methods for textblock objects */
517static void evas_object_textblock_init(Evas_Object *eo_obj); 529static void evas_object_textblock_init(Evas_Object *eo_obj);
518static void evas_object_textblock_render(Evas_Object *eo_obj, 530static void evas_object_textblock_render(Evas_Object *eo_obj,
@@ -597,6 +609,85 @@ static void _evas_textblock_invalidate_all(Evas_Textblock_Data *o);
597static void _evas_textblock_cursors_update_offset(const Evas_Textblock_Cursor *cur, const Evas_Object_Textblock_Node_Text *n, size_t start, int offset); 609static void _evas_textblock_cursors_update_offset(const Evas_Textblock_Cursor *cur, const Evas_Object_Textblock_Node_Text *n, size_t start, int offset);
598static void _evas_textblock_cursors_set_node(Evas_Textblock_Data *o, const Evas_Object_Textblock_Node_Text *n, Evas_Object_Textblock_Node_Text *new_node); 610static void _evas_textblock_cursors_set_node(Evas_Textblock_Data *o, const Evas_Object_Textblock_Node_Text *n, Evas_Object_Textblock_Node_Text *new_node);
599 611
612/** selection iterator */
613/**
614 * @internal
615 * Returns the value of the current data of list node,
616 * and goes to the next list node.
617 *
618 * @param it the iterator.
619 * @param data the data of the current list node.
620 * @return EINA_FALSE if the current list node does not exists.
621 * Otherwise, returns EINA_TRUE.
622 */
623static Eina_Bool
624_evas_textblock_selection_iterator_next(Evas_Textblock_Selection_Iterator *it, void **data)
625{
626 if (!it->current)
627 return EINA_FALSE;
628
629 *data = eina_list_data_get(it->current);
630 it->current = eina_list_next(it->current);
631
632 return EINA_TRUE;
633}
634
635/**
636 * @internal
637 * Gets the iterator container (Eina_List) which created the iterator.
638 * @param it the iterator.
639 * @return A pointer to Eina_List.
640 */
641static Eina_List *
642_evas_textblock_selection_iterator_get_container(Evas_Textblock_Selection_Iterator *it)
643{
644 return it->list;
645}
646
647/**
648 * @internal
649 * Frees the iterator container (Eina_List).
650 * @param it the iterator.
651 */
652static void
653_evas_textblock_selection_iterator_free(Evas_Textblock_Selection_Iterator *it)
654{
655 while (it->list)
656 it->list = eina_list_remove_list(it->list, it->list);
657 EINA_MAGIC_SET(&it->iterator, 0);
658 free(it);
659}
660
661/**
662 * @internal
663 * Creates newly allocated iterator associated to a list.
664 * @param list The list.
665 * @return If the memory cannot be allocated, NULL is returned.
666 * Otherwise, a valid iterator is returned.
667 */
668Eina_Iterator *
669_evas_textblock_selection_iterator_new(Eina_List *list)
670{
671 Evas_Textblock_Selection_Iterator *it;
672
673 it = calloc(1, sizeof(Evas_Textblock_Selection_Iterator));
674 if (!it) return NULL;
675
676 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
677 it->list = list;
678 it->current = list;
679
680 it->iterator.version = EINA_ITERATOR_VERSION;
681 it->iterator.next = FUNC_ITERATOR_NEXT(
682 _evas_textblock_selection_iterator_next);
683 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
684 _evas_textblock_selection_iterator_get_container);
685 it->iterator.free = FUNC_ITERATOR_FREE(
686 _evas_textblock_selection_iterator_free);
687
688 return &it->iterator;
689}
690
600/* styles */ 691/* styles */
601/** 692/**
602 * @internal 693 * @internal
@@ -10343,6 +10434,99 @@ _evas_textblock_cursor_range_in_line_geometry_get(
10343 return rects; 10434 return rects;
10344} 10435}
10345 10436
10437EAPI Eina_Iterator *
10438evas_textblock_cursor_range_simple_geometry_get(const Evas_Textblock_Cursor *cur1, const Evas_Textblock_Cursor *cur2)
10439{
10440 Evas_Object_Textblock_Line *ln1, *ln2;
10441 Evas_Object_Textblock_Item *it1, *it2;
10442 Eina_List *rects = NULL;
10443 Eina_Iterator *itr = NULL;
10444
10445 if (!cur1 || !cur1->node) return NULL;
10446 if (!cur2 || !cur2->node) return NULL;
10447 if (cur1->obj != cur2->obj) return NULL;
10448 Evas_Textblock_Data *o = eo_data_scope_get(cur1->obj, MY_CLASS);
10449
10450 _relayout_if_needed(cur1->obj, o);
10451
10452 if (evas_textblock_cursor_compare(cur1, cur2) > 0)
10453 {
10454 const Evas_Textblock_Cursor *tc;
10455
10456 tc = cur1;
10457 cur1 = cur2;
10458 cur2 = tc;
10459 }
10460
10461 ln1 = ln2 = NULL;
10462 it1 = it2 = NULL;
10463 _find_layout_item_match(cur1, &ln1, &it1);
10464 if (!ln1 || !it1) return NULL;
10465 _find_layout_item_match(cur2, &ln2, &it2);
10466 if (!ln2 || !it2) return NULL;
10467
10468 if (ln1 == ln2)
10469 {
10470 rects = _evas_textblock_cursor_range_in_line_geometry_get(ln1, cur1, cur2);
10471 }
10472 else
10473 {
10474 int lm = 0, rm = 0;
10475 Eina_List *rects2 = NULL;
10476 Evas_Coord w;
10477 Evas_Textblock_Cursor *tc;
10478 Evas_Textblock_Rectangle *tr;
10479
10480 if (ln1->items)
10481 {
10482 Evas_Object_Textblock_Format *fm = ln1->items->format;
10483 if (fm)
10484 {
10485 lm = fm->margin.l;
10486 rm = fm->margin.r;
10487 }
10488 }
10489
10490 evas_object_geometry_get(cur1->obj, NULL, NULL, &w, NULL);
10491 rects = _evas_textblock_cursor_range_in_line_geometry_get(ln1, cur1, NULL);
10492
10493 /* Extend selection rectangle in first line */
10494 tc = evas_object_textblock_cursor_new(cur1->obj);
10495 evas_textblock_cursor_copy(cur1, tc);
10496 evas_textblock_cursor_line_char_last(tc);
10497 tr = calloc(1, sizeof(Evas_Textblock_Rectangle));
10498 evas_textblock_cursor_pen_geometry_get(tc, &tr->x, &tr->y, &tr->w, &tr->h);
10499 if (ln1->par->direction == EVAS_BIDI_DIRECTION_RTL)
10500 {
10501 tr->w = tr->x + tr->w - rm;
10502 tr->x = lm;
10503 }
10504 else
10505 {
10506 tr->w = w - tr->x - rm;
10507 }
10508 rects = eina_list_append(rects, tr);
10509 evas_textblock_cursor_free(tc);
10510
10511 rects2 = _evas_textblock_cursor_range_in_line_geometry_get(ln2, NULL, cur2);
10512
10513 /* Add middle rect */
10514 if ((ln1->par->y + ln1->y + ln1->h) != (ln2->par->y + ln2->y))
10515 {
10516 tr = calloc(1, sizeof(Evas_Textblock_Rectangle));
10517 tr->x = lm;
10518 tr->y = ln1->par->y + ln1->y + ln1->h;
10519 tr->w = w - tr->x - rm;
10520 tr->h = ln2->par->y + ln2->y - tr->y;
10521 rects = eina_list_append(rects, tr);
10522 }
10523 rects = eina_list_merge(rects, rects2);
10524 }
10525 itr = _evas_textblock_selection_iterator_new(rects);
10526
10527 return itr;
10528}
10529
10346EAPI Eina_List * 10530EAPI Eina_List *
10347evas_textblock_cursor_range_geometry_get(const Evas_Textblock_Cursor *cur1, const Evas_Textblock_Cursor *cur2) 10531evas_textblock_cursor_range_geometry_get(const Evas_Textblock_Cursor *cur1, const Evas_Textblock_Cursor *cur2)
10348{ 10532{