return rects;
}
+/* Helper that creates a selection rectangle to a given line.
+ * The given 'inv' indicates an inverse behavior. */
+static Evas_Textblock_Rectangle *
+_line_fill_rect_get(const Evas_Object_Textblock_Line *ln,
+ Evas_Coord w, Evas_Coord lm, Evas_Coord rm, Eina_Bool inv)
+{
+ Evas_Textblock_Rectangle *tr;
+
+ tr = calloc(1, sizeof(Evas_Textblock_Rectangle));
+ tr->y = ln->par->y + ln->y;
+ tr->h = ln->h;
+
+ //Reminder: ln->x includes the left margin */
+ if ((!inv && (ln->par->direction == EVAS_BIDI_DIRECTION_RTL)) ||
+ (inv && (ln->par->direction != EVAS_BIDI_DIRECTION_RTL)))
+ {
+ tr->x = lm;
+ tr->w = ln->x - lm;
+ }
+ else
+ {
+ tr->x = ln->x + ln->w;
+ tr->w = w - rm - tr->x;
+ }
+
+ if (tr->w == 0)
+ {
+ free(tr);
+ tr = NULL;
+ }
+ return tr;
+}
+
EAPI Eina_Iterator *
evas_textblock_cursor_range_simple_geometry_get(const Evas_Textblock_Cursor *cur1, const Evas_Textblock_Cursor *cur2)
{
int lm = 0, rm = 0;
Eina_List *rects2 = NULL;
Evas_Coord w;
- Evas_Textblock_Cursor *tc;
Evas_Textblock_Rectangle *tr;
+ evas_object_geometry_get(cur1->obj, NULL, NULL, &w, NULL);
+
+ /* Use the minimum left margin and right margin for a uniform
+ * line coverage of the rectangles */
if (ln1->items)
{
Evas_Object_Textblock_Format *fm = ln1->items->format;
}
}
- evas_object_geometry_get(cur1->obj, NULL, NULL, &w, NULL);
- rects = _evas_textblock_cursor_range_in_line_geometry_get(ln1, cur1, NULL);
-
- /* Extend selection rectangle in first line */
- tc = evas_object_textblock_cursor_new(cur1->obj);
- evas_textblock_cursor_copy(cur1, tc);
- evas_textblock_cursor_line_char_last(tc);
- tr = calloc(1, sizeof(Evas_Textblock_Rectangle));
- evas_textblock_cursor_pen_geometry_get(tc, &tr->x, &tr->y, &tr->w, &tr->h);
- if (ln1->par->direction == EVAS_BIDI_DIRECTION_RTL)
+ if (ln2->items)
{
- tr->w = tr->x + tr->w - rm;
- tr->x = lm;
+ Evas_Object_Textblock_Format *fm = ln2->items->format;
+ if (fm)
+ {
+ if (fm->margin.l < lm) lm = fm->margin.l;
+ if (fm->margin.r < rm) rm = fm->margin.r;
+ }
}
- else
+
+ /* Append the rectangles by visual order (top, middle, bottom). Keep
+ * it like that so it is also easier to test and debug. */
+
+ /* Top line */
+ rects = _evas_textblock_cursor_range_in_line_geometry_get(ln1, cur1, NULL);
+ /* Fill-in the top line */
+ tr = _line_fill_rect_get(ln1, w, lm, rm, EINA_FALSE);
+ if (tr)
{
- tr->w = w - tr->x - rm;
+ rects = eina_list_append(rects, tr);
}
- rects = eina_list_append(rects, tr);
- evas_textblock_cursor_free(tc);
-
- rects2 = _evas_textblock_cursor_range_in_line_geometry_get(ln2, NULL, cur2);
- /* Add middle rect */
+ /* Middle rect (lines) */
if ((ln1->par->y + ln1->y + ln1->h) != (ln2->par->y + ln2->y))
{
tr = calloc(1, sizeof(Evas_Textblock_Rectangle));
tr->h = ln2->par->y + ln2->y - tr->y;
rects = eina_list_append(rects, tr);
}
+
+ /* Bottom line */
+ rects2 = _evas_textblock_cursor_range_in_line_geometry_get(ln2, NULL, cur2);
+ /* Fill-in the bottom line */
+ tr = _line_fill_rect_get(ln2, w, lm, rm, EINA_TRUE);
+ if (tr)
+ {
+ rects2 = eina_list_append(rects2, tr);
+ }
rects = eina_list_merge(rects, rects2);
}
itr = _evas_textblock_selection_iterator_new(rects);
eina_iterator_free(it);
eina_iterator_free(it2);
+ /* Check number of rectangles in case a of line wrapping */
+ evas_object_textblock_text_markup_set(tb, "<wrap=word>abc def <color=#0ff>ghi");
+ evas_object_resize(tb, w, w / 2);
+ evas_textblock_cursor_pos_set(cur, 10);
+
+ {
+ Evas_Coord cx;
+ evas_textblock_cursor_geometry_bidi_get(cur, &cx, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ EVAS_TEXTBLOCK_CURSOR_BEFORE);
+ /* enforce wrapping of "ghi" to the next line */
+ evas_object_resize(tb, cx, 400);
+ /* Sanity, check there is actually a second line */
+ fail_if (!evas_textblock_cursor_line_set(cur, 1));
+ fail_if (evas_textblock_cursor_line_set(cur, 2));
+ }
+
+ evas_textblock_cursor_pos_set(cur, 7);
+ evas_textblock_cursor_pos_set(main_cur, 9);
+
+ it = evas_textblock_cursor_range_simple_geometry_get(cur, main_cur);
+ fail_if(!it);
+ rects = eina_iterator_container_get(it);
+ fail_if(!rects);
+ ck_assert_int_eq(eina_list_count(rects), 3);
+
+ {
+ Evas_Coord y1, y2;
+ void *tmp = tr;
+ /* We have 3 rectangles */
+ Eina_Iterator *itr = it;
+ fail_if (!eina_iterator_next(itr, &tmp));
+ tr = tmp;
+ y1 = tr->y;
+ fail_if (!eina_iterator_next(itr, &tmp));
+ tr = tmp;
+ y2 = tr->y;
+
+ /* Basically it means that the "extending" rectangle should not somehow
+ * reach the second line in this example. */
+ ck_assert_int_eq(y1, y2);
+ eina_iterator_free(it);
+ }
+
+ /* Alignment fills */
+
+ /* LTR text */
+ evas_object_resize(tb, 400, 400);
+ evas_object_textblock_text_markup_set(tb,
+ "<align=0.1>"
+ "Hello World<ps>"
+ "How are you<ps>");
+ evas_textblock_cursor_line_set(cur, 0);
+ evas_textblock_cursor_line_set(main_cur, 1);
+ it = evas_textblock_cursor_range_simple_geometry_get(cur, main_cur);
+ fail_if(!it);
+ rects = eina_iterator_container_get(it);
+ fail_if(!rects);
+ ck_assert_int_eq(eina_list_count(rects), 3);
+ evas_textblock_cursor_char_next(main_cur);
+ eina_iterator_free(it);
+
+ evas_textblock_cursor_char_next(main_cur);
+ it = evas_textblock_cursor_range_simple_geometry_get(cur, main_cur);
+ fail_if(!it);
+ rects = eina_iterator_container_get(it);
+ fail_if(!rects);
+ ck_assert_int_eq(eina_list_count(rects), 4);
+ evas_textblock_cursor_char_next(main_cur);
+ eina_iterator_free(it);
+
+ evas_textblock_cursor_line_set(main_cur, 2);
+ evas_textblock_cursor_char_next(main_cur);
+ it = evas_textblock_cursor_range_simple_geometry_get(cur, main_cur);
+ fail_if(!it);
+ rects = eina_iterator_container_get(it);
+ fail_if(!rects);
+ ck_assert_int_eq(eina_list_count(rects), 4);
+ evas_textblock_cursor_char_next(main_cur);
+ eina_iterator_free(it);
+
+ /* RTL text aligned to the left */
+ evas_object_textblock_text_markup_set(tb,
+ "<align=left>"
+ "שלום עולם<ps>"
+ "מה שלומך");
+ evas_textblock_cursor_line_set(cur, 0);
+ evas_textblock_cursor_line_set(main_cur, 1);
+ it = evas_textblock_cursor_range_simple_geometry_get(cur, main_cur);
+ fail_if(!it);
+ rects = eina_iterator_container_get(it);
+ fail_if(!rects);
+ ck_assert_int_eq(eina_list_count(rects), 2);
+ evas_textblock_cursor_char_next(main_cur);
+ eina_iterator_free(it);
+
+ evas_textblock_cursor_char_next(main_cur);
+ it = evas_textblock_cursor_range_simple_geometry_get(cur, main_cur);
+ fail_if(!it);
+ rects = eina_iterator_container_get(it);
+ fail_if(!rects);
+ ck_assert_int_eq(eina_list_count(rects), 3);
+ evas_textblock_cursor_char_next(main_cur);
+ eina_iterator_free(it);
+
+ /* RTL text aligned to the middle */
+ evas_object_textblock_text_markup_set(tb,
+ "<align=middle>"
+ "שלום עולם<ps>"
+ "מה שלומך");
+ evas_textblock_cursor_line_set(cur, 0);
+ evas_textblock_cursor_line_set(main_cur, 1);
+ it = evas_textblock_cursor_range_simple_geometry_get(cur, main_cur);
+ fail_if(!it);
+ rects = eina_iterator_container_get(it);
+ fail_if(!rects);
+ ck_assert_int_eq(eina_list_count(rects), 3);
+ eina_iterator_free(it);
+
+ evas_textblock_cursor_char_next(main_cur);
+ it = evas_textblock_cursor_range_simple_geometry_get(cur, main_cur);
+ fail_if(!it);
+ rects = eina_iterator_container_get(it);
+ fail_if(!rects);
+ ck_assert_int_eq(eina_list_count(rects), 4);
+ eina_iterator_free(it);
+
+ evas_object_textblock_text_markup_set(tb,
+ "<align=middle>"
+ "שלום עולם<ps>"
+ "מה שלומך");
+ evas_textblock_cursor_line_set(cur, 0);
+ evas_textblock_cursor_line_set(main_cur, 1);
+ it = evas_textblock_cursor_range_simple_geometry_get(cur, main_cur);
+ fail_if(!it);
+ rects = eina_iterator_container_get(it);
+ fail_if(!rects);
+ ck_assert_int_eq(eina_list_count(rects), 3);
+ eina_iterator_free(it);
+
+ evas_textblock_cursor_char_next(main_cur);
+ it = evas_textblock_cursor_range_simple_geometry_get(cur, main_cur);
+ fail_if(!it);
+ rects = eina_iterator_container_get(it);
+ fail_if(!rects);
+ ck_assert_int_eq(eina_list_count(rects), 4);
+ eina_iterator_free(it);
+
+ /* Auto align RTL and LTR */
+ evas_object_textblock_text_markup_set(tb,
+ "Hello world<ps>"
+ "מה שלומך");
+ evas_textblock_cursor_line_set(cur, 0);
+ evas_textblock_cursor_line_set(main_cur, 1);
+ it = evas_textblock_cursor_range_simple_geometry_get(cur, main_cur);
+ fail_if(!it);
+ rects = eina_iterator_container_get(it);
+ fail_if(!rects);
+ ck_assert_int_eq(eina_list_count(rects), 2);
+ eina_iterator_free(it);
+
+ evas_textblock_cursor_char_next(main_cur);
+ it = evas_textblock_cursor_range_simple_geometry_get(cur, main_cur);
+ fail_if(!it);
+ rects = eina_iterator_container_get(it);
+ fail_if(!rects);
+ ck_assert_int_eq(eina_list_count(rects), 3);
+ eina_iterator_free(it);
+
/* Same run different scripts */
evas_object_textblock_text_markup_set(tb, "עבריתenglishрусскийעברית");