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
This commit is contained in:
Ali Alzyod 2021-05-23 19:54:20 +01:00 committed by Carsten Haitzler (Rasterman)
parent 47b0fc1384
commit a129ea3bc0
2 changed files with 90 additions and 22 deletions

View File

@ -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*/

View File

@ -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 = "<font_size=20>AAAA</font_size>";
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 = "AAAAA<font_size=20>AAAA</font_size>";
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;