From 4adde89bc6dc72843859ed7677262ad744ba9a44 Mon Sep 17 00:00:00 2001 From: Youngbok Shin Date: Mon, 10 Apr 2017 12:15:19 +0900 Subject: [PATCH] evas: give width offset when Evas tries to find ellipsis position Summary: If the last item before ellipsis item has bigger width than its advance, evas_common_font_query_last_up_to_pos() function can find wrong ellipsis position. When Evas finds a position for non last item, Evas must care about additionally available space for glyph's width of the given x position. ex) the last item's glyph before ellipsis item has a tail to draw above the ellipsis item. @fix Test Plan: Test case will added as comment. (Becasue of font license problem.) Reviewers: herdsman, raster, jpeg, woohyun Subscribers: cedric, Blackmole Differential Revision: https://phab.enlightenment.org/D4727 Change-Id: Ie6dbec6c3dcc98ff0919d88e40969d0551dd898e --- src/lib/evas/canvas/evas_object_text.c | 8 ++++---- src/lib/evas/canvas/evas_object_textblock.c | 22 +++++++++++----------- src/lib/evas/common/evas_font.h | 2 +- src/lib/evas/common/evas_font_query.c | 12 ++++++++++-- src/lib/evas/include/evas_private.h | 2 +- .../evas/engines/software_generic/evas_engine.c | 4 ++-- 6 files changed, 29 insertions(+), 21 deletions(-) diff --git a/src/lib/evas/canvas/evas_object_text.c b/src/lib/evas/canvas/evas_object_text.c index 052eb15..e79ea4c 100644 --- a/src/lib/evas/canvas/evas_object_text.c +++ b/src/lib/evas/canvas/evas_object_text.c @@ -312,7 +312,7 @@ _evas_object_text_last_up_to_pos(const Evas_Object *eo_obj, o->font, &it->text_props, cx - x, - cy); + cy, 0); } x += it->adv; } @@ -329,7 +329,7 @@ _evas_object_text_last_up_to_pos(const Evas_Object *eo_obj, o->font, &it->text_props, cx - it->x, - cy); + cy, 0); } } } @@ -948,7 +948,7 @@ _evas_object_text_layout(Evas_Object *eo_obj, Evas_Text_Data *o, Eina_Unicode *t o->font, &itr->text_props, ellipsis_coord - (advance + l + r), - 0); + 0, start_ellip_it->w); if (cut >= 0) { start_ellip_it->text_pos = itr->text_pos; @@ -1007,7 +1007,7 @@ _evas_object_text_layout(Evas_Object *eo_obj, Evas_Text_Data *o, Eina_Unicode *t o->font, &itr->text_props, ellip_frame - (advance + l + r), - 0); + 0, end_ellip_it->w); if (cut >= 0) { end_ellip_it->text_pos = itr->text_pos + cut; diff --git a/src/lib/evas/canvas/evas_object_textblock.c b/src/lib/evas/canvas/evas_object_textblock.c index 81840cc2..66a4f19 100644 --- a/src/lib/evas/canvas/evas_object_textblock.c +++ b/src/lib/evas/canvas/evas_object_textblock.c @@ -3787,7 +3787,7 @@ _layout_text_item_new(Ctxt *c EINA_UNUSED, Evas_Object_Textblock_Format *fmt) */ static int _layout_text_cutoff_get(Ctxt *c, Evas_Object_Textblock_Format *fmt, - const Evas_Object_Textblock_Text_Item *ti) + const Evas_Object_Textblock_Text_Item *ti, int width_offset) { if (fmt->font.font) { @@ -3798,7 +3798,7 @@ _layout_text_cutoff_get(Ctxt *c, Evas_Object_Textblock_Format *fmt, x = 0; Evas_Object_Protected_Data *obj = eo_data_scope_get(c->obj, EVAS_OBJECT_CLASS); return ENFN->font_last_up_to_pos(ENDT, fmt->font.font, - &ti->text_props, x, 0); + &ti->text_props, x, 0, width_offset); } return -1; } @@ -4498,7 +4498,7 @@ _layout_get_charwrap(Ctxt *c, Evas_Object_Textblock_Format *fmt, if (it->type == EVAS_TEXTBLOCK_ITEM_FORMAT) wrap = 0; else - wrap = _layout_text_cutoff_get(c, fmt, _ITEM_TEXT(it)); + wrap = _layout_text_cutoff_get(c, fmt, _ITEM_TEXT(it), 0); if (wrap < 0) return -1; @@ -4559,13 +4559,13 @@ _layout_get_hyphenationwrap(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Coord cw; /* Get cutoff */ - swrap = _layout_text_cutoff_get(c, fmt, _ITEM_TEXT(it)); + swrap = _layout_text_cutoff_get(c, fmt, _ITEM_TEXT(it), 0); /* Get cutoff considering an additional hyphen item */ cw = c->w; c->hyphen_ti = _layout_hyphen_item_new(c, _ITEM_TEXT(it)); c->w -= c->hyphen_ti->parent.w; - hyphen_swrap = _layout_text_cutoff_get(c, fmt, _ITEM_TEXT(it)); + hyphen_swrap = _layout_text_cutoff_get(c, fmt, _ITEM_TEXT(it), c->hyphen_ti->parent.w); c->w = cw; /* Stronger condition than '< 0' for hyphenations */ @@ -4716,7 +4716,7 @@ _layout_get_word_mixwrap_common(Ctxt *c, Evas_Object_Textblock_Format *fmt, if (it->type == EVAS_TEXTBLOCK_ITEM_FORMAT) swrap = 0; else - swrap = _layout_text_cutoff_get(c, fmt, _ITEM_TEXT(it)); + swrap = _layout_text_cutoff_get(c, fmt, _ITEM_TEXT(it), 0); /* Avoiding too small textblocks to even contain one char. * FIXME: This can cause breaking inside ligatures. */ @@ -4915,7 +4915,7 @@ _layout_handle_ellipsis(Ctxt *c, Evas_Object_Textblock_Item *it, Eina_List *i) { ti = _ITEM_TEXT(last_it); - wrap = _layout_text_cutoff_get(c, last_it->format, ti); + wrap = _layout_text_cutoff_get(c, last_it->format, ti, ellip_ti->parent.w); if ((wrap > 0) && !IS_AT_END(ti, (size_t) wrap)) { @@ -5053,7 +5053,7 @@ _calc_items_width(Ctxt *c) } static inline int -_item_get_cutoff(Ctxt *c, Evas_Object_Textblock_Item *it, Evas_Coord x) +_item_get_cutoff(Ctxt *c, Evas_Object_Textblock_Item *it, Evas_Coord x, Evas_Coord width_offset) { int pos = -1; Evas_Object_Textblock_Text_Item *ti; @@ -5063,7 +5063,7 @@ _item_get_cutoff(Ctxt *c, Evas_Object_Textblock_Item *it, Evas_Coord x) if (ti && ti->parent.format->font.font) { pos = ENFN->font_last_up_to_pos(ENDT, ti->parent.format->font.font, - &ti->text_props, x, 0); + &ti->text_props, x, 0, width_offset); } return pos; } @@ -5130,7 +5130,7 @@ _layout_par_ellipsis_items(Ctxt *c, double ellip) pos = (it && it->type == EVAS_TEXTBLOCK_ITEM_TEXT) ? - (_item_get_cutoff(c, it, l - off)) : -1; + (_item_get_cutoff(c, it, l - off, ellip_ti->parent.w)) : -1; if (pos >= 0) { _layout_item_text_split_strip_white(c, _ITEM_TEXT(it), i, pos); @@ -5151,7 +5151,7 @@ _layout_par_ellipsis_items(Ctxt *c, double ellip) } pos = (it && it->type == EVAS_TEXTBLOCK_ITEM_TEXT) ? - (_item_get_cutoff(c, it, h - off)) : -1; + (_item_get_cutoff(c, it, h - off, 0)) : -1; if (pos >= 0) _layout_item_text_split_strip_white(c, _ITEM_TEXT(it), j, pos + 1); if (it) diff --git a/src/lib/evas/common/evas_font.h b/src/lib/evas/common/evas_font.h index 5017262..8c92c6c 100644 --- a/src/lib/evas/common/evas_font.h +++ b/src/lib/evas/common/evas_font.h @@ -79,7 +79,7 @@ EAPI void evas_common_font_query_advance (RGBA_Font *fn, con EAPI int evas_common_font_query_char_coords (RGBA_Font *fn, const Evas_Text_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch); EAPI int evas_common_font_query_pen_coords (RGBA_Font *fn, const Evas_Text_Props *intl_props, int pos, int *cpen_x, int *cy, int *cadv, int *ch); EAPI int evas_common_font_query_char_at_coords (RGBA_Font *fn, const Evas_Text_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch); -EAPI int evas_common_font_query_last_up_to_pos (RGBA_Font *fn, const Evas_Text_Props *intl_props, int x, int y); +EAPI int evas_common_font_query_last_up_to_pos (RGBA_Font *fn, const Evas_Text_Props *intl_props, int x, int y, int width_offset); EAPI int evas_common_font_query_run_font_end_get(RGBA_Font *fn, RGBA_Font_Int **script_fi, RGBA_Font_Int **cur_fi, Evas_Script_Type script, const Eina_Unicode *text, int run_len); EAPI void evas_common_font_ascent_descent_get(RGBA_Font *fn, const Evas_Text_Props *text_props, int *ascent, int *descent); diff --git a/src/lib/evas/common/evas_font_query.c b/src/lib/evas/common/evas_font_query.c index 2deb838..c52486b 100644 --- a/src/lib/evas/common/evas_font_query.c +++ b/src/lib/evas/common/evas_font_query.c @@ -813,7 +813,7 @@ end: * @return the position found, -1 on failure. */ EAPI int -evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const Evas_Text_Props *text_props, int x, int y) +evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const Evas_Text_Props *text_props, int x, int y, int width_offset) { int asc, desc; int ret=-1; @@ -845,6 +845,14 @@ evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const Evas_Text_Props *text pen_x = full_adv - (gli->pen_after - start_pen); /* If invisible, skip */ if (gli->index == 0) continue; + + /* FIXME: Should we care glyph's width for RTL? + I think if width+x_bear/advance stacked from left side, + we don't need to care glyph's width to find linebreak position + or ellipsis position. + Even if (x < (pen_x + gli->x_bear + gli->width)))) is removed, + the whole test suite is passed. + */ if ((x >= pen_x) && (((i == 0) && (x <= full_adv)) || (x < (full_adv - (gli[-1].pen_after - start_pen)) || @@ -875,7 +883,7 @@ evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const Evas_Text_Props *text if ((x >= EVAS_FONT_WALK_PEN_X) && ((x < (EVAS_FONT_WALK_PEN_X_AFTER)) || - (x < (EVAS_FONT_WALK_PEN_X + + (x + width_offset < (EVAS_FONT_WALK_PEN_X + _glyph_itr->x_bear + _glyph_itr->width))) && (y >= -asc) && (y <= desc)) { diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index 5c7dcea..053ab2f 100755 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -1388,7 +1388,7 @@ struct _Evas_Func void (*image_scale_hint_set) (void *data, void *image, int hint); int (*image_scale_hint_get) (void *data, void *image); - int (*font_last_up_to_pos) (void *data, Evas_Font_Set *font, const Evas_Text_Props *intl_props, int x, int y); + int (*font_last_up_to_pos) (void *data, Evas_Font_Set *font, const Evas_Text_Props *intl_props, int x, int y, int width_offset); Eina_Bool (*image_map_draw) (void *data, void *context, void *surface, void *image, RGBA_Map *m, int smooth, int level, Eina_Bool do_async); void *(*image_map_surface_new) (void *data, int w, int h, int alpha); diff --git a/src/modules/evas/engines/software_generic/evas_engine.c b/src/modules/evas/engines/software_generic/evas_engine.c index 7a72f4c..c8ad700 100644 --- a/src/modules/evas/engines/software_generic/evas_engine.c +++ b/src/modules/evas/engines/software_generic/evas_engine.c @@ -2717,9 +2717,9 @@ eng_font_char_at_coords_get(void *data EINA_UNUSED, Evas_Font_Set *font, const E } static int -eng_font_last_up_to_pos(void *data EINA_UNUSED, Evas_Font_Set *font, const Evas_Text_Props *text_props, int x, int y) +eng_font_last_up_to_pos(void *data EINA_UNUSED, Evas_Font_Set *font, const Evas_Text_Props *text_props, int x, int y, int width_offset) { - return evas_common_font_query_last_up_to_pos((RGBA_Font *) font, text_props, x, y); + return evas_common_font_query_last_up_to_pos((RGBA_Font *) font, text_props, x, y, width_offset); } static int -- 2.7.4