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
This commit is contained in:
Youngbok Shin 2015-12-09 09:50:33 +02:00 committed by Daniel Hirt
parent b6ead19a94
commit 20ef85e307
2 changed files with 69 additions and 25 deletions

View File

@ -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);

View File

@ -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);
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);
/* 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);
}
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);