From a129ea3bc0e9e2c39c3282ac5d2183827bdb6a07 Mon Sep 17 00:00:00 2001 From: ali-alzyod Date: Sun, 23 May 2021 19:54:20 +0100 Subject: [PATCH] TextBlock: Fix content Fit with Markup-font-size Summary: This patch fixes wrong behavior for text block content fit when markup contains a part with specified font sizes (these parts will not be fitted by content fit algorithm). + THIS STILL NEED TEST TO BE ADDED Subscribers: raster, cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12275 --- src/lib/evas/canvas/evas_object_textblock.c | 95 ++++++++++++++++----- src/tests/evas/evas_test_textblock.c | 17 ++++ 2 files changed, 90 insertions(+), 22 deletions(-) diff --git a/src/lib/evas/canvas/evas_object_textblock.c b/src/lib/evas/canvas/evas_object_textblock.c index ff87db7be0..8f339fe5d2 100644 --- a/src/lib/evas/canvas/evas_object_textblock.c +++ b/src/lib/evas/canvas/evas_object_textblock.c @@ -17723,6 +17723,45 @@ Eina_Bool fit_is_fitting(const Evas_Object *eo_obj) return o->fit_in_progress; } +// Calculate text size for specific font size +// by appending styles at end of textblock style +void +get_text_size_for_font( Evas_Object *eo_obj, + size_t font_size, + TEXT_FIT_CONTENT_CONFIG * fc, + Evas_Coord *wf_new, //output + Evas_Coord *hf_new //output + ) +{ + Eina_Bool bwrap = EINA_FALSE; + if (fc->options == TEXTBLOCK_FIT_MODE_WIDTH) + { + bwrap = EINA_TRUE; + } + // We cache upto 255 font sizes, for fast text fit calculation + if (font_size <= 0xFF && (fc->size_cache[font_size].w != 0 && fc->size_cache[font_size].h != 0)) + { + *wf_new = fc->size_cache[font_size].w; + *hf_new = fc->size_cache[font_size].h; + } + else + { + int pad_l, pad_r, pad_t, pad_b; + + fit_style_update(eo_obj, font_size, EINA_TRUE, bwrap); + Eina_Size2D size = efl_canvas_textblock_size_formatted_get(eo_obj); + efl_canvas_textblock_style_insets_get(eo_obj, &pad_l, &pad_r, &pad_t, &pad_b); + *wf_new = size.w + pad_l + pad_r; + *hf_new = size.h + pad_t + pad_b; + if (font_size < 255) + { + // cache these values + fc->size_cache[font_size].w = *wf_new; + fc->size_cache[font_size].h = *hf_new; + } + } +} + int fit_text_block(Evas_Object *eo_obj) { EINA_SAFETY_ON_NULL_RETURN_VAL(eo_obj, EVAS_ERROR_INVALID_PARAM); @@ -17783,38 +17822,47 @@ int fit_text_block(Evas_Object *eo_obj) int r = fc->size_list_length; int l = 0; - Eina_Bool bwrap = EINA_FALSE; - if (fc->options == TEXTBLOCK_FIT_MODE_WIDTH) - { - bwrap = EINA_TRUE; - } + // These values used to test if size is not changing + // due markup specified fonts + int prev_height = 0; + int prev_font_index = 0; + Eina_Bool finished = EINA_FALSE; + while(r > l) { int mid = (r + l) / 2; - /*cache font sizes vaules from 0-255 in size_cache array*/ + /*get fontsize from p_size_array array*/ size_t font_size = fc->p_size_array[mid]; - if (font_size <= 0xFF && (fc->size_cache[font_size].w != 0 && fc->size_cache[font_size].h != 0)) - { - wf_new = fc->size_cache[font_size].w; - hf_new = fc->size_cache[font_size].h; - } - else - { - int pad_l, pad_r, pad_t, pad_b; + get_text_size_for_font(eo_obj, font_size, fc, &wf_new, &hf_new); - fit_style_update(eo_obj,fc->p_size_array[mid],EINA_TRUE,bwrap); - Eina_Size2D size = efl_canvas_textblock_size_formatted_get(eo_obj); - efl_canvas_textblock_style_insets_get(eo_obj, &pad_l, &pad_r, &pad_t, &pad_b); - wf_new = size.w + pad_l + pad_r; - hf_new = size.h + pad_t + pad_b; - if (fc->p_size_array[mid]<255) + //Special handle for height does not change(markup has fixed sizes) + if((hf_new == prev_height) & ((fc->options & TEXTBLOCK_FIT_MODE_HEIGHT) == TEXTBLOCK_FIT_MODE_HEIGHT)) + { + unsigned int start_index = prev_font_index; + size_t font_size = (start_index < fc->size_list_length - 1) ? fc->p_size_array[start_index] : 0xFF; + while ((start_index < fc->size_list_length - 1) && // still valid font index + (font_size < 0xff) && // still cache-able font size + ((fc->size_cache[font_size].h == prev_height) || fc->size_cache[font_size].h == 0)) + /*text height is the same, or not calculated yet*/ { - fc->size_cache[font_size].w = wf_new; - fc->size_cache[font_size].h = hf_new; + if(fc->size_cache[font_size].h == 0) + { + get_text_size_for_font(eo_obj, font_size, fc, &wf_new, &hf_new); + if(hf_new != prev_height) + { + break; + } + } + start_index++; + l = start_index; + font_size = (start_index < fc->size_list_length - 1) ? fc->p_size_array[start_index] : 0xFF; } + finished = EINA_TRUE; } + if (finished) break; + if ( ((wf_new > w) & ((fc->options & TEXTBLOCK_FIT_MODE_WIDTH) == TEXTBLOCK_FIT_MODE_WIDTH)) || ((hf_new > h) & ((fc->options & TEXTBLOCK_FIT_MODE_HEIGHT) == TEXTBLOCK_FIT_MODE_HEIGHT))) @@ -17825,6 +17873,9 @@ int fit_text_block(Evas_Object *eo_obj) { l = mid + 1; } + + prev_height = hf_new; + prev_font_index = mid; } /*Lower bound founded, subtract one to move for nearest value*/ diff --git a/src/tests/evas/evas_test_textblock.c b/src/tests/evas/evas_test_textblock.c index 40dbb70967..eb6d5b8538 100644 --- a/src/tests/evas/evas_test_textblock.c +++ b/src/tests/evas/evas_test_textblock.c @@ -4243,6 +4243,23 @@ EFL_START_TEST(evas_textblock_fit) fail_if(n_ret != EVAS_ERROR_SUCCESS); evas_object_textblock_size_formatted_get(tb, &fw, &fh); fail_if(fw_new == fw && fh_new == fh); + + const char *buf1 = "AAAA"; + evas_object_textblock_text_markup_set(tb, buf1); + evas_object_resize(tb, 300, 4); + n_ret = evas_textblock_fit_options_set(tb,TEXTBLOCK_FIT_MODE_ALL); + fail_if(n_ret != EVAS_ERROR_SUCCESS); + n_ret = evas_textblock_fit_size_range_set(tb,1,255); + fail_if(n_ret != EVAS_ERROR_SUCCESS); + evas_object_textblock_size_formatted_get(tb, &fw, &fh); + + + const char *buf2 = "AAAAAAAAA"; + evas_object_textblock_text_markup_set(tb, buf2); + evas_object_resize(tb, 300, 4); + evas_object_textblock_size_formatted_get(tb, &fw_new, &fh_new); + fail_if(fw_new < (fw * 2)); + END_TB_TEST(); } EFL_END_TEST;