herdsman pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=20ef85e307818c7c92927688ee6fd5d9dec1ee8f
commit 20ef85e307818c7c92927688ee6fd5d9dec1ee8f Author: Youngbok Shin <youngb.s...@samsung.com> Date: Wed Dec 9 09:50:33 2015 +0200 Evas text: Fix Evas Text truncated text case. Summary: Evas Text only concerns about a advance of each text item. When a width of last character is bigger than its advance, the last character can be truncated. And the different line size calculation caused different aligning between Evas Text and Evas Textblock. So, the width of last character will be considered in Evas Text just like Evas Textblock. @fix Test Plan: The following text shows how the size calculation is different between Evas Textblock and Text. Get native size from Evas Textblock and get width(geometry) of Evas Text. You can see the width of Evas Text is bigger than native size of Evas Textblock. (adv > width) こんにちは。 The following text will be truncated without this patch. (adv < width) ନୂଁ Reviewers: woohyun, tasn, herdsman Subscribers: jpeg, cedric Differential Revision: https://phab.enlightenment.org/D3004 --- src/lib/evas/canvas/evas_object_text.c | 33 ++++++++++------- src/tests/evas/evas_test_text.c | 65 ++++++++++++++++++++++++++-------- 2 files changed, 71 insertions(+), 27 deletions(-) diff --git a/src/lib/evas/canvas/evas_object_text.c b/src/lib/evas/canvas/evas_object_text.c index ff3e761..46b2039 100644 --- a/src/lib/evas/canvas/evas_object_text.c +++ b/src/lib/evas/canvas/evas_object_text.c @@ -54,7 +54,7 @@ struct _Evas_Text_Data Evas_Object_Text_Item *ellipsis_end; Evas_Coord w, h; int advance; - int advance_without_ellipsis; + int width_without_ellipsis; Eina_Bool ellipsis; } last_computed; @@ -348,9 +348,9 @@ _evas_object_text_char_at_coords(const Evas_Object *eo_obj, } static Evas_Coord -_evas_object_text_horiz_advance_without_ellipsis_get(const Evas_Text_Data *o) +_evas_object_text_horiz_width_without_ellipsis_get(const Evas_Text_Data *o) { - return o->last_computed.advance_without_ellipsis; + return o->last_computed.width_without_ellipsis; } static Evas_Coord @@ -685,7 +685,7 @@ _evas_object_text_layout(Evas_Object *eo_obj, Evas_Text_Data *o, Eina_Unicode *t { Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS); EvasBiDiStrIndex *v_to_l = NULL; - Evas_Coord advance = 0; + Evas_Coord advance = 0, width = 0; size_t pos, visual_pos; int len = eina_unicode_strlen(text); int l = 0, r = 0; @@ -754,6 +754,8 @@ _evas_object_text_layout(Evas_Object *eo_obj, Evas_Text_Data *o, Eina_Unicode *t if (text) { + const Evas_Object_Text_Item *last_it = NULL; + while (len > 0) { Evas_Font_Instance *script_fi = NULL; @@ -791,15 +793,22 @@ _evas_object_text_layout(Evas_Object *eo_obj, Evas_Text_Data *o, Eina_Unicode *t pos += run_len; script_len -= run_len; len -= run_len; + + if (it->w > 0) + last_it = it; } } + + width = advance; + if (last_it) + width += last_it->w - last_it->adv; } - o->last_computed.advance_without_ellipsis = advance; + o->last_computed.width_without_ellipsis = width; _evas_object_text_pad_get(eo_obj, o, &l, &r, NULL, NULL); /* Handle ellipsis */ - if (pos && (o->cur.ellipsis >= 0.0) && (advance + l + r > obj->cur->geometry.w) && (obj->cur->geometry.w > 0)) + if (pos && (o->cur.ellipsis >= 0.0) && (width + l + r > obj->cur->geometry.w) && (obj->cur->geometry.w > 0)) { Evas_Coord ellip_frame = obj->cur->geometry.w; Evas_Object_Text_Item *start_ellip_it = NULL, *end_ellip_it = NULL; @@ -821,7 +830,7 @@ _evas_object_text_layout(Evas_Object *eo_obj, Evas_Text_Data *o, Eina_Unicode *t start_ellip_it = _layout_ellipsis_item_new(obj, o); } o->last_computed.ellipsis_start = start_ellip_it; - ellip_frame -= start_ellip_it->adv; + ellip_frame -= start_ellip_it->w; } if (o->cur.ellipsis != 1) { @@ -837,18 +846,18 @@ _evas_object_text_layout(Evas_Object *eo_obj, Evas_Text_Data *o, Eina_Unicode *t end_ellip_it = _layout_ellipsis_item_new(obj, o); } o->last_computed.ellipsis_end = end_ellip_it; - ellip_frame -= end_ellip_it->adv; + ellip_frame -= end_ellip_it->w; } /* The point where we should start from, going for the full * ellip frame. */ - Evas_Coord ellipsis_coord = o->cur.ellipsis * (advance - ellip_frame); + Evas_Coord ellipsis_coord = o->cur.ellipsis * (width - ellip_frame); if (start_ellip_it) { Evas_Object_Text_Item *itr = o->items; advance = 0; - while (itr && (advance + l + r + itr->adv < ellipsis_coord)) + while (itr && (advance + l + r + itr->w < ellipsis_coord)) { Eina_Inlist *itrn = EINA_INLIST_GET(itr)->next; if ((itr != start_ellip_it) && (itr != end_ellip_it)) @@ -890,7 +899,7 @@ _evas_object_text_layout(Evas_Object *eo_obj, Evas_Text_Data *o, Eina_Unicode *t { if (itr != end_ellip_it) /* was start_ellip_it */ { - if (advance + l + r + itr->adv >= ellip_frame) + if (advance + l + r + itr->w >= ellip_frame) { break; } @@ -2243,7 +2252,7 @@ _evas_object_text_recalc(Evas_Object *eo_obj, Eina_Unicode *text) int w, h; int l = 0, r = 0, t = 0, b = 0; - w = _evas_object_text_horiz_advance_without_ellipsis_get(o); + w = _evas_object_text_horiz_width_without_ellipsis_get(o); h = _evas_object_text_vert_advance_get(eo_obj, o); _evas_object_text_pad_get(eo_obj, o, &l, &r, &t, &b); diff --git a/src/tests/evas/evas_test_text.c b/src/tests/evas/evas_test_text.c index 128e8ac..fe5644a 100644 --- a/src/tests/evas/evas_test_text.c +++ b/src/tests/evas/evas_test_text.c @@ -141,6 +141,20 @@ START_TEST(evas_text_geometries) pos = evas_object_text_last_up_to_pos(to, -50, 0); ck_assert_int_eq(pos, -1); + /* Obviously, adv > width case */ + evas_object_text_text_set(to, "こんにちは。"); + adv = evas_object_text_horiz_advance_get(to); + evas_object_geometry_get(to, NULL, NULL, &w, NULL); + ck_assert_int_lt(w, adv); + +#ifdef HAVE_HARFBUZZ + /* Obviously, adv < width case */ + evas_object_text_text_set(to, "ନୂଁ"); + adv = evas_object_text_horiz_advance_get(to); + evas_object_geometry_get(to, NULL, NULL, &w, NULL); + ck_assert_int_lt(adv, w); +#endif + END_TEXT_TEST(); } END_TEST @@ -172,27 +186,36 @@ END_TEST static void _test_ellipsis(Evas_Object *to, const char *buf, const char *font, Evas_Font_Size size, double ellipsis) { + Evas_Coord text_width; + Evas_Coord w, h; + evas_object_text_ellipsis_set(to, ellipsis); evas_object_move(to, 0, 0); - evas_object_resize(to, 500, 500); evas_object_text_font_set(to, font, size); evas_object_text_text_set(to, buf); + /* Besure to give a enough width for text. */ + evas_object_resize(to, 500, 500); + /* Because of the way text object behaves, this will actually force + * a resize. */ + evas_object_geometry_get(to, NULL, NULL, &w, NULL); + + text_width = w; + /* Force a resize. */ + evas_object_resize(to, text_width - 1, 500); + evas_object_geometry_get(to, NULL, NULL, &w, NULL); + ck_assert_int_ne(text_width, w); /* Make it smaller to force ellipsis and check the resulting size. */ - { - Evas_Coord w, h; - evas_object_geometry_get(to, NULL, NULL, NULL, &h); - evas_object_resize(to, 140, h); - - /* Because of the way text object behaves, this will actually force - * a resize. */ - evas_object_geometry_get(to, NULL, NULL, &w, NULL); - /* If it's gotten way too small, it means we have an issue. */ - fail_if(w < 100); - - w = evas_object_text_horiz_advance_get(to); - fail_if(w < 100); - } + evas_object_geometry_get(to, NULL, NULL, NULL, &h); + evas_object_resize(to, 140, h); + + /* Force a resize. */ + evas_object_geometry_get(to, NULL, NULL, &w, NULL); + /* If it's gotten way too small, it means we have an issue. */ + fail_if(w < 100); + + w = evas_object_text_horiz_advance_get(to); + fail_if(w < 100); } START_TEST(evas_text_ellipsis) @@ -225,6 +248,18 @@ START_TEST(evas_text_ellipsis) buf = "Fffffffffffffffffffffffffffffffffff"; _test_ellipsis(to, buf, font, size, 0.0); + /* Obviously, adv > width case */ + buf = "This is a test for adv > width case. こんにちは。"; + _test_ellipsis(to, buf, font, size, 0.0); + _test_ellipsis(to, buf, font, size, 0.5); + _test_ellipsis(to, buf, font, size, 1.0); + + /* Obviously, adv < width case */ + buf = "This is a test for adv < width case. ନୂଁ"; + _test_ellipsis(to, buf, font, size, 0.0); + _test_ellipsis(to, buf, font, size, 0.5); + _test_ellipsis(to, buf, font, size, 1.0); + /* Check ellipsis value with NULL */ fail_if(evas_object_text_ellipsis_get(NULL) != -1.0); --