summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2019-10-31 12:21:59 +0000
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2019-10-31 12:31:52 +0000
commit80d317f20ebdc521d62a443a30482cf05bf89a07 (patch)
tree179b38501272eab8fb79a249bd479309ebb01d4d
parent72a5367f8dd0ceeefea3729dafedb970e47d0613 (diff)
evas - revert evas variation sequence support - out of bound accesses
This code is filled with out of bounds accesses now after the reverted patch. All those base_char+1, itr+1 etc. in evas_common_font_query_run_font_end_get() are accessing BEYOND the end of the run. textgrid shows this instantly to fall over as it uses single unicode codepoint chars with no nul terminator. As this api takes an explicit run_len we should never access beyond the end of the run_len. Please revisit this code and keep in mind proper memory/bounds accessing. If there was ano run_len and it assumed strings were regular strings that had to be nul terminated... then it might be ok, but not here. of course if i put in guards for these +1's then it ends up in infintie loops, so enough debugging and send it back for a rethink. :) .... Revert "evas_object_textblock: add support for variation sequences" This reverts commit 46f2d8acdcda3f374c9e393ecb734ff9d00fef7d.
-rw-r--r--src/bin/elementary/test.c2
-rw-r--r--src/bin/elementary/test_label.c24
-rw-r--r--src/lib/evas/common/evas_font.h53
-rw-r--r--src/lib/evas/common/evas_font_load.c6
-rw-r--r--src/lib/evas/common/evas_font_main.c296
-rw-r--r--src/lib/evas/common/evas_font_query.c54
-rw-r--r--src/lib/evas/common/evas_text_utils.c6
-rw-r--r--src/tests/evas/evas_test_textblock.c20
-rw-r--r--src/tests/evas/fonts/NotoColorEmoji.ttfbin7297112 -> 0 bytes
-rw-r--r--src/tests/evas/fonts/NotoEmoji-Regular.ttfbin418804 -> 0 bytes
10 files changed, 49 insertions, 412 deletions
diff --git a/src/bin/elementary/test.c b/src/bin/elementary/test.c
index bcdb484af3..8259ed8b0c 100644
--- a/src/bin/elementary/test.c
+++ b/src/bin/elementary/test.c
@@ -243,7 +243,6 @@ void test_label_wrap(void *data, Evas_Object *obj, void *event_info);
243void test_label_ellipsis(void *data, Evas_Object *obj, void *event_info); 243void test_label_ellipsis(void *data, Evas_Object *obj, void *event_info);
244void test_label_colors(void *data, Evas_Object *obj, void *event_info); 244void test_label_colors(void *data, Evas_Object *obj, void *event_info);
245void test_label_emoji(void *data, Evas_Object *obj, void *event_info); 245void test_label_emoji(void *data, Evas_Object *obj, void *event_info);
246void test_label_variation_sequence(void *data, Evas_Object *obj, void *event_info);
247void test_conformant(void *data, Evas_Object *obj, void *event_info); 246void test_conformant(void *data, Evas_Object *obj, void *event_info);
248void test_conformant2(void *data, Evas_Object *obj, void *event_info); 247void test_conformant2(void *data, Evas_Object *obj, void *event_info);
249void test_conformant_indicator(void *data, Evas_Object *obj, void *event_info); 248void test_conformant_indicator(void *data, Evas_Object *obj, void *event_info);
@@ -1211,7 +1210,6 @@ add_tests:
1211 ADD_TEST(NULL, "Text", "Label Ellipsis", test_label_ellipsis); 1210 ADD_TEST(NULL, "Text", "Label Ellipsis", test_label_ellipsis);
1212 ADD_TEST(NULL, "Text", "Label Colors", test_label_colors); 1211 ADD_TEST(NULL, "Text", "Label Colors", test_label_colors);
1213 ADD_TEST(NULL, "Text", "Label Emoji", test_label_emoji); 1212 ADD_TEST(NULL, "Text", "Label Emoji", test_label_emoji);
1214 ADD_TEST(NULL, "Text", "Label Variation Sequnece", test_label_variation_sequence);
1215 ADD_TEST_EO(NULL, "Text", "Efl.Ui.Textpath", test_ui_textpath); 1213 ADD_TEST_EO(NULL, "Text", "Efl.Ui.Textpath", test_ui_textpath);
1216 1214
1217 //------------------------------// 1215 //------------------------------//
diff --git a/src/bin/elementary/test_label.c b/src/bin/elementary/test_label.c
index 72cb2aeca3..233ce015b4 100644
--- a/src/bin/elementary/test_label.c
+++ b/src/bin/elementary/test_label.c
@@ -403,30 +403,6 @@ test_label_colors(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *ev
403 evas_object_show(win); 403 evas_object_show(win);
404} 404}
405 405
406/*** Label variation sequence **************************************************************/
407void
408test_label_variation_sequence(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
409{
410 Evas_Object *win, *lb;
411
412 win = elm_win_util_standard_add("label-variation sequence", "Label variation sequnece");
413 elm_win_autodel_set(win, EINA_TRUE);
414
415 lb = elm_label_add(win);
416 elm_object_text_set(lb,
417 "You need to have at least on font contains variation sequence<br>"
418 "Three different 8 glyphs : <br>"
419 "8<tab>8&#xfe0f;<tab>8&#xfe0f;&#x20E3;<br>"
420 "line with 3 variation glyphs : <br>"
421 "8&#xfe0f;&#x20E3;&#x262a;&#xfe0f;AAA&#x262a;&#xfe0E;1234567&#xfe0f;&#x20E3;"
422 );
423 evas_object_size_hint_weight_set(lb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
424 elm_win_resize_object_add(win, lb);
425 evas_object_show(lb);
426
427 evas_object_show(win);
428}
429
430/*** Label Emoji *************************************************************/ 406/*** Label Emoji *************************************************************/
431static char * 407static char *
432_fontlist_text_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part EINA_UNUSED) 408_fontlist_text_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part EINA_UNUSED)
diff --git a/src/lib/evas/common/evas_font.h b/src/lib/evas/common/evas_font.h
index b4490ea992..e16785520d 100644
--- a/src/lib/evas/common/evas_font.h
+++ b/src/lib/evas/common/evas_font.h
@@ -56,32 +56,7 @@ typedef unsigned long long DATA64;
56#define LKU(x) eina_lock_release(&(x)) 56#define LKU(x) eina_lock_release(&(x))
57#define LKDBG(x) eina_lock_debug(&(x)) 57#define LKDBG(x) eina_lock_debug(&(x))
58 58
59/**
60 * See explanation of variation_sequences at:
61 * https://unicode.org/Public/UCD/latest/ucd/StandardizedVariants.txt
62 * https://unicode.org/reports/tr37/
63 * https://unicode.org/ivd/
64 * https://www.freetype.org/freetype2/docs/reference/ft2-glyph_variants.html
65*/
66#define VAR_SEQ(x) GENERIC_VARIATION_SEQUENCES(x) | IDEOGRAPHICS_VARIATION_SEQUENCES(x) | MANGOLIAN_VARIATION_SEQUENCES(x)
67#define GENERIC_VARIATION_SEQUENCES(x) (x>=0xFE00 && x<=0xFE0F) ? x : 0
68#define IDEOGRAPHICS_VARIATION_SEQUENCES(x) (x>=0xE0100 && x<=0xE01EF) ? x : 0
69#define MANGOLIAN_VARIATION_SEQUENCES(x) (x>=0x180B && x<=0x180D) ? x : 0
70/**
71 * http://unicode.org/emoji/charts/emoji-variants.html
72*/
73#define VARIATION_EMOJI_PRESENTATION 0xFE0F
74#define VARIATION_TEXT_PRESENTATION 0xFE0E
75
76/**
77 * These Options (Flags) are used with evas_common_font_glyph_search function
78 */
79#define EVAS_FONT_SEARCH_OPTION_NONE 0x0000
80#define EVAS_FONT_SEARCH_OPTION_SKIP_COLOR 0x0001
81
82 59
83#define FASH_INT_MAGIC 0x01012345
84#define FASH_GLYPH_MAGIC 0x02012345
85 60
86enum _Evas_Font_Style 61enum _Evas_Font_Style
87{ 62{
@@ -153,10 +128,6 @@ typedef struct _RGBA_Font_Source RGBA_Font_Source;
153typedef struct _RGBA_Font_Glyph RGBA_Font_Glyph; 128typedef struct _RGBA_Font_Glyph RGBA_Font_Glyph;
154typedef struct _RGBA_Font_Glyph_Out RGBA_Font_Glyph_Out; 129typedef struct _RGBA_Font_Glyph_Out RGBA_Font_Glyph_Out;
155 130
156typedef struct _Fash_Item_variation_Index_Item Fash_Item_variation_Index_Item;
157typedef struct _Fash_Item_variation_List Fash_Item_variation_List;
158typedef struct _Fash_Item_Index_Map_Variations Fash_Item_Index_Map_Variations;
159
160typedef struct _Fash_Item_Index_Map Fash_Item_Index_Map; 131typedef struct _Fash_Item_Index_Map Fash_Item_Index_Map;
161typedef struct _Fash_Int_Map Fash_Int_Map; 132typedef struct _Fash_Int_Map Fash_Int_Map;
162typedef struct _Fash_Int_Map2 Fash_Int_Map2; 133typedef struct _Fash_Int_Map2 Fash_Int_Map2;
@@ -168,25 +139,9 @@ struct _Fash_Item_Index_Map
168 RGBA_Font_Int *fint; 139 RGBA_Font_Int *fint;
169 int index; 140 int index;
170}; 141};
171struct _Fash_Item_variation_Index_Item
172{
173 Fash_Item_Index_Map item;
174 Eina_Unicode variation_sequence;
175};
176struct _Fash_Item_variation_List
177{
178 Fash_Item_variation_Index_Item *list;
179 size_t length;
180 size_t capacity;
181};
182struct _Fash_Item_Index_Map_Variations
183{
184 Fash_Item_Index_Map item;
185 Fash_Item_variation_List *variations;
186};
187struct _Fash_Int_Map 142struct _Fash_Int_Map
188{ 143{
189 Fash_Item_Index_Map_Variations items[256]; 144 Fash_Item_Index_Map item[256];
190}; 145};
191struct _Fash_Int_Map2 146struct _Fash_Int_Map2
192{ 147{
@@ -194,7 +149,6 @@ struct _Fash_Int_Map2
194}; 149};
195struct _Fash_Int 150struct _Fash_Int
196{ 151{
197 unsigned int MAGIC;
198 Fash_Int_Map2 *bucket[256]; 152 Fash_Int_Map2 *bucket[256];
199 void (*freeme) (Fash_Int *fash); 153 void (*freeme) (Fash_Int *fash);
200}; 154};
@@ -212,7 +166,6 @@ struct _Fash_Glyph_Map2
212}; 166};
213struct _Fash_Glyph 167struct _Fash_Glyph
214{ 168{
215 unsigned int MAGIC;
216 Fash_Glyph_Map2 *bucket[256]; 169 Fash_Glyph_Map2 *bucket[256];
217 void (*freeme) (Fash_Glyph *fash); 170 void (*freeme) (Fash_Glyph *fash);
218}; 171};
@@ -394,7 +347,7 @@ void *evas_common_font_freetype_face_get(RGBA_Font *font); /* XXX: Not EAPI on p
394 347
395EAPI RGBA_Font_Glyph *evas_common_font_int_cache_glyph_get (RGBA_Font_Int *fi, FT_UInt index); 348EAPI RGBA_Font_Glyph *evas_common_font_int_cache_glyph_get (RGBA_Font_Int *fi, FT_UInt index);
396EAPI Eina_Bool evas_common_font_int_cache_glyph_render(RGBA_Font_Glyph *fg); 349EAPI Eina_Bool evas_common_font_int_cache_glyph_render(RGBA_Font_Glyph *fg);
397EAPI FT_UInt evas_common_get_char_index (RGBA_Font_Int* fi, Eina_Unicode gl, Eina_Unicode variation_sequence); 350EAPI FT_UInt evas_common_get_char_index (RGBA_Font_Int* fi, Eina_Unicode gl);
398 351
399/* load */ 352/* load */
400EAPI void evas_common_font_dpi_set (int dpi_h, int dpi_v); 353EAPI void evas_common_font_dpi_set (int dpi_h, int dpi_v);
@@ -444,7 +397,7 @@ EAPI void evas_common_font_ascent_descent_get(RGBA_Font *fn, const
444 397
445EAPI void *evas_common_font_glyph_compress(void *data, int num_grays, int pixel_mode, int pitch_data, int w, int h, int *size_ret); 398EAPI void *evas_common_font_glyph_compress(void *data, int num_grays, int pixel_mode, int pitch_data, int w, int h, int *size_ret);
446EAPI DATA8 *evas_common_font_glyph_uncompress(RGBA_Font_Glyph *fg, int *wret, int *hret); 399EAPI DATA8 *evas_common_font_glyph_uncompress(RGBA_Font_Glyph *fg, int *wret, int *hret);
447EAPI int evas_common_font_glyph_search (RGBA_Font *fn, RGBA_Font_Int **fi_ret, Eina_Unicode gl, Eina_Unicode variation_sequence, uint32_t evas_font_search_options); 400EAPI int evas_common_font_glyph_search (RGBA_Font *fn, RGBA_Font_Int **fi_ret, Eina_Unicode gl);
448 401
449void evas_common_font_load_init(void); 402void evas_common_font_load_init(void);
450void evas_common_font_load_shutdown(void); 403void evas_common_font_load_shutdown(void);
diff --git a/src/lib/evas/common/evas_font_load.c b/src/lib/evas/common/evas_font_load.c
index 3aa2070499..f2011bd72f 100644
--- a/src/lib/evas/common/evas_font_load.c
+++ b/src/lib/evas/common/evas_font_load.c
@@ -687,11 +687,7 @@ evas_common_font_free(RGBA_Font *fn)
687 evas_common_font_int_unref(fi); 687 evas_common_font_int_unref(fi);
688 evas_common_font_flush(); 688 evas_common_font_flush();
689 eina_list_free(fn->fonts); 689 eina_list_free(fn->fonts);
690 if (fn->fash) 690 if (fn->fash) fn->fash->freeme(fn->fash);
691 {
692 fn->fash->freeme(fn->fash);
693 fn->fash = NULL;
694 }
695 LKD(fn->lock); 691 LKD(fn->lock);
696 free(fn); 692 free(fn);
697} 693}
diff --git a/src/lib/evas/common/evas_font_main.c b/src/lib/evas/common/evas_font_main.c
index c41e350dcf..1a163748ca 100644
--- a/src/lib/evas/common/evas_font_main.c
+++ b/src/lib/evas/common/evas_font_main.c
@@ -355,182 +355,33 @@ end:
355/* Set of common functions that are used in a couple of places. */ 355/* Set of common functions that are used in a couple of places. */
356 356
357static void 357static void
358_fash_int_map_and_variations_free(Fash_Int_Map *map)
359 {
360 if(!map)
361 return;
362 int i;
363
364 for (i = 0; i < 256; i++)
365 {
366 if (map->items[i].variations)
367 {
368 if (map->items[i].variations->list)
369 {
370 free(map->items[i].variations->list);
371 map->items[i].variations->list = NULL;
372 map->items[i].variations->capacity = 0;
373 map->items[i].variations->length = 0;
374 }
375 free(map->items[i].variations);
376 map->items[i].variations = NULL;
377 }
378 }
379
380 free(map);
381}
382
383static void
384_fash_int2_free(Fash_Int_Map2 *fash) 358_fash_int2_free(Fash_Int_Map2 *fash)
385 { 359{
386 int i; 360 int i;
387 if (fash) 361
388 { 362 for (i = 0; i < 256; i++) if (fash->bucket[i]) free(fash->bucket[i]);
389 for (i = 0; i < 256; i++) 363 free(fash);
390 if (fash->bucket[i])
391 {
392 _fash_int_map_and_variations_free(fash->bucket[i]);
393 fash->bucket[i] = NULL;
394 }
395 free(fash);
396 fash = NULL;
397 }
398} 364}
399 365
400static void 366static void
401_fash_int_free(Fash_Int *fash) 367_fash_int_free(Fash_Int *fash)
402{ 368{
403 int i; 369 int i;
404 if (fash)
405 {
406 if (fash->MAGIC != FASH_INT_MAGIC)
407 {
408 return;
409 }
410 370
411 for (i = 0; i < 256; i++) 371 for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_int2_free(fash->bucket[i]);
412 { 372 free(fash);
413 if (fash->bucket[i])
414 {
415 _fash_int2_free(fash->bucket[i]);
416 fash->bucket[i] = NULL;
417 }
418 }
419 free(fash);
420 }
421} 373}
422 374
423static Fash_Int * 375static Fash_Int *
424_fash_int_new(void) 376_fash_int_new(void)
425{ 377{
426 Fash_Int *fash = calloc(1, sizeof(Fash_Int)); 378 Fash_Int *fash = calloc(1, sizeof(Fash_Int));
427 EINA_SAFETY_ON_NULL_RETURN_VAL(fash, NULL);
428 fash->MAGIC = FASH_INT_MAGIC;
429 fash->freeme = _fash_int_free; 379 fash->freeme = _fash_int_free;
430 return fash; 380 return fash;
431} 381}
432 382
433static Fash_Item_variation_List *
434_variations_list_new(void)
435{
436 Fash_Item_variation_List *variations = calloc(1, sizeof(Fash_Item_variation_List));
437 EINA_SAFETY_ON_NULL_RETURN_VAL(variations, NULL);
438 variations->capacity = 0;
439 variations->length = 0;
440 variations->list = 0;
441 return variations;
442}
443
444static void
445_variations_list_add(Fash_Item_variation_List *variations,RGBA_Font_Int *fint, int index, Eina_Unicode variation_sequence)
446{
447 Fash_Item_variation_Index_Item *list = variations->list;
448 if (variations->capacity == variations->length)
449 {
450 list = (Fash_Item_variation_Index_Item *) realloc(list, (variations->capacity + 4) * sizeof(Fash_Item_variation_Index_Item));
451 if (list)
452 {
453 variations->list = list;
454 variations->capacity += 4;
455 }
456 }
457
458 EINA_SAFETY_ON_NULL_RETURN(list);
459
460 int start = 0;
461 int end = variations->length;
462 if (end == 0)
463 {
464 // if only on element just add it in 0 index
465 variations->list[0].item.fint = fint;
466 variations->list[0].item.index = index;
467 variations->list[0].variation_sequence = variation_sequence;
468 variations->length++;
469 }
470 else
471 {
472 // find lower bound
473 while (end > start)
474 {
475 int middle = start + (end - start) / 2;
476 if (variations->list[middle].variation_sequence >= variation_sequence)
477 end = middle;
478 else
479 start = middle + 1;
480 }
481
482 // if passed value founded in list, just replace it
483 if (start < (int)variations->length && variations->list[start].variation_sequence == variation_sequence)
484 {
485 variations->list[start].item.fint = fint;
486 variations->list[start].item.index = index;
487 variations->list[start].variation_sequence = variation_sequence;
488 return;
489 }
490
491 // shift array to insert item
492 for (int i = (variations->length - 1) ; i >= start; i--)
493 {
494 variations->list[i + 1] = variations->list[i];
495 }
496
497 // insert new item and keep array sorted
498 variations->list[start].item.fint = fint;
499 variations->list[start].item.index = index;
500 variations->list[start].variation_sequence = variation_sequence;
501 variations->length++;
502 }
503}
504
505
506static Fash_Item_Index_Map * 383static Fash_Item_Index_Map *
507_variations_list_find(Fash_Item_variation_List * variations, Eina_Unicode variation_sequence) 384_fash_int_find(Fash_Int *fash, int item)
508{
509 if (!variations)
510 return NULL;
511
512 if (!variations->list)
513 return NULL;
514
515 int start = 0;
516 int end = variations->length;
517
518 while(end > start)
519 {
520 int middle = start + (end - start) / 2;
521 if (variations->list[middle].variation_sequence == variation_sequence)
522 return &(variations->list[middle].item);
523 else if (variations->list[middle].variation_sequence < variation_sequence)
524 start = middle + 1;
525 else
526 end = middle - 1;
527 }
528
529 return NULL;
530}
531
532static const Fash_Item_Index_Map *
533_fash_int_find(Fash_Int *fash, int item, Eina_Unicode variation_sequence)
534{ 385{
535 int grp, maj, min; 386 int grp, maj, min;
536 387
@@ -540,22 +391,14 @@ _fash_int_find(Fash_Int *fash, int item, Eina_Unicode variation_sequence)
540 min = item & 0xff; 391 min = item & 0xff;
541 if (!fash->bucket[grp]) return NULL; 392 if (!fash->bucket[grp]) return NULL;
542 if (!fash->bucket[grp]->bucket[maj]) return NULL; 393 if (!fash->bucket[grp]->bucket[maj]) return NULL;
543 if (!variation_sequence) 394 return &(fash->bucket[grp]->bucket[maj]->item[min]);
544 return &(fash->bucket[grp]->bucket[maj]->items[min].item);
545 else
546 return _variations_list_find(fash->bucket[grp]->bucket[maj]->items[min].variations, variation_sequence);
547} 395}
548 396
549static void 397static void
550_fash_int_add(Fash_Int *fash, int item, RGBA_Font_Int *fint, int idx, Eina_Unicode variation_sequence) 398_fash_int_add(Fash_Int *fash, int item, RGBA_Font_Int *fint, int idx)
551{ 399{
552 int grp, maj, min; 400 int grp, maj, min;
553 401
554 // If we already have cached passed item, skip adding it again
555 const Fash_Item_Index_Map *fm = _fash_int_find(fash, item, variation_sequence);
556 if (fm && fm->fint)
557 return;
558
559 // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16) 402 // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
560 grp = (item >> 16) & 0xff; 403 grp = (item >> 16) & 0xff;
561 maj = (item >> 8) & 0xff; 404 maj = (item >> 8) & 0xff;
@@ -566,20 +409,8 @@ _fash_int_add(Fash_Int *fash, int item, RGBA_Font_Int *fint, int idx, Eina_Unico
566 if (!fash->bucket[grp]->bucket[maj]) 409 if (!fash->bucket[grp]->bucket[maj])
567 fash->bucket[grp]->bucket[maj] = calloc(1, sizeof(Fash_Int_Map)); 410 fash->bucket[grp]->bucket[maj] = calloc(1, sizeof(Fash_Int_Map));
568 EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]->bucket[maj]); 411 EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]->bucket[maj]);
569 if (variation_sequence) 412 fash->bucket[grp]->bucket[maj]->item[min].fint = fint;
570 { 413 fash->bucket[grp]->bucket[maj]->item[min].index = idx;
571 if (!fash->bucket[grp]->bucket[maj]->items[min].variations)
572 {
573 fash->bucket[grp]->bucket[maj]->items[min].variations =_variations_list_new();
574 EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]->bucket[maj]->items[min].variations);
575 }
576 _variations_list_add(fash->bucket[grp]->bucket[maj]->items[min].variations, fint, idx, variation_sequence);
577 }
578 else
579 {
580 fash->bucket[grp]->bucket[maj]->items[min].item.fint = fint;
581 fash->bucket[grp]->bucket[maj]->items[min].item.index = idx;
582 }
583} 414}
584 415
585static void 416static void
@@ -631,45 +462,24 @@ _fash_gl2_free(Fash_Glyph_Map2 *fash)
631 int i; 462 int i;
632 463
633 // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16) 464 // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
634 for (i = 0; i < 256; i++) 465 for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_glyph_free(fash->bucket[i]);
635 {
636 if (fash->bucket[i])
637 {
638 _fash_glyph_free(fash->bucket[i]);
639 fash->bucket[i] = NULL;
640 }
641 }
642 free(fash); 466 free(fash);
643} 467}
644 468
645static void 469static void
646_fash_gl_free(Fash_Glyph *fash) 470_fash_gl_free(Fash_Glyph *fash)
647{ 471{
648 if (fash) 472 int i;
649 {
650 if (fash->MAGIC != FASH_GLYPH_MAGIC)
651 return;
652 473
653 int i; 474 // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
654 // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16) 475 for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_gl2_free(fash->bucket[i]);
655 for (i = 0; i < 256; i++) 476 free(fash);
656 {
657 if (fash->bucket[i])
658 {
659 _fash_gl2_free(fash->bucket[i]);
660 fash->bucket[i] = NULL;
661 }
662 }
663 free(fash);
664 }
665} 477}
666 478
667static Fash_Glyph * 479static Fash_Glyph *
668_fash_gl_new(void) 480_fash_gl_new(void)
669{ 481{
670 Fash_Glyph *fash = calloc(1, sizeof(Fash_Glyph)); 482 Fash_Glyph *fash = calloc(1, sizeof(Fash_Glyph));
671 EINA_SAFETY_ON_NULL_RETURN_VAL(fash, NULL);
672 fash->MAGIC = FASH_GLYPH_MAGIC;
673 fash->freeme = _fash_gl_free; 483 fash->freeme = _fash_gl_free;
674 return fash; 484 return fash;
675} 485}
@@ -870,7 +680,7 @@ struct _Font_Char_Index
870}; 680};
871 681
872EAPI FT_UInt 682EAPI FT_UInt
873evas_common_get_char_index(RGBA_Font_Int* fi, Eina_Unicode gl, Eina_Unicode variation_sequence) 683evas_common_get_char_index(RGBA_Font_Int* fi, Eina_Unicode gl)
874{ 684{
875 static const unsigned short mapfix[] = 685 static const unsigned short mapfix[] =
876 { 686 {
@@ -932,10 +742,7 @@ evas_common_get_char_index(RGBA_Font_Int* fi, Eina_Unicode gl, Eina_Unicode vari
932 * that something else try to use it. 742 * that something else try to use it.
933 */ 743 */
934 /* FTLOCK(); */ 744 /* FTLOCK(); */
935 if (variation_sequence) 745 result.index = FT_Get_Char_Index(fi->src->ft.face, gl);
936 result.index = FT_Face_GetCharVariantIndex(fi->src->ft.face, gl, variation_sequence);
937 else
938 result.index = FT_Get_Char_Index(fi->src->ft.face, gl);
939 /* FTUNLOCK(); */ 746 /* FTUNLOCK(); */
940 result.gl = gl; 747 result.gl = gl;
941 748
@@ -967,10 +774,7 @@ evas_common_get_char_index(RGBA_Font_Int* fi, Eina_Unicode gl, Eina_Unicode vari
967 { 774 {
968 gl = mapfix[(i << 1) + 1]; 775 gl = mapfix[(i << 1) + 1];
969 FTLOCK(); 776 FTLOCK();
970 if (variation_sequence) 777 result.index = FT_Get_Char_Index(fi->src->ft.face, gl);
971 result.index = FT_Face_GetCharVariantIndex(fi->src->ft.face, gl, variation_sequence);
972 else
973 result.index = FT_Get_Char_Index(fi->src->ft.face, gl);
974 FTUNLOCK(); 778 FTUNLOCK();
975 break; 779 break;
976 } 780 }
@@ -995,49 +799,20 @@ evas_common_get_char_index(RGBA_Font_Int* fi, Eina_Unicode gl, Eina_Unicode vari
995 return result.index; 799 return result.index;
996} 800}
997 801
998
999/*
1000 * @internal
1001 * Search for unicode glyph inside all font files, and return font and glyph index
1002 *
1003 * @param[in] fn the font to use.
1004 * @param[out] fi_ret founded font.
1005 * @param[in] gl unicode glyph to search for
1006 * @param[in] variation_sequence for the gl glyph
1007 * @param[in] evas_font_search_options search options when searching font files
1008 *
1009 */
1010
1011EAPI int 802EAPI int
1012evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, Eina_Unicode gl, Eina_Unicode variation_sequence, uint32_t evas_font_search_options) 803evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, Eina_Unicode gl)
1013{ 804{
1014 Eina_List *l; 805 Eina_List *l;
1015 806
1016 if (fn->fash) 807 if (fn->fash)
1017 { 808 {
1018 const Fash_Item_Index_Map *fm = _fash_int_find(fn->fash, gl, variation_sequence); 809 Fash_Item_Index_Map *fm = _fash_int_find(fn->fash, gl);
1019 if (fm) 810 if (fm)
1020 { 811 {
1021 if (fm->fint) 812 if (fm->fint)
1022 { 813 {
1023 if (evas_font_search_options == EVAS_FONT_SEARCH_OPTION_NONE) 814 *fi_ret = fm->fint;
1024 { 815 return fm->index;
1025 *fi_ret = fm->fint;
1026 return fm->index;
1027 }
1028 else if( (evas_font_search_options & EVAS_FONT_SEARCH_OPTION_SKIP_COLOR) == EVAS_FONT_SEARCH_OPTION_SKIP_COLOR)
1029 {
1030 if (!fm->fint->src->ft.face)
1031 {
1032 evas_common_font_int_reload(fm->fint);
1033 }
1034
1035 if (fm->fint->src->ft.face && !FT_HAS_COLOR(fm->fint->src->ft.face))
1036 {
1037 *fi_ret = fm->fint;
1038 return fm->index;
1039 }
1040 }
1041 } 816 }
1042 else if (fm->index == -1) return 0; 817 else if (fm->index == -1) return 0;
1043 } 818 }
@@ -1076,35 +851,20 @@ evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, Eina_Unicod
1076 } 851 }
1077 if (fi->src->ft.face) 852 if (fi->src->ft.face)
1078 { 853 {
1079 Eina_Bool is_color_only = (evas_font_search_options & EVAS_FONT_SEARCH_OPTION_SKIP_COLOR) == EVAS_FONT_SEARCH_OPTION_SKIP_COLOR && 854 idx = evas_common_get_char_index(fi, gl);
1080 FT_HAS_COLOR(fi->src->ft.face);
1081
1082 if (is_color_only)
1083 {
1084 /* This is color font ignore it */
1085 continue;
1086 }
1087
1088 idx = (int) evas_common_get_char_index(fi, gl, variation_sequence);
1089 if (idx != 0) 855 if (idx != 0)
1090 { 856 {
1091 if (!fi->ft.size) 857 if (!fi->ft.size)
1092 evas_common_font_int_load_complete(fi); 858 evas_common_font_int_load_complete(fi);
1093 if (!is_color_only) 859 if (!fn->fash) fn->fash = _fash_int_new();
1094 { 860 if (fn->fash) _fash_int_add(fn->fash, gl, fi, idx);
1095 if (!fn->fash) fn->fash = _fash_int_new();
1096 if (fn->fash) _fash_int_add(fn->fash, gl, fi, idx, variation_sequence);
1097 }
1098 *fi_ret = fi; 861 *fi_ret = fi;
1099 return idx; 862 return idx;
1100 } 863 }
1101 else 864 else
1102 { 865 {
1103 if (!is_color_only) 866 if (!fn->fash) fn->fash = _fash_int_new();
1104 { 867 if (fn->fash) _fash_int_add(fn->fash, gl, NULL, -1);
1105 if (!fn->fash) fn->fash = _fash_int_new();
1106 if (fn->fash) _fash_int_add(fn->fash, gl, NULL, -1, variation_sequence);
1107 }
1108 } 868 }
1109 } 869 }
1110 } 870 }
diff --git a/src/lib/evas/common/evas_font_query.c b/src/lib/evas/common/evas_font_query.c
index 7b50a74e62..1ff0447963 100644
--- a/src/lib/evas/common/evas_font_query.c
+++ b/src/lib/evas/common/evas_font_query.c
@@ -32,9 +32,6 @@ evas_common_font_query_run_font_end_get(RGBA_Font *fn, RGBA_Font_Int **script_fi
32 (evas_common_language_char_script_get(*base_char) != script) ; 32 (evas_common_language_char_script_get(*base_char) != script) ;
33 base_char++) 33 base_char++)
34 ; 34 ;
35 /* If counter reach variation sequence it is safe to pick default font */
36 if(VAR_SEQ(*base_char) || (base_char != run_end && VAR_SEQ(*(base_char+1)))) goto get_top_font;
37
38 if (base_char == run_end) base_char = text; 35 if (base_char == run_end) base_char = text;
39 36
40 /* Find the first renderable char */ 37 /* Find the first renderable char */
@@ -43,7 +40,7 @@ evas_common_font_query_run_font_end_get(RGBA_Font *fn, RGBA_Font_Int **script_fi
43 /* 0x1F is the last ASCII contral char, just a hack in 40 /* 0x1F is the last ASCII contral char, just a hack in
44 * the meanwhile. */ 41 * the meanwhile. */
45 if ((*base_char > 0x1F) && 42 if ((*base_char > 0x1F) &&
46 evas_common_font_glyph_search(fn, &fi, *base_char, 0, EVAS_FONT_SEARCH_OPTION_NONE)) 43 evas_common_font_glyph_search(fn, &fi, *base_char))
47 break; 44 break;
48 base_char++; 45 base_char++;
49 } 46 }
@@ -52,8 +49,7 @@ evas_common_font_query_run_font_end_get(RGBA_Font *fn, RGBA_Font_Int **script_fi
52 /* If everything else fails, at least try to find a font for the 49 /* If everything else fails, at least try to find a font for the
53 * replacement char */ 50 * replacement char */
54 if (base_char == run_end) 51 if (base_char == run_end)
55 evas_common_font_glyph_search(fn, &fi, REPLACEMENT_CHAR, 0, EVAS_FONT_SEARCH_OPTION_NONE); 52 evas_common_font_glyph_search(fn, &fi, REPLACEMENT_CHAR);
56get_top_font:
57 53
58 if (!fi) 54 if (!fi)
59 fi = fn->fonts->data; 55 fi = fn->fonts->data;
@@ -84,17 +80,15 @@ get_top_font:
84 if (evas_common_language_char_script_get(*itr) == EVAS_SCRIPT_INHERITED) 80 if (evas_common_language_char_script_get(*itr) == EVAS_SCRIPT_INHERITED)
85 continue; 81 continue;
86 82
87 Eina_Unicode variation_sequence = VAR_SEQ(*(itr+1));
88
89 /* Break if either it's not in the font, or if it is in the 83 /* Break if either it's not in the font, or if it is in the
90 * script's font. */ 84 * script's font. */
91 if (!evas_common_get_char_index(fi, *itr, variation_sequence)) 85 if (!evas_common_get_char_index(fi, *itr))
92 break; 86 break;
93 87
94 if (fi != *script_fi) 88 if (fi != *script_fi)
95 { 89 {
96 if (evas_common_get_char_index(*script_fi, *itr, variation_sequence)) 90 if (evas_common_get_char_index(*script_fi, *itr))
97 break; 91 break;
98 } 92 }
99 } 93 }
100 94
@@ -108,25 +102,10 @@ get_top_font:
108 /* If we can find a font, use it. Otherwise, find the first 102 /* If we can find a font, use it. Otherwise, find the first
109 * char the run of chars that can't be rendered until the first 103 * char the run of chars that can't be rendered until the first
110 * one that can. */ 104 * one that can. */
111 Eina_Unicode variation_sequence = VAR_SEQ(*(itr+1)); 105 if (evas_common_font_glyph_search(fn, &tmp_fi, *itr))
112 if (evas_common_font_glyph_search(fn, &tmp_fi, *itr, variation_sequence, EVAS_FONT_SEARCH_OPTION_NONE))
113 { 106 {
114 fi = tmp_fi; 107 fi = tmp_fi;
115 } 108 }
116 else if ( (variation_sequence == VARIATION_TEXT_PRESENTATION) && evas_common_font_glyph_search(fn, &tmp_fi, *itr, 0, EVAS_FONT_SEARCH_OPTION_SKIP_COLOR))
117 {
118 /* If we can not find unicode with variation sequence, then we will
119 Search and find for non color glyph because variation sequence is Text
120 */
121 fi = tmp_fi;
122 }
123 else if ( variation_sequence && evas_common_font_glyph_search(fn, &tmp_fi, *itr, 0, EVAS_FONT_SEARCH_OPTION_NONE))
124 {
125 /* If we can not find unicode with variation sequence, then we will
126 Search and find glyph without the variation sequence
127 */
128 fi = tmp_fi;
129 }
130 else 109 else
131 { 110 {
132 itr++; 111 itr++;
@@ -134,13 +113,9 @@ get_top_font:
134 * font */ 113 * font */
135 for ( ; itr < run_end ; itr++) 114 for ( ; itr < run_end ; itr++)
136 { 115 {
137 if(VAR_SEQ(*itr))
138 continue;
139
140 Eina_Unicode variation_sequence = VAR_SEQ(*(itr+1));
141 tmp_fi = fi; 116 tmp_fi = fi;
142 if (evas_common_get_char_index(fi, *itr, variation_sequence) || 117 if (evas_common_get_char_index(fi, *itr) ||
143 evas_common_font_glyph_search(fn, &tmp_fi, *itr, variation_sequence, EVAS_FONT_SEARCH_OPTION_NONE)) 118 evas_common_font_glyph_search(fn, &tmp_fi, *itr))
144 { 119 {
145 fi = tmp_fi; 120 fi = tmp_fi;
146 break; 121 break;
@@ -152,9 +127,9 @@ get_top_font:
152 * find a font most suitable for the replacement char and 127 * find a font most suitable for the replacement char and
153 * break */ 128 * break */
154 if ((itr == run_end) || 129 if ((itr == run_end) ||
155 !evas_common_get_char_index(fi, REPLACEMENT_CHAR, 0)) 130 !evas_common_get_char_index(fi, REPLACEMENT_CHAR))
156 { 131 {
157 evas_common_font_glyph_search(fn, &fi, REPLACEMENT_CHAR, 0, EVAS_FONT_SEARCH_OPTION_NONE); 132 evas_common_font_glyph_search(fn, &fi, REPLACEMENT_CHAR);
158 break; 133 break;
159 } 134 }
160 } 135 }
@@ -165,11 +140,8 @@ get_top_font:
165 /* If this char is not renderable by any font, but the replacement 140 /* If this char is not renderable by any font, but the replacement
166 * char can be rendered using the currentfont, continue this 141 * char can be rendered using the currentfont, continue this
167 * run. */ 142 * run. */
168 Eina_Unicode variation_sequence = VAR_SEQ(*(itr+1)); 143 if (!evas_common_font_glyph_search(fn, &tmp_fi, *itr) &&
169 144 evas_common_get_char_index(fi, REPLACEMENT_CHAR))
170 if (!evas_common_font_glyph_search(fn, &tmp_fi, *itr, variation_sequence, EVAS_FONT_SEARCH_OPTION_NONE) &&
171 (variation_sequence ? !evas_common_font_glyph_search(fn, &tmp_fi, *itr, 0, EVAS_FONT_SEARCH_OPTION_NONE) : 1) &&
172 evas_common_get_char_index(fi, REPLACEMENT_CHAR, 0))
173 { 145 {
174 itr++; 146 itr++;
175 } 147 }
diff --git a/src/lib/evas/common/evas_text_utils.c b/src/lib/evas/common/evas_text_utils.c
index acf7cf8fb7..e9c5cc2c94 100644
--- a/src/lib/evas/common/evas_text_utils.c
+++ b/src/lib/evas/common/evas_text_utils.c
@@ -1066,7 +1066,7 @@ _content_create_ot(RGBA_Font_Int *fi, const Eina_Unicode *text,
1066 /* If we got a malformed index, show the replacement char instead */ 1066 /* If we got a malformed index, show the replacement char instead */
1067 if (gl_itr->index == 0) 1067 if (gl_itr->index == 0)
1068 { 1068 {
1069 gl_itr->index = evas_common_get_char_index(fi, REPLACEMENT_CHAR, 0); 1069 gl_itr->index = evas_common_get_char_index(fi, REPLACEMENT_CHAR);
1070 is_replacement = EINA_TRUE; 1070 is_replacement = EINA_TRUE;
1071 } 1071 }
1072 idx = gl_itr->index; 1072 idx = gl_itr->index;
@@ -1172,10 +1172,10 @@ _content_create_regular(RGBA_Font_Int *fi, const Eina_Unicode *text,
1172 _gl = *text; 1172 _gl = *text;
1173 if (_gl == 0) break; 1173 if (_gl == 0) break;
1174 1174
1175 idx = evas_common_get_char_index(fi, _gl, 0); 1175 idx = evas_common_get_char_index(fi, _gl);
1176 if (idx == 0) 1176 if (idx == 0)
1177 { 1177 {
1178 idx = evas_common_get_char_index(fi, REPLACEMENT_CHAR, 0); 1178 idx = evas_common_get_char_index(fi, REPLACEMENT_CHAR);
1179 } 1179 }
1180 1180
1181 fg = evas_common_font_int_cache_glyph_get(fi, idx); 1181 fg = evas_common_font_int_cache_glyph_get(fi, idx);
diff --git a/src/tests/evas/evas_test_textblock.c b/src/tests/evas/evas_test_textblock.c
index 2db6888b12..f61574c065 100644
--- a/src/tests/evas/evas_test_textblock.c
+++ b/src/tests/evas/evas_test_textblock.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * TODO: 2 * TODO:
3 * * Test different font loading mechanisms. 3 * * Test different font lodaing mechanisms.
4 */ 4 */
5 5
6#ifdef HAVE_CONFIG_H 6#ifdef HAVE_CONFIG_H
@@ -4129,23 +4129,6 @@ EFL_START_TEST(evas_textblock_obstacle)
4129} 4129}
4130EFL_END_TEST; 4130EFL_END_TEST;
4131 4131
4132EFL_START_TEST(evas_textblock_variation_sequence)
4133{
4134 START_TB_TEST();
4135 evas_font_path_global_prepend("..");
4136 const char *str1 = "8&#xfe0f;&#x262a;&#xfe0f;";
4137 const char *str2 = "8&#xfe0e;&#x262a;&#xfe0e;";
4138 Evas_Coord fw, fh,fw_new, fh_new;
4139 evas_object_textblock_text_markup_set(tb, str1);
4140 evas_object_textblock_size_formatted_get(tb, &fw, &fh);
4141 evas_object_textblock_text_markup_set(tb, str2);
4142 evas_object_textblock_size_formatted_get(tb, &fw_new, &fh_new);
4143 fail_if(fw_new == fw && fh_new == fh);
4144
4145 END_TB_TEST();
4146}
4147EFL_END_TEST;
4148
4149#ifdef HAVE_HYPHEN 4132#ifdef HAVE_HYPHEN
4150static void 4133static void
4151_hyphenation_width_stress(Evas_Object *tb, Evas_Textblock_Cursor *cur) 4134_hyphenation_width_stress(Evas_Object *tb, Evas_Textblock_Cursor *cur)
@@ -4746,7 +4729,6 @@ void evas_test_textblock(TCase *tc)
4746 tcase_add_test(tc, evas_textblock_items); 4729 tcase_add_test(tc, evas_textblock_items);
4747 tcase_add_test(tc, evas_textblock_delete); 4730 tcase_add_test(tc, evas_textblock_delete);
4748 tcase_add_test(tc, evas_textblock_obstacle); 4731 tcase_add_test(tc, evas_textblock_obstacle);
4749 tcase_add_test(tc, evas_textblock_variation_sequence);
4750#ifdef HAVE_HYPHEN 4732#ifdef HAVE_HYPHEN
4751 tcase_add_test(tc, evas_textblock_hyphenation); 4733 tcase_add_test(tc, evas_textblock_hyphenation);
4752#endif 4734#endif
diff --git a/src/tests/evas/fonts/NotoColorEmoji.ttf b/src/tests/evas/fonts/NotoColorEmoji.ttf
deleted file mode 100644
index 69cf21a1a9..0000000000
--- a/src/tests/evas/fonts/NotoColorEmoji.ttf
+++ /dev/null
Binary files differ
diff --git a/src/tests/evas/fonts/NotoEmoji-Regular.ttf b/src/tests/evas/fonts/NotoEmoji-Regular.ttf
deleted file mode 100644
index 19b7badf4a..0000000000
--- a/src/tests/evas/fonts/NotoEmoji-Regular.ttf
+++ /dev/null
Binary files differ