summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAli Alzyod <ali198724@gmail.com>2019-12-12 14:22:45 +0900
committerWooHyun Jung <wh0705.jung@samsung.com>2019-12-12 14:22:46 +0900
commit8f87a2411a674fe985e76ef62bdcc555c535ce06 (patch)
treeff922a7c3498103bfc50e7f6aae3fdfd40681449
parent8fabc422b6565be81b94b802f0a8d3eff737e633 (diff)
evas_textblock: content fit feature
Summary: **Content Fit Feature for Evas_Object_Textblock** This Feature is available at **Evas **object level. And **Edje **level (where it is internally use evas functionality) This feature will allow text block to fit its content font size to proper size to fit its area. **Main Properties:** Fit Modes : None=Default, Width, Height, All [Width+Height] Fit Size Range : Contains maximum and minimum font size to be used (and in between). Fit Step Size : Step(Jump) value when trying fonts sizes between Size_Range max and min. Fit Size Array : Other way to resize font, where you explicitly select font sizes to be uses (for example [20, 50, 100] it will try 3 sizes only) Text Fit feature was available in Edje but: 1- It doesn't effected by ellipsis or warping in font style (or do not handle the in right way) 2- Accuracy is not good (specially if you have fix pixel size elements (spaces,tabs,items)) 3- No (Step size, Size Array) available. Test Plan: To check the Feature > elementary_test > fit > textbock fit You can modify all the modes and properties These are two examples, One using Evas other uses Edje **Evas** ``` #include <Elementary.h> enum BUTTON{ BUTTON_MODE = 0, BUTTON_MAX = 1, BUTTON_MIN = 2, BUTTON_STEP = 3, BUTTON_ARRAY = 4, BUTTON_CONTENT = 5, BUTTON_STYLE = 6, BUTTON_ALL = BUTTON_STYLE+1, }; char* BUTTON_STR[BUTTON_ALL] ={ "MODE", "MAX", "MIN", "STEP", "ARRAY", "CONTENT", "STYLE", }; char *contents[] = { "Hello World", "This is Line<br>THis is other Line", "This text contains <font_size=20 color=#F00>SPECIFIC SIZE</font_size> that does not effected by fit mode" }; char *styles[] = { "DEFAULT='font=sans font_size=30 color=#000 wrap=mixed ellipsis=1.0'", "DEFAULT='font=sans font_size=30 color=#000 wrap=mixed'", "DEFAULT='font=sans font_size=30 color=#000 ellipsis=1.0'", "DEFAULT='font=sans font_size=30 color=#000'", }; char *styles_names[] = { "wrap=<color=#F00>mixed</color> ellipsis=<color=#F00>1.0</color>", "wrap=<color=#F00>mixed</color> ellipsis=<color=#F00>NONE</color>", "wrap=<color=#F00>NONE</color> ellipsis=<color=#F00>1.0</color>", "wrap=<color=#F00>NONE</color> ellipsis=<color=#F00>NONE</color>", }; typedef struct _APP { Evas_Object *win, *box, *txtblock,*bg, *boxHor, *boxHor2; Eo *btn[BUTTON_ALL]; Eo *lbl_status; char * str; unsigned int i_contnet, i_style; } APP; APP *app; char * get_fit_status(Eo * textblock); static void _btn_clicked(void *data EINA_UNUSED, Eo *obj, void *eventInfo EINA_UNUSED){ if (obj == app->btn[BUTTON_MODE]) { unsigned int options; evas_textblock_fit_options_get(app->txtblock, &options); if (options == TEXTBLOCK_FIT_MODE_NONE) evas_textblock_fit_options_set(app->txtblock, TEXTBLOCK_FIT_MODE_HEIGHT); else if (options == TEXTBLOCK_FIT_MODE_HEIGHT) evas_textblock_fit_options_set(app->txtblock, TEXTBLOCK_FIT_MODE_WIDTH); else if (options == TEXTBLOCK_FIT_MODE_WIDTH) evas_textblock_fit_options_set(app->txtblock, TEXTBLOCK_FIT_MODE_ALL); else if (options == TEXTBLOCK_FIT_MODE_ALL) evas_textblock_fit_options_set(app->txtblock, TEXTBLOCK_FIT_MODE_NONE); } else if (obj == app->btn[BUTTON_MAX]) { unsigned int min, max; evas_textblock_fit_size_range_get(app->txtblock, &min, &max); max -= 5; evas_textblock_fit_size_range_set(app->txtblock, min, max); } else if (obj == app->btn[BUTTON_MIN]) { unsigned int min, max; evas_textblock_fit_size_range_get(app->txtblock, &min, &max); min += 5; evas_textblock_fit_size_range_set(app->txtblock, min, max); } else if (obj == app->btn[BUTTON_STEP]) { unsigned int step; evas_textblock_fit_step_size_get(app->txtblock, &step); step++; evas_textblock_fit_step_size_set(app->txtblock, step); } else if (obj == app->btn[BUTTON_ARRAY]) { unsigned int font_size[] = {10, 50, 100 ,150}; evas_textblock_fit_size_array_set(app->txtblock,font_size,4); } else if (obj == app->btn[BUTTON_CONTENT]) { app->i_contnet++; if(app->i_contnet>=sizeof(contents)/sizeof(char*)) app->i_contnet=0; evas_object_textblock_text_markup_set(app->txtblock,contents[app->i_contnet]); } else if (obj == app->btn[BUTTON_STYLE]) { app->i_style++; if(app->i_style>=sizeof(styles)/sizeof(char*)) app->i_style=0; Evas_Textblock_Style *style = evas_object_textblock_style_get(app->txtblock); evas_textblock_style_set(style,styles[app->i_style]); } elm_object_text_set(app->lbl_status, get_fit_status(app->txtblock)); } char * get_fit_status(Eo * textblock) { static char status[0xFFF]; unsigned int options,min,max,step,size_array[256]; size_t size_array_len; evas_textblock_fit_options_get(textblock,&options); evas_textblock_fit_size_range_get(textblock,&min,&max); evas_textblock_fit_step_size_get(textblock,&step); evas_textblock_fit_size_array_get(textblock,NULL,&size_array_len,0); if (size_array_len>255) size_array_len = 255; evas_textblock_fit_size_array_get(textblock,size_array,NULL,size_array_len); strcpy(status,"Mode : "); if (options == TEXTBLOCK_FIT_MODE_NONE) strcat(status,"MODE_NONE"); else if (options == TEXTBLOCK_FIT_MODE_HEIGHT) strcat(status,"MODE_HEIGHT"); else if (options == TEXTBLOCK_FIT_MODE_WIDTH) strcat(status,"MODE_WIDTH"); else if (options == TEXTBLOCK_FIT_MODE_ALL) strcat(status,"MODE_ALL"); strcat(status,"<br>"); sprintf(status + strlen(status),"Max : %d<br>",max); sprintf(status + strlen(status),"Min : %d<br>",min); sprintf(status + strlen(status),"Step : %d<br>",step); sprintf(status + strlen(status),"Array : [ "); for (size_t i = 0 ; i < 10 ; i++) { if(i<size_array_len) sprintf(status + strlen(status)," %d,",size_array[i]); } if(10<size_array_len) sprintf(status + strlen(status)," ... "); sprintf(status + strlen(status)," ]"); sprintf(status + strlen(status),"<br>"); sprintf(status + strlen(status),"%s",styles_names[app->i_style]); return status; } int elm_main(int argc, char **argv) { app = calloc(sizeof(APP), 1); elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED); app->win = elm_win_util_standard_add("Main", "App"); elm_win_autodel_set(app->win, EINA_TRUE); app->box = elm_box_add(app->win); app->boxHor = elm_box_add(app->box); app->boxHor2 = elm_box_add(app->box); app->txtblock = evas_object_textblock_add(app->box); app->bg = elm_bg_add(app->box); elm_bg_color_set(app->bg,255,255,255); Evas_Textblock_Style *style = evas_textblock_style_new(); evas_textblock_style_set(style,styles[0]); evas_object_textblock_style_set(app->txtblock,style); evas_object_textblock_text_markup_set(app->txtblock,contents[0]); elm_box_horizontal_set(app->boxHor, EINA_TRUE); elm_box_horizontal_set(app->boxHor2, EINA_TRUE); evas_object_size_hint_weight_set(app->box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(app->box, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_weight_set(app->box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(app->box, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_show(app->txtblock); evas_object_show(app->bg); evas_object_show(app->box); evas_object_show(app->boxHor); evas_object_show(app->boxHor2); elm_box_pack_end(app->box, app->bg); elm_box_pack_end(app->box, app->boxHor); elm_box_pack_end(app->box, app->boxHor2); elm_object_content_set(app->bg,app->txtblock); elm_win_resize_object_add(app->win, app->box); evas_object_resize(app->win, 320, 480); for(int i = 0 ; i < BUTTON_ALL ; i++) { app->btn[i] = elm_button_add(app->boxHor); evas_object_smart_callback_add(app->btn[i], "clicked", _btn_clicked, NULL); elm_object_text_set(app->btn[i], BUTTON_STR[i]); elm_box_pack_end(app->boxHor, app->btn[i]); evas_object_show(app->btn[i]); } app->lbl_status = elm_label_add(app->boxHor2); elm_object_text_set(app->lbl_status, get_fit_status(app->txtblock)); elm_box_pack_end(app->boxHor2, app->lbl_status); evas_object_show(app->lbl_status); evas_object_size_hint_weight_set(app->txtblock, EVAS_HINT_EXPAND,EVAS_HINT_EXPAND); evas_object_size_hint_align_set(app->txtblock, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_weight_set(app->bg, EVAS_HINT_EXPAND,EVAS_HINT_EXPAND); evas_object_size_hint_align_set(app->bg, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_show(app->win); elm_run(); return 0; } ELM_MAIN() ``` **Edje** ``` // compile: edje_cc source.edc // run: edje_player source.edje collections { styles { style { name: "text_style"; base: "font=sans font_size=30 color=#FFF wrap=mixed ellipsis=1.0"; tag: "br" "\n"; tag: "ps" "ps"; tag: "tab" "\t"; tag: "b" "+ font_weight=Bold"; } } group { name: "my_group"; // must be the same as in source.c parts { part { name: "background"; type: RECT; scale: 1; description { color: 0 0 0 0; rel1.relative: 0.0 0.0; rel2.relative: 1.0 1.0; } } part { name: "text"; type: TEXTBLOCK; scale: 1; entry_mode: NONE; effect: OUTLINE_SHADOW; description { state: "default" 0.0; rel1.to : "background"; rel1.relative: 0.0 0.0; rel2.to : "background"; rel2.relative: 1.0 1.0; text { style: "text_style"; align: 0.0 0.0; text: "Hello World This is Me"; fit: 1 1; fit_step: 1; size_range: 30 200; //fit_size_array: 20 40 60 80 100 200; } } } } } } ``` Found Task T5724 relative to this Feature Reviewers: woohyun, bowonryu, cedric, raster Reviewed By: woohyun Subscribers: a.srour, #committers, #reviewers, cedric Tags: #efl Differential Revision: https://phab.enlightenment.org/D9280
-rw-r--r--src/bin/edje/edje_cc_handlers.c81
-rw-r--r--src/bin/elementary/test.c2
-rw-r--r--src/bin/elementary/test_label.c232
-rw-r--r--src/lib/edje/edje_data.c2
-rw-r--r--src/lib/edje/edje_private.h3
-rw-r--r--src/lib/edje/edje_textblock.c103
-rw-r--r--src/lib/eet/Eet.h23
-rw-r--r--src/lib/evas/canvas/evas_object_textblock.c496
-rw-r--r--src/lib/evas/canvas/evas_textblock_legacy.h100
-rw-r--r--src/tests/evas/evas_test_textblock.c27
10 files changed, 979 insertions, 90 deletions
diff --git a/src/bin/edje/edje_cc_handlers.c b/src/bin/edje/edje_cc_handlers.c
index c9bbc17..8353d26 100644
--- a/src/bin/edje/edje_cc_handlers.c
+++ b/src/bin/edje/edje_cc_handlers.c
@@ -419,6 +419,8 @@ static void st_collections_group_parts_part_description_text_repch(void);
419static void st_collections_group_parts_part_description_text_size(void); 419static void st_collections_group_parts_part_description_text_size(void);
420static void st_collections_group_parts_part_description_text_size_range(void); 420static void st_collections_group_parts_part_description_text_size_range(void);
421static void st_collections_group_parts_part_description_text_fit(void); 421static void st_collections_group_parts_part_description_text_fit(void);
422static void st_collections_group_parts_part_description_text_fit_step(void);
423static void st_collections_group_parts_part_description_text_fit_size_array(void);
422static void st_collections_group_parts_part_description_text_min(void); 424static void st_collections_group_parts_part_description_text_min(void);
423static void st_collections_group_parts_part_description_text_max(void); 425static void st_collections_group_parts_part_description_text_max(void);
424static void st_collections_group_parts_part_description_text_align(void); 426static void st_collections_group_parts_part_description_text_align(void);
@@ -952,6 +954,8 @@ New_Statement_Handler statement_handlers[] =
952 {"collections.group.parts.part.description.text.size", st_collections_group_parts_part_description_text_size}, 954 {"collections.group.parts.part.description.text.size", st_collections_group_parts_part_description_text_size},
953 {"collections.group.parts.part.description.text.size_range", st_collections_group_parts_part_description_text_size_range}, 955 {"collections.group.parts.part.description.text.size_range", st_collections_group_parts_part_description_text_size_range},
954 {"collections.group.parts.part.description.text.fit", st_collections_group_parts_part_description_text_fit}, 956 {"collections.group.parts.part.description.text.fit", st_collections_group_parts_part_description_text_fit},
957 {"collections.group.parts.part.description.text.fit_step", st_collections_group_parts_part_description_text_fit_step},
958 {"collections.group.parts.part.description.text.fit_size_array", st_collections_group_parts_part_description_text_fit_size_array},
955 {"collections.group.parts.part.description.text.min", st_collections_group_parts_part_description_text_min}, 959 {"collections.group.parts.part.description.text.min", st_collections_group_parts_part_description_text_min},
956 {"collections.group.parts.part.description.text.max", st_collections_group_parts_part_description_text_max}, 960 {"collections.group.parts.part.description.text.max", st_collections_group_parts_part_description_text_max},
957 {"collections.group.parts.part.description.text.align", st_collections_group_parts_part_description_text_align}, 961 {"collections.group.parts.part.description.text.align", st_collections_group_parts_part_description_text_align},
@@ -11654,6 +11658,83 @@ st_collections_group_parts_part_description_text_fit(void)
11654 ed->text.fit_y = parse_bool(1); 11658 ed->text.fit_y = parse_bool(1);
11655} 11659}
11656 11660
11661
11662/**
11663 @page edcref
11664
11665 @property
11666 fit_step
11667 @parameters
11668 [font step size in points (pt)]
11669 @effect
11670 Sets the font step size for the text part. when fitting text
11671
11672 Defaults: 1
11673 @since 1.24.0
11674 @endproperty
11675 */
11676static void
11677st_collections_group_parts_part_description_text_fit_step(void)
11678{
11679 Edje_Part_Description_Text *ed;
11680
11681 check_arg_count(1);
11682
11683 if (current_part->type != EDJE_PART_TYPE_TEXTBLOCK)
11684 {
11685 ERR("parse error %s:%i. text attributes in non-TEXTBLOCK part.",
11686 file_in, line - 1);
11687 exit(-1);
11688 }
11689
11690 ed = (Edje_Part_Description_Text *)current_desc;
11691
11692 ed->text.fit_step = parse_int(0);
11693
11694 if (ed->text.fit_step < 1)
11695 {
11696 ERR("parse error %s:%i. fit step less than 1.",
11697 file_in, line - 1);
11698 exit(-1);
11699 }
11700}
11701
11702/**
11703 @page edcref
11704
11705 @property
11706 fit
11707 @parameters
11708 [Array of font sizes in points]
11709 @effect
11710 Sets the allowed font sizes array for the text part.
11711 @since 1.24.0
11712 @endproperty
11713 */
11714static void
11715st_collections_group_parts_part_description_text_fit_size_array(void)
11716{
11717 int n, argc;
11718 Edje_Part_Description_Text *ed;
11719
11720 if (current_part->type != EDJE_PART_TYPE_TEXTBLOCK)
11721 {
11722 ERR("parse error %s:%i. text attributes in non-TEXTBLOCK part.",
11723 file_in, line - 1);
11724 exit(-1);
11725 }
11726
11727 ed = (Edje_Part_Description_Text *)current_desc;
11728 check_min_arg_count(1);
11729
11730 for (n = 0, argc = get_arg_count(); n < argc; n++)
11731 {
11732 unsigned int *value = malloc(sizeof(unsigned int));
11733 *value = (unsigned int) parse_int(n);
11734 ed->text.fit_size_array = eina_list_append(ed->text.fit_size_array, value);
11735 }
11736}
11737
11657/** 11738/**
11658 @page edcref 11739 @page edcref
11659 11740
diff --git a/src/bin/elementary/test.c b/src/bin/elementary/test.c
index cab1923..966d164 100644
--- a/src/bin/elementary/test.c
+++ b/src/bin/elementary/test.c
@@ -240,6 +240,7 @@ void test_flip_page_eo(void *data, Evas_Object *obj, void *event_info);
240void test_label(void *data, Evas_Object *obj, void *event_info); 240void test_label(void *data, Evas_Object *obj, void *event_info);
241void test_label_slide(void *data, Evas_Object *obj, void *event_info); 241void test_label_slide(void *data, Evas_Object *obj, void *event_info);
242void test_label_wrap(void *data, Evas_Object *obj, void *event_info); 242void test_label_wrap(void *data, Evas_Object *obj, void *event_info);
243void test_textblock_fit(void *data, Evas_Object *obj, void *event_info);
243void test_label_ellipsis(void *data, Evas_Object *obj, void *event_info); 244void test_label_ellipsis(void *data, Evas_Object *obj, void *event_info);
244void test_label_colors(void *data, Evas_Object *obj, void *event_info); 245void test_label_colors(void *data, Evas_Object *obj, void *event_info);
245void test_label_emoji(void *data, Evas_Object *obj, void *event_info); 246void test_label_emoji(void *data, Evas_Object *obj, void *event_info);
@@ -1206,6 +1207,7 @@ add_tests:
1206 ADD_TEST(NULL, "Text", "Label", test_label); 1207 ADD_TEST(NULL, "Text", "Label", test_label);
1207 ADD_TEST(NULL, "Text", "Label Slide", test_label_slide); 1208 ADD_TEST(NULL, "Text", "Label Slide", test_label_slide);
1208 ADD_TEST(NULL, "Text", "Label Wrap", test_label_wrap); 1209 ADD_TEST(NULL, "Text", "Label Wrap", test_label_wrap);
1210 ADD_TEST(NULL, "Text", "Textblock Fit", test_textblock_fit);
1209 ADD_TEST(NULL, "Text", "Label Ellipsis", test_label_ellipsis); 1211 ADD_TEST(NULL, "Text", "Label Ellipsis", test_label_ellipsis);
1210 ADD_TEST(NULL, "Text", "Label Colors", test_label_colors); 1212 ADD_TEST(NULL, "Text", "Label Colors", test_label_colors);
1211 ADD_TEST(NULL, "Text", "Label Emoji", test_label_emoji); 1213 ADD_TEST(NULL, "Text", "Label Emoji", test_label_emoji);
diff --git a/src/bin/elementary/test_label.c b/src/bin/elementary/test_label.c
index 233ce01..929d06b 100644
--- a/src/bin/elementary/test_label.c
+++ b/src/bin/elementary/test_label.c
@@ -309,6 +309,238 @@ test_label_slide(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *eve
309 evas_object_show(win); 309 evas_object_show(win);
310} 310}
311 311
312
313
314/*** FIT TEXT **************************************************************/
315enum BUTTON{
316 BUTTON_MODE = 0,
317 BUTTON_MAX = 1,
318 BUTTON_MIN = 2,
319 BUTTON_STEP = 3,
320 BUTTON_ARRAY = 4,
321 BUTTON_CONTENT = 5,
322 BUTTON_STYLE = 6,
323 BUTTON_ALL = BUTTON_STYLE+1,
324};
325
326char* BUTTON_STR[BUTTON_ALL] ={
327 "MODE",
328 "MAX",
329 "MIN",
330 "STEP",
331 "ARRAY",
332 "CONTENT",
333 "STYLE",
334};
335
336char *contents[] = {
337 "Hello World",
338 "This is Line<br>THis is other Line",
339 "This text contains <font_size=20 color=#F00>SPECIFIC SIZE</font_size>that does not effected by fit mode"
340 };
341
342char *styles[] = {
343 "DEFAULT='font=sans font_size=30 color=#000 wrap=mixed ellipsis=1.0'",
344 "DEFAULT='font=sans font_size=30 color=#000 wrap=mixed'",
345 "DEFAULT='font=sans font_size=30 color=#000 ellipsis=1.0'",
346 "DEFAULT='font=sans font_size=30 color=#000'",
347 };
348
349char *styles_names[] = {
350 "wrap=<color=#F00>mixed</color> ellipsis=<color=#F00>1.0</color>",
351 "wrap=<color=#F00>mixed</color> ellipsis=<color=#F00>NONE</color>",
352 "wrap=<color=#F00>NONE</color> ellipsis=<color=#F00>1.0</color>",
353 "wrap=<color=#F00>NONE</color> ellipsis=<color=#F00>NONE</color>",
354 };
355
356typedef struct _APP
357{
358 Evas_Object *win, *box, *txtblock,*bg, *boxHor, *boxHor2;
359 Eo *btn[BUTTON_ALL];
360 Eo *lbl_status;
361 char * str;
362 unsigned int i_contnet, i_style;
363} APP;
364APP *app;
365
366char * get_fit_status(Eo * textblock);
367
368static void _btn_clicked(void *data EINA_UNUSED, Eo *obj, void *eventInfo EINA_UNUSED){
369 if (obj == app->btn[BUTTON_MODE])
370 {
371 unsigned int options;
372 evas_textblock_fit_options_get(app->txtblock, &options);
373 if (options == TEXTBLOCK_FIT_MODE_NONE)
374 evas_textblock_fit_options_set(app->txtblock, TEXTBLOCK_FIT_MODE_HEIGHT);
375 else if (options == TEXTBLOCK_FIT_MODE_HEIGHT)
376 evas_textblock_fit_options_set(app->txtblock, TEXTBLOCK_FIT_MODE_WIDTH);
377 else if (options == TEXTBLOCK_FIT_MODE_WIDTH)
378 evas_textblock_fit_options_set(app->txtblock, TEXTBLOCK_FIT_MODE_ALL);
379 else if (options == TEXTBLOCK_FIT_MODE_ALL)
380 evas_textblock_fit_options_set(app->txtblock, TEXTBLOCK_FIT_MODE_NONE);
381 }
382 else if (obj == app->btn[BUTTON_MAX])
383 {
384 unsigned int min, max;
385 evas_textblock_fit_size_range_get(app->txtblock, &min, &max);
386 max -= 5;
387 evas_textblock_fit_size_range_set(app->txtblock, min, max);
388 }
389 else if (obj == app->btn[BUTTON_MIN])
390 {
391 unsigned int min, max;
392 evas_textblock_fit_size_range_get(app->txtblock, &min, &max);
393 min += 5;
394 evas_textblock_fit_size_range_set(app->txtblock, min, max);
395 }
396 else if (obj == app->btn[BUTTON_STEP])
397 {
398 unsigned int step;
399 evas_textblock_fit_step_size_get(app->txtblock, &step);
400 step++;
401 evas_textblock_fit_step_size_set(app->txtblock, step);
402 }
403 else if (obj == app->btn[BUTTON_ARRAY])
404 {
405 unsigned int font_size[] = {10, 50, 100 ,150};
406 evas_textblock_fit_size_array_set(app->txtblock,font_size,4);
407 }
408 else if (obj == app->btn[BUTTON_CONTENT])
409 {
410 app->i_contnet++;
411 if(app->i_contnet>=sizeof(contents)/sizeof(char*))
412 app->i_contnet=0;
413 evas_object_textblock_text_markup_set(app->txtblock,contents[app->i_contnet]);
414 }
415 else if (obj == app->btn[BUTTON_STYLE])
416 {
417 app->i_style++;
418 if(app->i_style>=sizeof(styles)/sizeof(char*))
419 app->i_style=0;
420
421 Evas_Textblock_Style *style = evas_object_textblock_style_get(app->txtblock);
422 evas_textblock_style_set(style,styles[app->i_style]);
423 }
424
425 elm_object_text_set(app->lbl_status, get_fit_status(app->txtblock));
426}
427
428char * get_fit_status(Eo * textblock)
429{
430 static char status[0xFFF];
431 unsigned int options,min,max,step,size_array[256];
432 size_t size_array_len;
433 evas_textblock_fit_options_get(textblock,&options);
434 evas_textblock_fit_size_range_get(textblock,&min,&max);
435 evas_textblock_fit_step_size_get(textblock,&step);
436 evas_textblock_fit_size_array_get(textblock,NULL,&size_array_len,0);
437 if (size_array_len>255)
438 size_array_len = 255;
439 evas_textblock_fit_size_array_get(textblock,size_array,NULL,size_array_len);
440
441 strcpy(status,"Mode : ");
442 if (options == TEXTBLOCK_FIT_MODE_NONE)
443 strcat(status,"MODE_NONE");
444 else if (options == TEXTBLOCK_FIT_MODE_HEIGHT)
445 strcat(status,"MODE_HEIGHT");
446 else if (options == TEXTBLOCK_FIT_MODE_WIDTH)
447 strcat(status,"MODE_WIDTH");
448 else if (options == TEXTBLOCK_FIT_MODE_ALL)
449 strcat(status,"MODE_ALL");
450
451 strcat(status,"<br>");
452 sprintf(status + strlen(status),"Max : %d<br>",max);
453 sprintf(status + strlen(status),"Min : %d<br>",min);
454 sprintf(status + strlen(status),"Step : %d<br>",step);
455 sprintf(status + strlen(status),"Array : [ ");
456 for (size_t i = 0 ; i < 10 ; i++)
457 {
458 if(i<size_array_len)
459 sprintf(status + strlen(status)," %d,",size_array[i]);
460 }
461
462 if(10<size_array_len)
463 sprintf(status + strlen(status)," ... ");
464 sprintf(status + strlen(status)," ]");
465
466 sprintf(status + strlen(status),"<br>");
467 sprintf(status + strlen(status),"%s",styles_names[app->i_style]);
468
469
470
471 return status;
472}
473
474void
475test_textblock_fit(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
476{
477 app = calloc(sizeof(APP), 1);
478
479 elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
480
481 app->win = elm_win_util_standard_add("Main", "App");
482 elm_win_autodel_set(app->win, EINA_TRUE);
483
484 app->box = elm_box_add(app->win);
485 app->boxHor = elm_box_add(app->box);
486 app->boxHor2 = elm_box_add(app->box);
487 app->txtblock = evas_object_textblock_add(app->box);
488 app->bg = elm_bg_add(app->box);
489 elm_bg_color_set(app->bg,255,255,255);
490
491 Evas_Textblock_Style *style = evas_textblock_style_new();
492 evas_textblock_style_set(style,styles[0]);
493 evas_object_textblock_style_set(app->txtblock,style);
494 evas_object_textblock_text_markup_set(app->txtblock,contents[0]);
495
496 elm_box_horizontal_set(app->boxHor, EINA_TRUE);
497 elm_box_horizontal_set(app->boxHor2, EINA_TRUE);
498
499 evas_object_size_hint_weight_set(app->box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
500 evas_object_size_hint_align_set(app->box, EVAS_HINT_FILL, EVAS_HINT_FILL);
501
502
503 evas_object_size_hint_weight_set(app->box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
504 evas_object_size_hint_align_set(app->box, EVAS_HINT_FILL, EVAS_HINT_FILL);
505
506 evas_object_show(app->txtblock);
507 evas_object_show(app->bg);
508 evas_object_show(app->box);
509 evas_object_show(app->boxHor);
510 evas_object_show(app->boxHor2);
511
512 elm_box_pack_end(app->box, app->bg);
513 elm_box_pack_end(app->box, app->boxHor);
514 elm_box_pack_end(app->box, app->boxHor2);
515
516 elm_object_content_set(app->bg,app->txtblock);
517
518 elm_win_resize_object_add(app->win, app->box);
519 evas_object_resize(app->win, 320, 480);
520
521 for(int i = 0 ; i < BUTTON_ALL ; i++)
522 {
523 app->btn[i] = elm_button_add(app->boxHor);
524 evas_object_smart_callback_add(app->btn[i], "clicked", _btn_clicked, NULL);
525 elm_object_text_set(app->btn[i], BUTTON_STR[i]);
526 elm_box_pack_end(app->boxHor, app->btn[i]);
527 evas_object_show(app->btn[i]);
528 }
529
530 app->lbl_status = elm_label_add(app->boxHor2);
531 elm_object_text_set(app->lbl_status, get_fit_status(app->txtblock));
532 elm_box_pack_end(app->boxHor2, app->lbl_status);
533 evas_object_show(app->lbl_status);
534
535 evas_object_size_hint_weight_set(app->txtblock, EVAS_HINT_EXPAND,EVAS_HINT_EXPAND);
536 evas_object_size_hint_align_set(app->txtblock, EVAS_HINT_FILL, EVAS_HINT_FILL);
537
538 evas_object_size_hint_weight_set(app->bg, EVAS_HINT_EXPAND,EVAS_HINT_EXPAND);
539 evas_object_size_hint_align_set(app->bg, EVAS_HINT_FILL, EVAS_HINT_FILL);
540
541 evas_object_show(app->win);
542}
543
312/*** Label Wrap **************************************************************/ 544/*** Label Wrap **************************************************************/
313void 545void
314test_label_wrap(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) 546test_label_wrap(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
diff --git a/src/lib/edje/edje_data.c b/src/lib/edje/edje_data.c
index 08fdae4..ca9cbf1 100644
--- a/src/lib/edje/edje_data.c
+++ b/src/lib/edje/edje_data.c
@@ -1188,6 +1188,8 @@ _edje_edd_init(void)
1188 EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.size_range_max", text.size_range_max, EET_T_INT); 1188 EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.size_range_max", text.size_range_max, EET_T_INT);
1189 EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.fit_x", text.fit_x, EET_T_UCHAR); 1189 EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.fit_x", text.fit_x, EET_T_UCHAR);
1190 EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.fit_y", text.fit_y, EET_T_UCHAR); 1190 EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.fit_y", text.fit_y, EET_T_UCHAR);
1191 EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.fit_step", text.fit_step, EET_T_UINT);
1192 EET_DATA_DESCRIPTOR_ADD_LIST_UINT(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.fit_size_array", text.fit_size_array);
1191 EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.min_x", text.min_x, EET_T_UCHAR); 1193 EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.min_x", text.min_x, EET_T_UCHAR);
1192 EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.min_y", text.min_y, EET_T_UCHAR); 1194 EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.min_y", text.min_y, EET_T_UCHAR);
1193 EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.max_x", text.max_x, EET_T_UCHAR); 1195 EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.max_x", text.max_x, EET_T_UCHAR);
diff --git a/src/lib/edje/edje_private.h b/src/lib/edje/edje_private.h
index 33b07a2..c572d74 100644
--- a/src/lib/edje/edje_private.h
+++ b/src/lib/edje/edje_private.h
@@ -1460,6 +1460,9 @@ struct _Edje_Part_Description_Spec_Text
1460 int id_text_source; /* -1 if none */ 1460 int id_text_source; /* -1 if none */
1461 int size_range_min; 1461 int size_range_min;
1462 int size_range_max; /* -1 means, no bound. */ 1462 int size_range_max; /* -1 means, no bound. */
1463 unsigned int fit_step;
1464 /*FIXME THIS SHOULD BE EINA_LIST*/
1465 Eina_List *fit_size_array;
1463 1466
1464 unsigned char fit_x; /* resize font size down to fit in x dir */ 1467 unsigned char fit_x; /* resize font size down to fit in x dir */
1465 unsigned char fit_y; /* resize font size down to fit in y dir */ 1468 unsigned char fit_y; /* resize font size down to fit in y dir */
diff --git a/src/lib/edje/edje_textblock.c b/src/lib/edje/edje_textblock.c
index 76f3b2a..d0c5c6d 100644
--- a/src/lib/edje/edje_textblock.c
+++ b/src/lib/edje/edje_textblock.c
@@ -1,25 +1,5 @@
1#include "edje_private.h" 1#include "edje_private.h"
2 2
3static double
4_edje_part_recalc_single_textblock_scale_range_adjust(Edje_Part_Description_Text *chosen_desc, double base_scale, double scale)
5{
6 double size, min, max;
7
8 if (chosen_desc->text.size == 0)
9 return scale;
10
11 min = base_scale * chosen_desc->text.size_range_min;
12 max = chosen_desc->text.size_range_max * base_scale;
13 size = chosen_desc->text.size * scale;
14
15 if ((size > max) && (max > 0))
16 scale = max / (double)chosen_desc->text.size;
17 else if (size < min)
18 scale = min / (double)chosen_desc->text.size;
19
20 return scale;
21}
22
23/* 3/*
24 * Legacy function for min/max calculation of textblock part. 4 * Legacy function for min/max calculation of textblock part.
25 * It can't calculate min/max properly in many cases. 5 * It can't calculate min/max properly in many cases.
@@ -528,7 +508,6 @@ _edje_part_recalc_single_textblock(FLOAT_T sc,
528 508
529 if (chosen_desc) 509 if (chosen_desc)
530 { 510 {
531 Eina_Size2D size;
532 511
533 if (ep->part->scale) 512 if (ep->part->scale)
534 evas_object_scale_set(ep->object, TO_DOUBLE(sc)); 513 evas_object_scale_set(ep->object, TO_DOUBLE(sc));
@@ -539,76 +518,28 @@ _edje_part_recalc_single_textblock(FLOAT_T sc,
539 { 518 {
540 if ((chosen_desc->text.fit_x) || (chosen_desc->text.fit_y)) 519 if ((chosen_desc->text.fit_x) || (chosen_desc->text.fit_y))
541 { 520 {
542 double base_s = 1.0; 521 unsigned int size_array[255];
543 double orig_s; 522 size_t size_array_len = 0;
544 double s = base_s; 523 Eina_List *l;
545 524 unsigned int *value;
546 if (ep->part->scale) base_s = TO_DOUBLE(sc); 525 EINA_LIST_FOREACH(chosen_desc->text.fit_size_array, l, value)
547 efl_gfx_entity_scale_set(ep->object, base_s);
548 size = efl_canvas_textblock_size_native_get(ep->object);
549
550 orig_s = base_s;
551 /* Now make it bigger so calculations will be more accurate
552 * and less influenced by hinting... */
553 {
554 orig_s = _edje_part_recalc_single_textblock_scale_range_adjust(chosen_desc, base_s,
555 orig_s * TO_INT(params->eval.w) / size.w);
556 efl_gfx_entity_scale_set(ep->object, orig_s);
557 size = efl_canvas_textblock_size_native_get(ep->object);
558 }
559 if (chosen_desc->text.fit_x)
560 { 526 {
561 if (size.w > 0) 527 size_array[size_array_len++] = *value;
562 {
563 s = _edje_part_recalc_single_textblock_scale_range_adjust(chosen_desc, base_s,
564 orig_s * TO_INT(params->eval.w) / size.w);
565 efl_gfx_entity_scale_set(ep->object, s);
566 efl_canvas_textblock_size_native_get(ep->object);
567 }
568 } 528 }
529 unsigned int mode = TEXTBLOCK_FIT_MODE_NONE;
530
531 if (chosen_desc->text.fit_x)
532 mode |= TEXTBLOCK_FIT_MODE_WIDTH;
569 if (chosen_desc->text.fit_y) 533 if (chosen_desc->text.fit_y)
534 mode |= TEXTBLOCK_FIT_MODE_HEIGHT;
535 evas_textblock_fit_options_set(ep->object, mode);
536 evas_textblock_fit_step_size_set(ep->object, chosen_desc->text.fit_step);
537 if ( chosen_desc->text.size_range_min || chosen_desc->text.size_range_max)
538 evas_textblock_fit_size_range_set(ep->object, chosen_desc->text.size_range_min, chosen_desc->text.size_range_max);
539 if (size_array_len>0)
570 { 540 {
571 if (size.h > 0) 541 evas_textblock_fit_size_array_set(ep->object,size_array,size_array_len);
572 {
573 double tmp_s = _edje_part_recalc_single_textblock_scale_range_adjust(chosen_desc, base_s,
574 orig_s * TO_INT(params->eval.h) / size.h);
575 /* If we already have X fit, restrict Y to be no bigger
576 * than what we got with X. */
577 if (!((chosen_desc->text.fit_x) && (tmp_s > s)))
578 {
579 s = tmp_s;
580 }
581
582 efl_gfx_entity_scale_set(ep->object, s);
583 efl_canvas_textblock_size_native_get(ep->object);
584 }
585 } 542 }
586
587 /* Final tuning, try going down 90% at a time, hoping it'll
588 * actually end up being correct. */
589 {
590 int i = 5; /* Tries before we give up. */
591 Eina_Size2D size;
592 size = efl_canvas_textblock_size_native_get(ep->object);
593
594 /* If we are still too big, try reducing the size to
595 * 95% each try. */
596 while ((i > 0) &&
597 ((chosen_desc->text.fit_x && (size.w > TO_INT(params->eval.w))) ||
598 (chosen_desc->text.fit_y && (size.h > TO_INT(params->eval.h)))))
599 {
600 double tmp_s = _edje_part_recalc_single_textblock_scale_range_adjust(chosen_desc, base_s, s * 0.95);
601
602 /* Break if we are not making any progress. */
603 if (EQ(tmp_s, s))
604 break;
605 s = tmp_s;
606
607 efl_gfx_entity_scale_set(ep->object, s);
608 size = efl_canvas_textblock_size_native_get(ep->object);
609 i--;
610 }
611 }
612 } 543 }
613 544
614 if ((ed->file->efl_version.major >= 1) && (ed->file->efl_version.minor >= 19)) 545 if ((ed->file->efl_version.major >= 1) && (ed->file->efl_version.minor >= 19))
diff --git a/src/lib/eet/Eet.h b/src/lib/eet/Eet.h
index 25babe1..eb7cb53 100644
--- a/src/lib/eet/Eet.h
+++ b/src/lib/eet/Eet.h
@@ -3538,6 +3538,29 @@ eet_data_descriptor_encode(Eet_Data_Descriptor *edd,
3538 3538
3539/** 3539/**
3540 * @ingroup Eet_Data_Group 3540 * @ingroup Eet_Data_Group
3541 * @brief Adds a linked list of unsigned integers to a data descriptor.
3542 * @param edd The data descriptor to add the type to.
3543 * @param struct_type The type of the struct.
3544 * @param name The string name to use to encode/decode this member
3545 * (must be a constant global and never change).
3546 * @param member The struct member itself to be encoded.
3547 *
3548 * This macro lets you easily add a linked list of unsigned int. All the
3549 * parameters are the same as for EET_DATA_DESCRIPTOR_ADD_BASIC().
3550 *
3551 * @since 1.24.0
3552 */
3553#define EET_DATA_DESCRIPTOR_ADD_LIST_UINT(edd, struct_type, name, member) \
3554 do { \
3555 struct_type ___ett; \
3556 eet_data_descriptor_element_add(edd, name, EET_T_UINT, EET_G_LIST, \
3557 (char *)(& (___ett.member)) - \
3558 (char *)(& (___ett)), \
3559 0, /* 0, */ NULL, NULL); \
3560 } while (0)
3561
3562/**
3563 * @ingroup Eet_Data_Group
3541 * @brief Adds a hash type to a data descriptor. 3564 * @brief Adds a hash type to a data descriptor.
3542 * @param edd The data descriptor to add the type to. 3565 * @param edd The data descriptor to add the type to.
3543 * @param struct_type The type of the struct. 3566 * @param struct_type The type of the struct.
diff --git a/src/lib/evas/canvas/evas_object_textblock.c b/src/lib/evas/canvas/evas_object_textblock.c
index c09418d..019af53 100644
--- a/src/lib/evas/canvas/evas_object_textblock.c
+++ b/src/lib/evas/canvas/evas_object_textblock.c
@@ -139,6 +139,12 @@ static const char o_type[] = "textblock";
139#define EINA_INLIST_REMOVE(l,i) do { l = (__typeof__(l)) eina_inlist_remove(EINA_INLIST_GET(l), EINA_INLIST_GET(i)); } while (0) 139#define EINA_INLIST_REMOVE(l,i) do { l = (__typeof__(l)) eina_inlist_remove(EINA_INLIST_GET(l), EINA_INLIST_GET(i)); } while (0)
140#define EINA_INLIST_APPEND(l,i) do { l = (__typeof__(l)) eina_inlist_append(EINA_INLIST_GET(l), EINA_INLIST_GET(i)); } while (0) 140#define EINA_INLIST_APPEND(l,i) do { l = (__typeof__(l)) eina_inlist_append(EINA_INLIST_GET(l), EINA_INLIST_GET(i)); } while (0)
141 141
142/**
143 * @internal
144 * @typedef TEXT_FIT_CONTENT_CONFIG
145 * Configurations used to fit content inside Textblock
146 */
147typedef struct _TEXT_FIT_CONTENT_CONFIG TEXT_FIT_CONTENT_CONFIG;
142 148
143/** 149/**
144 * @internal 150 * @internal
@@ -420,6 +426,20 @@ typedef struct _User_Style_Entry
420 const char *key; 426 const char *key;
421} User_Style_Entry; 427} User_Style_Entry;
422 428
429struct _TEXT_FIT_CONTENT_CONFIG
430{
431 unsigned int options;
432 unsigned int min_font_size,max_font_size;
433 unsigned int step_size;
434 unsigned int *p_size_array;
435 size_t size_list_length;
436 Eina_Size2D size_cache[256+1]; /** used hash font sizes 1-255 */
437 Eina_Size2D last_size;
438 int last_size_index;
439 Eina_Bool force_refit;
440 char fit_style[256];
441};
442
423#define _FMT(x) (o->default_format.format.x) 443#define _FMT(x) (o->default_format.format.x)
424#define _FMT_INFO(x) (o->default_format.info.x) 444#define _FMT_INFO(x) (o->default_format.info.x)
425 445
@@ -495,6 +515,7 @@ struct _Evas_Object_Textblock
495 Eina_Hash *sources; 515 Eina_Hash *sources;
496 Text_Item_Filter *text_items; // inlist 516 Text_Item_Filter *text_items; // inlist
497 } gfx_filter; 517 } gfx_filter;
518 TEXT_FIT_CONTENT_CONFIG fit_content_config;
498 Eina_Bool redraw : 1; 519 Eina_Bool redraw : 1;
499 Eina_Bool changed : 1; 520 Eina_Bool changed : 1;
500 Eina_Bool pause_change : 1; 521 Eina_Bool pause_change : 1;
@@ -509,6 +530,7 @@ struct _Evas_Object_Textblock
509 Eina_Bool multiline : 1; 530 Eina_Bool multiline : 1;
510 Eina_Bool wrap_changed : 1; 531 Eina_Bool wrap_changed : 1;
511 Eina_Bool auto_styles : 1; 532 Eina_Bool auto_styles : 1;
533 Eina_Bool fit_in_progress : 1;
512}; 534};
513 535
514struct _Evas_Textblock_Selection_Iterator 536struct _Evas_Textblock_Selection_Iterator
@@ -619,6 +641,19 @@ static void _evas_textblock_cursor_copy(Efl_Text_Cursor_Handle *dst, const Efl_T
619static void 641static void
620_textblock_style_generic_set(Evas_Object *eo_obj, Evas_Textblock_Style *ts, const char *key); 642_textblock_style_generic_set(Evas_Object *eo_obj, Evas_Textblock_Style *ts, const char *key);
621 643
644
645/*********Internal fitting Functions and Defines*********/
646int fit_cache_clear(TEXT_FIT_CONTENT_CONFIG *fc,const unsigned int fit_cache_flags);
647int fit_text_block(Evas_Object *eo_obj);
648int fit_fill_internal_list(TEXT_FIT_CONTENT_CONFIG *fc);
649int fit_start_fitting(Evas_Object *eo_obj);
650int fit_finish_fitting(Evas_Object *eo_obj);
651Eina_Bool fit_is_fitting(const Evas_Object *eo_obj);
652const unsigned int FIT_CACHE_CANVAS_SIZE = 0x0001;
653const unsigned int FIT_CACHE_INTERNAL_SIZE_ARRAY = 0x0002;
654const unsigned int FIT_CACHE_FORCE_REFIT = 0x0004;
655const unsigned int FIT_CACHE_ALL = 0x000F;
656
622/** selection iterator */ 657/** selection iterator */
623/** 658/**
624 * @internal 659 * @internal
@@ -7369,6 +7404,11 @@ _layout_setup(Ctxt *c, const Eo *eo_obj, Evas_Coord w, Evas_Coord h)
7369 finalize = EINA_TRUE; 7404 finalize = EINA_TRUE;
7370 } 7405 }
7371 } 7406 }
7407 /* Extra Style used by fitting configure*/
7408 if (*o->fit_content_config.fit_style)
7409 {
7410 _format_fill(c->obj, c->fmt, o->fit_content_config.fit_style, EINA_FALSE);
7411 }
7372 7412
7373 if (finalize) 7413 if (finalize)
7374 _format_finalize(c->obj, c->fmt); 7414 _format_finalize(c->obj, c->fmt);
@@ -7463,7 +7503,9 @@ _relayout_if_needed(const Evas_Object *eo_obj, Efl_Canvas_Textblock_Data *o)
7463 if (obj->delete_me) return EINA_TRUE; 7503 if (obj->delete_me) return EINA_TRUE;
7464 7504
7465 /* XXX const */ 7505 /* XXX const */
7466 evas_object_textblock_coords_recalc((Evas_Object *)eo_obj, obj, obj->private_data); 7506 if(!fit_is_fitting(eo_obj))
7507 evas_object_textblock_coords_recalc((Evas_Object *)eo_obj, obj, obj->private_data);
7508
7467 if (o->formatted.valid) 7509 if (o->formatted.valid)
7468 { 7510 {
7469 return EINA_TRUE; 7511 return EINA_TRUE;
@@ -7621,6 +7663,10 @@ _efl_canvas_textblock_efl_object_constructor(Eo *eo_obj, Efl_Canvas_Textblock_Da
7621 _FMT(ellipsis) = -1; 7663 _FMT(ellipsis) = -1;
7622 _FMT_INFO(bitmap_scalable) = EFL_TEXT_FONT_BITMAP_SCALABLE_COLOR; 7664 _FMT_INFO(bitmap_scalable) = EFL_TEXT_FONT_BITMAP_SCALABLE_COLOR;
7623 7665
7666 /* Fit default properties*/
7667 evas_textblock_fit_size_range_set(eo_obj,1,255);
7668 evas_textblock_fit_step_size_set(eo_obj,1);
7669
7624 o->auto_styles = EINA_TRUE; 7670 o->auto_styles = EINA_TRUE;
7625 7671
7626 return eo_obj; 7672 return eo_obj;
@@ -11311,10 +11357,13 @@ _evas_textblock_changed(Efl_Canvas_Textblock_Data *o, Evas_Object *eo_obj)
11311 o->formatted.valid = 0; 11357 o->formatted.valid = 0;
11312 o->native.valid = 0; 11358 o->native.valid = 0;
11313 o->content_changed = 1; 11359 o->content_changed = 1;
11314 if (o->markup_text) 11360 if (!fit_is_fitting(eo_obj))
11315 { 11361 {
11316 eina_stringshare_del(o->markup_text); 11362 if (o->markup_text)
11317 o->markup_text = NULL; 11363 {
11364 eina_stringshare_del(o->markup_text);
11365 o->markup_text = NULL;
11366 }
11318 } 11367 }
11319 11368
11320 // FIXME: emit ONCE after this following checks 11369 // FIXME: emit ONCE after this following checks
@@ -11324,6 +11373,15 @@ _evas_textblock_changed(Efl_Canvas_Textblock_Data *o, Evas_Object *eo_obj)
11324 _cursor_emit_if_changed(data_obj); 11373 _cursor_emit_if_changed(data_obj);
11325 } 11374 }
11326 11375
11376 /*
11377 If format changed we need to refit content again.
11378 If content already fitting then ignore fitting (fitting cause fall to this callback)
11379 */
11380 if (!fit_is_fitting(eo_obj))
11381 {
11382 fit_cache_clear(&o->fit_content_config, FIT_CACHE_ALL);
11383 fit_text_block(eo_obj);
11384 }
11327 evas_object_change(eo_obj, obj); 11385 evas_object_change(eo_obj, obj);
11328} 11386}
11329 11387
@@ -14264,6 +14322,11 @@ evas_object_textblock_free(Evas_Object *eo_obj)
14264 14322
14265 /* remove obstacles */ 14323 /* remove obstacles */
14266 _obstacles_free(eo_obj, o); 14324 _obstacles_free(eo_obj, o);
14325 if (o->fit_content_config.p_size_array)
14326 {
14327 free(o->fit_content_config.p_size_array);
14328 o->fit_content_config.p_size_array = NULL;
14329 }
14267 14330
14268#ifdef HAVE_HYPHEN 14331#ifdef HAVE_HYPHEN
14269 /* Hyphenation */ 14332 /* Hyphenation */
@@ -15350,6 +15413,7 @@ _efl_canvas_textblock_efl_gfx_filter_filter_source_get(const Eo *obj EINA_UNUSED
15350 return eina_hash_find(pd->gfx_filter.sources, name); 15413 return eina_hash_find(pd->gfx_filter.sources, name);
15351} 15414}
15352 15415
15416
15353static void 15417static void
15354evas_object_textblock_coords_recalc(Evas_Object *eo_obj, 15418evas_object_textblock_coords_recalc(Evas_Object *eo_obj,
15355 Evas_Object_Protected_Data *obj, 15419 Evas_Object_Protected_Data *obj,
@@ -15407,6 +15471,17 @@ evas_object_textblock_coords_recalc(Evas_Object *eo_obj,
15407 o->formatted.valid = 0; 15471 o->formatted.valid = 0;
15408 o->changed = 1; 15472 o->changed = 1;
15409 } 15473 }
15474
15475 Evas_Coord x,y,w,h;
15476 evas_object_geometry_get(eo_obj, &x, &y, &w, &h);
15477 if (
15478 (w!=o->fit_content_config.last_size.w || h!=o->fit_content_config.last_size.h) &&
15479 (o->fit_content_config.options & TEXTBLOCK_FIT_MODE_ALL) != TEXTBLOCK_FIT_MODE_NONE
15480 )
15481 {
15482 fit_cache_clear(&o->fit_content_config, FIT_CACHE_INTERNAL_SIZE_ARRAY);
15483 fit_text_block(eo_obj);
15484 }
15410} 15485}
15411 15486
15412static void 15487static void
@@ -15534,6 +15609,54 @@ done:
15534 eo_obj, is_v, was_v); 15609 eo_obj, is_v, was_v);
15535} 15610}
15536 15611
15612void fit_style_update(Evas_Object *object, int i_font_size, Eina_Bool disable_ellipsis, Eina_Bool disable_wrap)
15613{
15614 Efl_Canvas_Textblock_Data *o = efl_data_scope_get(object, MY_CLASS);
15615 TEXT_FIT_CONTENT_CONFIG * fc = &o->fit_content_config;
15616 memset(fc->fit_style,0,sizeof(fc->fit_style));
15617 char * fit_style = fc->fit_style;
15618 if (i_font_size >= 0)
15619 {
15620 char font_size[0xF] = {0};
15621 char *pfont = font_size;
15622 sprintf(font_size, "font_size=%i ", i_font_size);
15623 while (*pfont)
15624 {
15625 *fit_style = *pfont;
15626 pfont++;
15627 fit_style++;
15628 }
15629 }
15630
15631 if (disable_ellipsis == EINA_TRUE)
15632 {
15633 *fit_style = ' ';
15634 fit_style++;
15635 char *p = "ellipsis=2.0";
15636 while (*p)
15637 {
15638 *fit_style = *p;
15639 p++;
15640 fit_style++;
15641 }
15642 }
15643
15644 if (disable_wrap == EINA_TRUE)
15645 {
15646 *fit_style = ' ';
15647 fit_style++;
15648 char *p = "wrap=none";
15649 while (*p)
15650 {
15651 *fit_style = *p;
15652 p++;
15653 fit_style++;
15654 }
15655 }
15656
15657 _canvas_text_format_changed(object,o);
15658}
15659
15537static void 15660static void
15538evas_object_textblock_render_post(Evas_Object *eo_obj EINA_UNUSED, 15661evas_object_textblock_render_post(Evas_Object *eo_obj EINA_UNUSED,
15539 Evas_Object_Protected_Data *obj, 15662 Evas_Object_Protected_Data *obj,
@@ -17026,6 +17149,371 @@ _efl_canvas_textblock_async_layout(Eo *eo_obj EINA_UNUSED, Efl_Canvas_Textblock_
17026 NULL, ctx); 17149 NULL, ctx);
17027 return f; 17150 return f;
17028} 17151}
17152/* Fitting Internal Functions*/
17153
17154int fit_cache_clear(TEXT_FIT_CONTENT_CONFIG *fc, unsigned int fit_cache_flags)
17155{
17156 EINA_SAFETY_ON_NULL_RETURN_VAL(fc, EVAS_ERROR_INVALID_PARAM);
17157 if ((fit_cache_flags&FIT_CACHE_CANVAS_SIZE) == FIT_CACHE_CANVAS_SIZE)
17158 fc->last_size = EINA_SIZE2D(0, 0);
17159 if ((fit_cache_flags&FIT_CACHE_INTERNAL_SIZE_ARRAY) == FIT_CACHE_INTERNAL_SIZE_ARRAY)
17160 for(int i = 0 ; i < 255 ; i++) fc->size_cache[i] = EINA_SIZE2D(0,0);
17161 if ((fit_cache_flags&FIT_CACHE_FORCE_REFIT) == FIT_CACHE_FORCE_REFIT)
17162 fc->force_refit = EINA_TRUE;
17163 return EVAS_ERROR_SUCCESS;
17164}
17165
17166int fit_start_fitting(Evas_Object *eo_obj)
17167{
17168 EINA_SAFETY_ON_NULL_RETURN_VAL(eo_obj, EVAS_ERROR_INVALID_PARAM);
17169 Efl_Canvas_Textblock_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
17170 if (o->fit_in_progress == EINA_TRUE)
17171 return EVAS_ERROR_INVALID_OPERATION;
17172
17173 o->fit_in_progress = EINA_TRUE;
17174 return EVAS_ERROR_SUCCESS;
17175}
17176
17177int fit_finish_fitting(Evas_Object *eo_obj)
17178{
17179 EINA_SAFETY_ON_NULL_RETURN_VAL(eo_obj, EVAS_ERROR_INVALID_PARAM);
17180 Efl_Canvas_Textblock_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
17181 if (o->fit_in_progress == EINA_FALSE)
17182 return EVAS_ERROR_INVALID_OPERATION;
17183
17184 o->fit_in_progress = EINA_FALSE;
17185 return EVAS_ERROR_SUCCESS;
17186}
17187
17188Eina_Bool fit_is_fitting(const Evas_Object *eo_obj)
17189{
17190 EINA_SAFETY_ON_NULL_RETURN_VAL(eo_obj, EVAS_ERROR_INVALID_PARAM);
17191 Efl_Canvas_Textblock_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
17192 return o->fit_in_progress;
17193}
17194
17195int fit_text_block(Evas_Object *eo_obj)
17196{
17197 EINA_SAFETY_ON_NULL_RETURN_VAL(eo_obj, EVAS_ERROR_INVALID_PARAM);
17198 Efl_Canvas_Textblock_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
17199 Evas_Coord x,y,w,h;
17200 Evas_Coord wf_new,hf_new;
17201
17202 TEXT_FIT_CONTENT_CONFIG * fc = &o->fit_content_config;
17203
17204 if (fc->options == TEXTBLOCK_FIT_MODE_NONE && !fc->force_refit)
17205 return EVAS_ERROR_SUCCESS;
17206
17207
17208 if (fc->options == TEXTBLOCK_FIT_MODE_NONE)
17209 {
17210 fit_start_fitting(eo_obj);
17211 fc->force_refit = 0;
17212 fit_style_update(eo_obj,-1, EINA_FALSE, EINA_FALSE);
17213 fit_finish_fitting(eo_obj);
17214 return EVAS_ERROR_SUCCESS;
17215 }
17216
17217 evas_object_geometry_get(eo_obj, &x, &y, &w, &h);
17218
17219 if (w > 0 && h > 0)
17220 {
17221 Eina_Bool b_fit_width = ((fc->options & TEXTBLOCK_FIT_MODE_WIDTH) == TEXTBLOCK_FIT_MODE_WIDTH);
17222 Eina_Bool b_fit_height = ((fc->options & TEXTBLOCK_FIT_MODE_HEIGHT) == TEXTBLOCK_FIT_MODE_HEIGHT);
17223 //FIXME uncomment condition when style is not warp
17224 if ( fc->force_refit || /*(w != fc->last_size.w && b_fit_width) || (h != fc->last_size.h && b_fit_height)*/ EINA_TRUE)
17225 {
17226 /* Extra Check to reduce recalculate */
17227 Eina_Bool b_max_reached = (fc->last_size_index == ((int)fc->size_list_length) - 1);
17228 Eina_Bool b_min_reached = (fc->last_size_index == 0);
17229 /* 1 - If max font size reached and text block size increased*/
17230 if (!fc->force_refit && b_max_reached && ((b_fit_width ? (w >= fc->last_size.w) : EINA_TRUE) && (b_fit_height ? (h >= fc->last_size.h) : EINA_TRUE)))
17231 return EVAS_ERROR_SUCCESS;
17232 /* 2- If min font size reached and text block size decreased*/
17233 if (!fc->force_refit && b_min_reached && ((b_fit_width ? (w <= fc->last_size.w) : EINA_TRUE) && (b_fit_height ? (h <= fc->last_size.h) : EINA_TRUE)))
17234 {
17235 /*This is needed to recalculate ellipsis, inside fitting to avoid losing markup_text*/
17236 fit_start_fitting(eo_obj);
17237 _canvas_text_format_changed(eo_obj, o);
17238 fit_finish_fitting(eo_obj);
17239 return EVAS_ERROR_SUCCESS;
17240 }
17241
17242 fit_start_fitting(eo_obj);
17243
17244 fc->force_refit = EINA_FALSE;
17245 fc->last_size.w = w;
17246 fc->last_size.h = h;
17247
17248 int r = fc->size_list_length;
17249 int l = 0;
17250
17251 Eina_Bool bwrap = EINA_FALSE;
17252 if (fc->options == TEXTBLOCK_FIT_MODE_WIDTH)
17253 {
17254 bwrap = EINA_TRUE;
17255 }
17256
17257 while(r > l)
17258 {
17259 int mid = (r + l) / 2;
17260 /*cache font sizes vaules from 0-255 in size_cache array*/
17261 size_t font_size = fc->p_size_array[mid];
17262 if (font_size <= 0xFF && (fc->size_cache[font_size].w != 0 && fc->size_cache[font_size].h != 0))
17263 {
17264 wf_new = fc->size_cache[font_size].w;
17265 hf_new = fc->size_cache[font_size].h;
17266 }
17267 else
17268 {
17269 fit_style_update(eo_obj,fc->p_size_array[mid],EINA_TRUE,bwrap);
17270 Eina_Size2D size = efl_canvas_textblock_size_formatted_get(eo_obj);
17271 wf_new = size.w;
17272 hf_new = size.h;
17273 if (fc->p_size_array[mid]<255)
17274 {
17275 fc->size_cache[font_size].w = wf_new;
17276 fc->size_cache[font_size].h = hf_new;
17277 }
17278 }
17279
17280 if (
17281 ((wf_new > w) & ((fc->options & TEXTBLOCK_FIT_MODE_WIDTH) == TEXTBLOCK_FIT_MODE_WIDTH)) ||
17282 ((hf_new > h) & ((fc->options & TEXTBLOCK_FIT_MODE_HEIGHT) == TEXTBLOCK_FIT_MODE_HEIGHT)))
17283 {
17284 r = mid;
17285 }
17286 else
17287 {
17288 l = mid + 1;
17289 }
17290 }
17291
17292 /*Lower bound founded, subtract one to move for nearest value*/
17293 fc->last_size_index = MAX(l-1, 0);
17294 fit_style_update(eo_obj,fc->p_size_array[fc->last_size_index],(fc->last_size_index != 0) && fc->options != TEXTBLOCK_FIT_MODE_HEIGHT ,EINA_FALSE);
17295 fit_finish_fitting(eo_obj);
17296 }
17297 }
17298 return EVAS_ERROR_SUCCESS;
17299}
17300
17301int fit_fill_internal_list(TEXT_FIT_CONTENT_CONFIG *fc)
17302{
17303 int diff = (fc->max_font_size - fc->min_font_size);
17304 if (fc->p_size_array)
17305 {
17306 free(fc->p_size_array);
17307 fc->p_size_array = NULL;
17308 }
17309 if (diff == 0)
17310 {
17311 fc->size_list_length = 1;
17312 fc->p_size_array = malloc(sizeof(unsigned int) * fc->size_list_length);
17313 if (!fc->p_size_array)
17314 return EVAS_ERROR_NO_MEMORY;
17315 fc->p_size_array[0] = fc->max_font_size;
17316 return EVAS_ERROR_SUCCESS;
17317 }
17318
17319 fc->size_list_length = 2 + diff / MAX(fc->step_size, 1);
17320 fc->p_size_array = malloc(sizeof(unsigned int) * fc->size_list_length);
17321 if (!fc->p_size_array)
17322 return EVAS_ERROR_NO_MEMORY;
17323
17324 size_t i ;
17325 for (i = 0 ; i < fc->size_list_length - 1; i++)
17326 {
17327 fc->p_size_array[i] = fc->min_font_size + i * MAX(fc->step_size, 1);
17328 }
17329 fc->p_size_array[fc->size_list_length - 1] = fc->max_font_size;
17330 fc->last_size_index = -1;
17331 return EVAS_ERROR_SUCCESS;
17332}
17333
17334
17335
17336EAPI int evas_textblock_fit_options_set(Evas_Object *obj, unsigned int options)
17337{
17338 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EVAS_ERROR_INVALID_PARAM);
17339 Efl_Canvas_Textblock_Data *o = efl_data_scope_get(obj, MY_CLASS);
17340 TEXT_FIT_CONTENT_CONFIG * fc = &o->fit_content_config;
17341 if (fc->options == options)
17342 return EVAS_ERROR_SUCCESS;
17343
17344 fc->options = options;
17345 fit_cache_clear(fc, FIT_CACHE_ALL);
17346 fit_text_block(obj);
17347 return EVAS_ERROR_SUCCESS;
17348}
17349
17350EAPI int evas_textblock_fit_options_get(const Evas_Object *obj, unsigned int *p_options)
17351{
17352 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EVAS_ERROR_INVALID_PARAM);
17353 Efl_Canvas_Textblock_Data *o = efl_data_scope_get(obj, MY_CLASS);
17354 TEXT_FIT_CONTENT_CONFIG * fc = &o->fit_content_config;
17355 if (p_options)
17356 *p_options = fc->options;
17357 return EVAS_ERROR_SUCCESS;
17358}
17359
17360EAPI int evas_textblock_fit_size_range_set(Evas_Object *obj, unsigned int min_font_size, unsigned int max_font_size)
17361{
17362 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EVAS_ERROR_INVALID_PARAM);
17363 Efl_Canvas_Textblock_Data *o = efl_data_scope_get(obj, MY_CLASS);
17364 TEXT_FIT_CONTENT_CONFIG * fc = &o->fit_content_config;
17365
17366 Eina_Bool max_changed = fc->max_font_size != max_font_size;
17367 Eina_Bool min_changed = fc->min_font_size != min_font_size;
17368
17369 /* last_selected_size used for optimization calculations
17370 * If last_size_index already recach last element in p_size_array
17371 * Skip optimization by setting last_selected_size to -1
17372 */
17373 int last_selected_size = fc->last_size_index;
17374 if (last_selected_size == ((int)fc->size_list_length-1))
17375 last_selected_size = -1;
17376
17377 if (!max_changed && !min_changed)
17378 return EVAS_ERROR_SUCCESS;
17379
17380 if (min_font_size < 0 || max_font_size <0)
17381 return EVAS_ERROR_INVALID_PARAM;
17382
17383 if (max_font_size < min_font_size)
17384 return EVAS_ERROR_INVALID_PARAM;
17385
17386 fc->max_font_size = max_font_size;
17387 fc->min_font_size = min_font_size;
17388
17389 int n_ret = EVAS_ERROR_SUCCESS;
17390 n_ret = fit_cache_clear(fc,FIT_CACHE_FORCE_REFIT);
17391 if (n_ret) return n_ret;
17392 n_ret = fit_fill_internal_list(fc);
17393 if (n_ret) return n_ret;
17394
17395 /* Optimization to reduce calculations
17396 * If only max size changed and last fit size index is still valid, then no need to recalculation
17397 * Where changing max font size will not change content of p_size_array for sizes < max_size
17398 */
17399 if (min_changed || (last_selected_size == -1 || last_selected_size > ((int)fc->size_list_length-1)))
17400 {
17401 n_ret = fit_text_block(obj);
17402 if (n_ret) return n_ret;
17403 }
17404 else
17405 {
17406 /* Keep fit size index */
17407 fc->last_size_index = last_selected_size;
17408 }
17409 return EVAS_ERROR_SUCCESS;
17410}
17411
17412EAPI int evas_textblock_fit_size_range_get(const Evas_Object *obj, unsigned int *p_min_font_size, unsigned int *p_max_font_size)
17413{
17414 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EVAS_ERROR_INVALID_PARAM);
17415 Efl_Canvas_Textblock_Data *o = efl_data_scope_get(obj, MY_CLASS);
17416 TEXT_FIT_CONTENT_CONFIG * fc = &o->fit_content_config;
17417
17418 if (p_min_font_size)
17419 *p_min_font_size = fc->min_font_size;
17420
17421 if (p_max_font_size)
17422 *p_max_font_size = fc->max_font_size;
17423
17424 return EVAS_ERROR_SUCCESS;
17425}
17426
17427EAPI int evas_textblock_fit_step_size_set(Evas_Object *obj, unsigned int step_size)
17428{
17429 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EVAS_ERROR_INVALID_PARAM);
17430 Efl_Canvas_Textblock_Data *o = efl_data_scope_get(obj, MY_CLASS);
17431 TEXT_FIT_CONTENT_CONFIG * fc = &o->fit_content_config;
17432 if (fc->step_size == step_size)
17433 return EVAS_ERROR_SUCCESS;
17434
17435 if (step_size == 0)
17436 return EVAS_ERROR_INVALID_PARAM;
17437
17438 fc->step_size = step_size;
17439 int n_ret = EVAS_ERROR_SUCCESS;
17440 n_ret = fit_cache_clear(fc, FIT_CACHE_FORCE_REFIT);
17441 if (n_ret) return n_ret;
17442 n_ret = fit_fill_internal_list(fc);
17443 if (n_ret) return n_ret;
17444 n_ret = fit_text_block(obj);
17445 if (n_ret) return n_ret;
17446 return EVAS_ERROR_SUCCESS;
17447}
17448
17449EAPI int evas_textblock_fit_step_size_get(const Evas_Object *obj, unsigned int * p_step_size)
17450{
17451 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EVAS_ERROR_INVALID_PARAM);
17452 Efl_Canvas_Textblock_Data *o = efl_data_scope_get(obj, MY_CLASS);
17453 TEXT_FIT_CONTENT_CONFIG * fc = &o->fit_content_config;
17454 if (p_step_size)
17455 *p_step_size = fc->step_size;
17456 return EVAS_ERROR_SUCCESS;
17457}
17458
17459int compareUINT(const void * a, const void * b)
17460{
17461 unsigned int a_value = *(const unsigned int*)a;
17462 unsigned int b_value = *(const unsigned int*)b;
17463
17464 if(a_value > b_value) return 1;
17465 else if(a_value < b_value) return -1;
17466 else return 0;
17467}
17468
17469EAPI int evas_textblock_fit_size_array_set(Evas_Object *obj, const unsigned int *p_size_array, size_t size_array_len)
17470{
17471 int n_ret = EVAS_ERROR_SUCCESS;
17472 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EVAS_ERROR_INVALID_PARAM);
17473 Efl_Canvas_Textblock_Data *o = efl_data_scope_get(obj, MY_CLASS);
17474 TEXT_FIT_CONTENT_CONFIG * fc = &o->fit_content_config;
17475 if (size_array_len == 0)
17476 return EVAS_ERROR_INVALID_PARAM;
17477
17478 if (fc->p_size_array)
17479 {
17480 free(fc->p_size_array);
17481 fc->p_size_array = NULL;
17482 fc->size_list_length = 0;
17483 }
17484
17485 fc->p_size_array = malloc(sizeof(unsigned int) * size_array_len);
17486 if (!fc->p_size_array) return EVAS_ERROR_NO_MEMORY;
17487 memcpy(fc->p_size_array,p_size_array,sizeof(unsigned int) * size_array_len);
17488 fc->size_list_length = size_array_len;
17489
17490 fc->last_size_index = -1;
17491
17492 qsort(fc->p_size_array,fc->size_list_length,sizeof(unsigned int),compareUINT);
17493
17494 n_ret = fit_cache_clear(fc, FIT_CACHE_FORCE_REFIT);
17495 if (n_ret) return n_ret;
17496 n_ret = fit_text_block(obj);
17497 if (n_ret) return n_ret;
17498 return EVAS_ERROR_SUCCESS;
17499}
17500
17501EAPI int evas_textblock_fit_size_array_get(const Evas_Object *obj, unsigned int *p_size_array, size_t *p_size_array_len, size_t passed_array_size)
17502{
17503 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EVAS_ERROR_INVALID_PARAM);
17504 Efl_Canvas_Textblock_Data *o = efl_data_scope_get(obj, MY_CLASS);
17505 TEXT_FIT_CONTENT_CONFIG * fc = &o->fit_content_config;
17506 if (p_size_array)
17507 {
17508 size_t num = MIN(passed_array_size,fc->size_list_length);
17509 memcpy(p_size_array,fc->p_size_array,sizeof(unsigned int)* num);
17510 }
17511 if (p_size_array_len)
17512 {
17513 *p_size_array_len = fc->size_list_length;
17514 }
17515 return EVAS_ERROR_SUCCESS;
17516}
17029 17517
17030#include "canvas/efl_canvas_textblock.eo.c" 17518#include "canvas/efl_canvas_textblock.eo.c"
17031#include "canvas/efl_canvas_textblock_eo.legacy.c" 17519#include "canvas/efl_canvas_textblock_eo.legacy.c"
diff --git a/src/lib/evas/canvas/evas_textblock_legacy.h b/src/lib/evas/canvas/evas_textblock_legacy.h
index f329911..b852c0d 100644
--- a/src/lib/evas/canvas/evas_textblock_legacy.h
+++ b/src/lib/evas/canvas/evas_textblock_legacy.h
@@ -1056,6 +1056,106 @@ EAPI void evas_textblock_cursor_char_delete(Evas_Textblock_Cursor *cur);
1056 * @ingroup Evas_Textblock 1056 * @ingroup Evas_Textblock
1057 */ 1057 */
1058EAPI Evas_Textblock_Cursor *evas_object_textblock_cursor_get(const Evas_Object *obj); 1058EAPI Evas_Textblock_Cursor *evas_object_textblock_cursor_get(const Evas_Object *obj);
1059
1060
1061
1062/* TEXT BLOCK FIT OPTIONS FLAGS*/
1063#define TEXTBLOCK_FIT_MODE_NONE 0x0000
1064#define TEXTBLOCK_FIT_MODE_WIDTH 0x0001
1065#define TEXTBLOCK_FIT_MODE_HEIGHT 0x0002
1066#define TEXTBLOCK_FIT_MODE_ALL 0x0003
1067
1068/* TEXT BLOCK ERROR CODES*/
1069/* FIXME this hould go to other public place*/
1070#define EVAS_ERROR_SUCCESS 0x0000
1071#define EVAS_ERROR_INVALID_PARAM 0x0001
1072#define EVAS_ERROR_NO_MEMORY 0x0002
1073#define EVAS_ERROR_INVALID_OPERATION 0x0003
1074
1075
1076/** Get the object's content it options.
1077 *
1078 * @param obj The textblock object.
1079 * @param[out] options content fitting options.
1080 * @return Returns error code.
1081 */
1082EAPI int evas_textblock_fit_options_get(const Evas_Object *obj, unsigned int * p_options);
1083
1084/** Set the object's content it options.
1085 *
1086 * @param obj The textblock object.
1087 * @param[in] options content fitting options.
1088 * @return Returns error code.
1089 */
1090EAPI int evas_textblock_fit_options_set(Evas_Object *obj, unsigned int options);
1091
1092/** Get the object's max and min font sizes used for fitting content.
1093 *
1094 * @param obj The textblock object.
1095 * @param[out] p_min_font_size min font size used when fitting content.
1096 * @param[out] p_max_font_size max font size used when fitting content.
1097 * @return Returns error code.
1098 */
1099EAPI int evas_textblock_fit_size_range_get(const Evas_Object *obj, unsigned int *p_min_font_size, unsigned int *p_max_font_size);
1100
1101/** Set the object's max and min font sizes used for fitting content.
1102 *
1103 * @param obj The textblock object.
1104 * @param[in] min_font_size min font size used when fitting content.
1105 * @param[in] max_font_size max font size used when fitting content.
1106 * @return Returns error code.
1107 */
1108EAPI int evas_textblock_fit_size_range_set(Evas_Object *obj, unsigned int min_font_size, unsigned int max_font_size);
1109
1110
1111/** Get the object's fitting step size when trying fonts between min font size and
1112 * max font size.
1113 *
1114 * @param obj The textblock object.
1115 * @param[out] p_step_size step jumps between min and max font size.
1116 * @return Returns error code.
1117 */
1118EAPI int evas_textblock_fit_step_size_get(const Evas_Object *obj, unsigned int *p_step_size);
1119
1120
1121/** Set the object's fitting step size when trying fonts between min font size and
1122 * max font size.
1123 *
1124 * @param obj The textblock object.
1125 * @param[out] step_size step jumps between min and max font size.
1126 * @return Returns error code.
1127 */
1128EAPI int evas_textblock_fit_step_size_set(Evas_Object *obj, unsigned int step_size);
1129
1130/** Get copy of the object's fitting font size array used internally
1131 *
1132 * @param obj The textblock object.
1133 * @param[out] p_size_array pointer to size array (passing NULL will ignore filling array).
1134 * @param[out] p_size_array_len the length of internall font sizes array.
1135 * @param[out] request_size_array request to fill specific amount in p_size_array.
1136 * @return Returns error code.
1137 */
1138EAPI int evas_textblock_fit_size_array_get(const Evas_Object *obj, unsigned int *p_size_array, size_t *p_size_array_len,size_t request_size_array);
1139
1140/** Set the object's fitting font size array that will be used internally
1141 * Changing fitting step_size,min_font_size,max_font size will generate new array
1142 * Internall array will be sorted
1143 *
1144 * @param obj The textblock object.
1145 * @param[in] p_size_array pointer to font sizes array.
1146 * @param[in] size_array_len the length passed font sizes array.
1147 * @return Returns error code.
1148 */
1149EAPI int evas_textblock_fit_size_array_set(Evas_Object *obj, const unsigned int *p_size_array, size_t size_array_len);
1150
1151
1152
1153
1154
1155
1156
1157
1158
1059#include "canvas/efl_canvas_textblock_eo.legacy.h" 1159#include "canvas/efl_canvas_textblock_eo.legacy.h"
1060/** 1160/**
1061 * @} 1161 * @}
diff --git a/src/tests/evas/evas_test_textblock.c b/src/tests/evas/evas_test_textblock.c
index 786be4a..a450ebc 100644
--- a/src/tests/evas/evas_test_textblock.c
+++ b/src/tests/evas/evas_test_textblock.c
@@ -4134,6 +4134,32 @@ EFL_START_TEST(evas_textblock_obstacle)
4134} 4134}
4135EFL_END_TEST; 4135EFL_END_TEST;
4136 4136
4137EFL_START_TEST(evas_textblock_fit)
4138{
4139 START_TB_TEST();
4140 Evas_Coord fw, fh,fw_new, fh_new;
4141 int n_ret;
4142 const char *buf =
4143 "This is an example text to demonstrate the textblock object"
4144 " with content fit feature.";
4145 evas_object_textblock_text_markup_set(tb, buf);
4146 evas_object_resize(tb, 300, 300);
4147 evas_object_textblock_size_formatted_get(tb, &fw, &fh);
4148 n_ret = evas_textblock_fit_options_set(tb,TEXTBLOCK_FIT_MODE_ALL);
4149 fail_if(n_ret != EVAS_ERROR_SUCCESS);
4150 n_ret = evas_textblock_fit_size_range_set(tb,1,50);
4151 fail_if(n_ret != EVAS_ERROR_SUCCESS);
4152 evas_object_textblock_size_formatted_get(tb, &fw_new, &fh_new);
4153 fail_if(fw_new == fw && fh_new == fh);
4154 unsigned int size_array[3] = {150,200,250};
4155 n_ret = evas_textblock_fit_size_array_set(tb,size_array,3);
4156 fail_if(n_ret != EVAS_ERROR_SUCCESS);
4157 evas_object_textblock_size_formatted_get(tb, &fw, &fh);
4158 fail_if(fw_new == fw && fh_new == fh);
4159 END_TB_TEST();
4160}
4161EFL_END_TEST;
4162
4137#ifdef HAVE_HYPHEN 4163#ifdef HAVE_HYPHEN
4138static void 4164static void
4139_hyphenation_width_stress(Evas_Object *tb, Evas_Textblock_Cursor *cur) 4165_hyphenation_width_stress(Evas_Object *tb, Evas_Textblock_Cursor *cur)
@@ -4654,6 +4680,7 @@ void evas_test_textblock(TCase *tc)
4654 tcase_add_test(tc, evas_textblock_items); 4680 tcase_add_test(tc, evas_textblock_items);
4655 tcase_add_test(tc, evas_textblock_delete); 4681 tcase_add_test(tc, evas_textblock_delete);
4656 tcase_add_test(tc, evas_textblock_obstacle); 4682 tcase_add_test(tc, evas_textblock_obstacle);
4683 tcase_add_test(tc, evas_textblock_fit);
4657#ifdef HAVE_HYPHEN 4684#ifdef HAVE_HYPHEN
4658 tcase_add_test(tc, evas_textblock_hyphenation); 4685 tcase_add_test(tc, evas_textblock_hyphenation);
4659#endif 4686#endif