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 46f2d8acdc.
This commit is contained in:
Carsten Haitzler 2019-10-31 12:21:59 +00:00
parent 72a5367f8d
commit 80d317f20e
10 changed files with 49 additions and 412 deletions

View File

@ -243,7 +243,6 @@ void test_label_wrap(void *data, Evas_Object *obj, void *event_info);
void test_label_ellipsis(void *data, Evas_Object *obj, void *event_info);
void test_label_colors(void *data, Evas_Object *obj, void *event_info);
void test_label_emoji(void *data, Evas_Object *obj, void *event_info);
void test_label_variation_sequence(void *data, Evas_Object *obj, void *event_info);
void test_conformant(void *data, Evas_Object *obj, void *event_info);
void test_conformant2(void *data, Evas_Object *obj, void *event_info);
void test_conformant_indicator(void *data, Evas_Object *obj, void *event_info);
@ -1211,7 +1210,6 @@ add_tests:
ADD_TEST(NULL, "Text", "Label Ellipsis", test_label_ellipsis);
ADD_TEST(NULL, "Text", "Label Colors", test_label_colors);
ADD_TEST(NULL, "Text", "Label Emoji", test_label_emoji);
ADD_TEST(NULL, "Text", "Label Variation Sequnece", test_label_variation_sequence);
ADD_TEST_EO(NULL, "Text", "Efl.Ui.Textpath", test_ui_textpath);
//------------------------------//

View File

@ -403,30 +403,6 @@ test_label_colors(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *ev
evas_object_show(win);
}
/*** Label variation sequence **************************************************************/
void
test_label_variation_sequence(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Evas_Object *win, *lb;
win = elm_win_util_standard_add("label-variation sequence", "Label variation sequnece");
elm_win_autodel_set(win, EINA_TRUE);
lb = elm_label_add(win);
elm_object_text_set(lb,
"You need to have at least on font contains variation sequence<br>"
"Three different 8 glyphs : <br>"
"8<tab>8&#xfe0f;<tab>8&#xfe0f;&#x20E3;<br>"
"line with 3 variation glyphs : <br>"
"8&#xfe0f;&#x20E3;&#x262a;&#xfe0f;AAA&#x262a;&#xfe0E;1234567&#xfe0f;&#x20E3;"
);
evas_object_size_hint_weight_set(lb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
elm_win_resize_object_add(win, lb);
evas_object_show(lb);
evas_object_show(win);
}
/*** Label Emoji *************************************************************/
static char *
_fontlist_text_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part EINA_UNUSED)

View File

@ -56,32 +56,7 @@ typedef unsigned long long DATA64;
#define LKU(x) eina_lock_release(&(x))
#define LKDBG(x) eina_lock_debug(&(x))
/**
* See explanation of variation_sequences at:
* https://unicode.org/Public/UCD/latest/ucd/StandardizedVariants.txt
* https://unicode.org/reports/tr37/
* https://unicode.org/ivd/
* https://www.freetype.org/freetype2/docs/reference/ft2-glyph_variants.html
*/
#define VAR_SEQ(x) GENERIC_VARIATION_SEQUENCES(x) | IDEOGRAPHICS_VARIATION_SEQUENCES(x) | MANGOLIAN_VARIATION_SEQUENCES(x)
#define GENERIC_VARIATION_SEQUENCES(x) (x>=0xFE00 && x<=0xFE0F) ? x : 0
#define IDEOGRAPHICS_VARIATION_SEQUENCES(x) (x>=0xE0100 && x<=0xE01EF) ? x : 0
#define MANGOLIAN_VARIATION_SEQUENCES(x) (x>=0x180B && x<=0x180D) ? x : 0
/**
* http://unicode.org/emoji/charts/emoji-variants.html
*/
#define VARIATION_EMOJI_PRESENTATION 0xFE0F
#define VARIATION_TEXT_PRESENTATION 0xFE0E
/**
* These Options (Flags) are used with evas_common_font_glyph_search function
*/
#define EVAS_FONT_SEARCH_OPTION_NONE 0x0000
#define EVAS_FONT_SEARCH_OPTION_SKIP_COLOR 0x0001
#define FASH_INT_MAGIC 0x01012345
#define FASH_GLYPH_MAGIC 0x02012345
enum _Evas_Font_Style
{
@ -153,10 +128,6 @@ typedef struct _RGBA_Font_Source RGBA_Font_Source;
typedef struct _RGBA_Font_Glyph RGBA_Font_Glyph;
typedef struct _RGBA_Font_Glyph_Out RGBA_Font_Glyph_Out;
typedef struct _Fash_Item_variation_Index_Item Fash_Item_variation_Index_Item;
typedef struct _Fash_Item_variation_List Fash_Item_variation_List;
typedef struct _Fash_Item_Index_Map_Variations Fash_Item_Index_Map_Variations;
typedef struct _Fash_Item_Index_Map Fash_Item_Index_Map;
typedef struct _Fash_Int_Map Fash_Int_Map;
typedef struct _Fash_Int_Map2 Fash_Int_Map2;
@ -168,25 +139,9 @@ struct _Fash_Item_Index_Map
RGBA_Font_Int *fint;
int index;
};
struct _Fash_Item_variation_Index_Item
{
Fash_Item_Index_Map item;
Eina_Unicode variation_sequence;
};
struct _Fash_Item_variation_List
{
Fash_Item_variation_Index_Item *list;
size_t length;
size_t capacity;
};
struct _Fash_Item_Index_Map_Variations
{
Fash_Item_Index_Map item;
Fash_Item_variation_List *variations;
};
struct _Fash_Int_Map
{
Fash_Item_Index_Map_Variations items[256];
Fash_Item_Index_Map item[256];
};
struct _Fash_Int_Map2
{
@ -194,7 +149,6 @@ struct _Fash_Int_Map2
};
struct _Fash_Int
{
unsigned int MAGIC;
Fash_Int_Map2 *bucket[256];
void (*freeme) (Fash_Int *fash);
};
@ -212,7 +166,6 @@ struct _Fash_Glyph_Map2
};
struct _Fash_Glyph
{
unsigned int MAGIC;
Fash_Glyph_Map2 *bucket[256];
void (*freeme) (Fash_Glyph *fash);
};
@ -394,7 +347,7 @@ void *evas_common_font_freetype_face_get(RGBA_Font *font); /* XXX: Not EAPI on p
EAPI RGBA_Font_Glyph *evas_common_font_int_cache_glyph_get (RGBA_Font_Int *fi, FT_UInt index);
EAPI Eina_Bool evas_common_font_int_cache_glyph_render(RGBA_Font_Glyph *fg);
EAPI FT_UInt evas_common_get_char_index (RGBA_Font_Int* fi, Eina_Unicode gl, Eina_Unicode variation_sequence);
EAPI FT_UInt evas_common_get_char_index (RGBA_Font_Int* fi, Eina_Unicode gl);
/* load */
EAPI 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
EAPI void *evas_common_font_glyph_compress(void *data, int num_grays, int pixel_mode, int pitch_data, int w, int h, int *size_ret);
EAPI DATA8 *evas_common_font_glyph_uncompress(RGBA_Font_Glyph *fg, int *wret, int *hret);
EAPI 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);
EAPI int evas_common_font_glyph_search (RGBA_Font *fn, RGBA_Font_Int **fi_ret, Eina_Unicode gl);
void evas_common_font_load_init(void);
void evas_common_font_load_shutdown(void);

View File

@ -687,11 +687,7 @@ evas_common_font_free(RGBA_Font *fn)
evas_common_font_int_unref(fi);
evas_common_font_flush();
eina_list_free(fn->fonts);
if (fn->fash)
{
fn->fash->freeme(fn->fash);
fn->fash = NULL;
}
if (fn->fash) fn->fash->freeme(fn->fash);
LKD(fn->lock);
free(fn);
}

View File

@ -354,183 +354,34 @@ end:
/* Set of common functions that are used in a couple of places. */
static void
_fash_int_map_and_variations_free(Fash_Int_Map *map)
{
if(!map)
return;
int i;
for (i = 0; i < 256; i++)
{
if (map->items[i].variations)
{
if (map->items[i].variations->list)
{
free(map->items[i].variations->list);
map->items[i].variations->list = NULL;
map->items[i].variations->capacity = 0;
map->items[i].variations->length = 0;
}
free(map->items[i].variations);
map->items[i].variations = NULL;
}
}
free(map);
}
static void
_fash_int2_free(Fash_Int_Map2 *fash)
{
{
int i;
if (fash)
{
for (i = 0; i < 256; i++)
if (fash->bucket[i])
{
_fash_int_map_and_variations_free(fash->bucket[i]);
fash->bucket[i] = NULL;
}
free(fash);
fash = NULL;
}
for (i = 0; i < 256; i++) if (fash->bucket[i]) free(fash->bucket[i]);
free(fash);
}
static void
_fash_int_free(Fash_Int *fash)
{
int i;
if (fash)
{
if (fash->MAGIC != FASH_INT_MAGIC)
{
return;
}
for (i = 0; i < 256; i++)
{
if (fash->bucket[i])
{
_fash_int2_free(fash->bucket[i]);
fash->bucket[i] = NULL;
}
}
free(fash);
}
for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_int2_free(fash->bucket[i]);
free(fash);
}
static Fash_Int *
_fash_int_new(void)
{
Fash_Int *fash = calloc(1, sizeof(Fash_Int));
EINA_SAFETY_ON_NULL_RETURN_VAL(fash, NULL);
fash->MAGIC = FASH_INT_MAGIC;
fash->freeme = _fash_int_free;
return fash;
}
static Fash_Item_variation_List *
_variations_list_new(void)
{
Fash_Item_variation_List *variations = calloc(1, sizeof(Fash_Item_variation_List));
EINA_SAFETY_ON_NULL_RETURN_VAL(variations, NULL);
variations->capacity = 0;
variations->length = 0;
variations->list = 0;
return variations;
}
static void
_variations_list_add(Fash_Item_variation_List *variations,RGBA_Font_Int *fint, int index, Eina_Unicode variation_sequence)
{
Fash_Item_variation_Index_Item *list = variations->list;
if (variations->capacity == variations->length)
{
list = (Fash_Item_variation_Index_Item *) realloc(list, (variations->capacity + 4) * sizeof(Fash_Item_variation_Index_Item));
if (list)
{
variations->list = list;
variations->capacity += 4;
}
}
EINA_SAFETY_ON_NULL_RETURN(list);
int start = 0;
int end = variations->length;
if (end == 0)
{
// if only on element just add it in 0 index
variations->list[0].item.fint = fint;
variations->list[0].item.index = index;
variations->list[0].variation_sequence = variation_sequence;
variations->length++;
}
else
{
// find lower bound
while (end > start)
{
int middle = start + (end - start) / 2;
if (variations->list[middle].variation_sequence >= variation_sequence)
end = middle;
else
start = middle + 1;
}
// if passed value founded in list, just replace it
if (start < (int)variations->length && variations->list[start].variation_sequence == variation_sequence)
{
variations->list[start].item.fint = fint;
variations->list[start].item.index = index;
variations->list[start].variation_sequence = variation_sequence;
return;
}
// shift array to insert item
for (int i = (variations->length - 1) ; i >= start; i--)
{
variations->list[i + 1] = variations->list[i];
}
// insert new item and keep array sorted
variations->list[start].item.fint = fint;
variations->list[start].item.index = index;
variations->list[start].variation_sequence = variation_sequence;
variations->length++;
}
}
static Fash_Item_Index_Map *
_variations_list_find(Fash_Item_variation_List * variations, Eina_Unicode variation_sequence)
{
if (!variations)
return NULL;
if (!variations->list)
return NULL;
int start = 0;
int end = variations->length;
while(end > start)
{
int middle = start + (end - start) / 2;
if (variations->list[middle].variation_sequence == variation_sequence)
return &(variations->list[middle].item);
else if (variations->list[middle].variation_sequence < variation_sequence)
start = middle + 1;
else
end = middle - 1;
}
return NULL;
}
static const Fash_Item_Index_Map *
_fash_int_find(Fash_Int *fash, int item, Eina_Unicode variation_sequence)
_fash_int_find(Fash_Int *fash, int item)
{
int grp, maj, min;
@ -540,22 +391,14 @@ _fash_int_find(Fash_Int *fash, int item, Eina_Unicode variation_sequence)
min = item & 0xff;
if (!fash->bucket[grp]) return NULL;
if (!fash->bucket[grp]->bucket[maj]) return NULL;
if (!variation_sequence)
return &(fash->bucket[grp]->bucket[maj]->items[min].item);
else
return _variations_list_find(fash->bucket[grp]->bucket[maj]->items[min].variations, variation_sequence);
return &(fash->bucket[grp]->bucket[maj]->item[min]);
}
static void
_fash_int_add(Fash_Int *fash, int item, RGBA_Font_Int *fint, int idx, Eina_Unicode variation_sequence)
_fash_int_add(Fash_Int *fash, int item, RGBA_Font_Int *fint, int idx)
{
int grp, maj, min;
// If we already have cached passed item, skip adding it again
const Fash_Item_Index_Map *fm = _fash_int_find(fash, item, variation_sequence);
if (fm && fm->fint)
return;
// 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
grp = (item >> 16) & 0xff;
maj = (item >> 8) & 0xff;
@ -566,20 +409,8 @@ _fash_int_add(Fash_Int *fash, int item, RGBA_Font_Int *fint, int idx, Eina_Unico
if (!fash->bucket[grp]->bucket[maj])
fash->bucket[grp]->bucket[maj] = calloc(1, sizeof(Fash_Int_Map));
EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]->bucket[maj]);
if (variation_sequence)
{
if (!fash->bucket[grp]->bucket[maj]->items[min].variations)
{
fash->bucket[grp]->bucket[maj]->items[min].variations =_variations_list_new();
EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]->bucket[maj]->items[min].variations);
}
_variations_list_add(fash->bucket[grp]->bucket[maj]->items[min].variations, fint, idx, variation_sequence);
}
else
{
fash->bucket[grp]->bucket[maj]->items[min].item.fint = fint;
fash->bucket[grp]->bucket[maj]->items[min].item.index = idx;
}
fash->bucket[grp]->bucket[maj]->item[min].fint = fint;
fash->bucket[grp]->bucket[maj]->item[min].index = idx;
}
static void
@ -631,45 +462,24 @@ _fash_gl2_free(Fash_Glyph_Map2 *fash)
int i;
// 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
for (i = 0; i < 256; i++)
{
if (fash->bucket[i])
{
_fash_glyph_free(fash->bucket[i]);
fash->bucket[i] = NULL;
}
}
for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_glyph_free(fash->bucket[i]);
free(fash);
}
static void
_fash_gl_free(Fash_Glyph *fash)
{
if (fash)
{
if (fash->MAGIC != FASH_GLYPH_MAGIC)
return;
int i;
int i;
// 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
for (i = 0; i < 256; i++)
{
if (fash->bucket[i])
{
_fash_gl2_free(fash->bucket[i]);
fash->bucket[i] = NULL;
}
}
free(fash);
}
// 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_gl2_free(fash->bucket[i]);
free(fash);
}
static Fash_Glyph *
_fash_gl_new(void)
{
Fash_Glyph *fash = calloc(1, sizeof(Fash_Glyph));
EINA_SAFETY_ON_NULL_RETURN_VAL(fash, NULL);
fash->MAGIC = FASH_GLYPH_MAGIC;
fash->freeme = _fash_gl_free;
return fash;
}
@ -870,7 +680,7 @@ struct _Font_Char_Index
};
EAPI FT_UInt
evas_common_get_char_index(RGBA_Font_Int* fi, Eina_Unicode gl, Eina_Unicode variation_sequence)
evas_common_get_char_index(RGBA_Font_Int* fi, Eina_Unicode gl)
{
static const unsigned short mapfix[] =
{
@ -932,10 +742,7 @@ evas_common_get_char_index(RGBA_Font_Int* fi, Eina_Unicode gl, Eina_Unicode vari
* that something else try to use it.
*/
/* FTLOCK(); */
if (variation_sequence)
result.index = FT_Face_GetCharVariantIndex(fi->src->ft.face, gl, variation_sequence);
else
result.index = FT_Get_Char_Index(fi->src->ft.face, gl);
result.index = FT_Get_Char_Index(fi->src->ft.face, gl);
/* FTUNLOCK(); */
result.gl = gl;
@ -967,10 +774,7 @@ evas_common_get_char_index(RGBA_Font_Int* fi, Eina_Unicode gl, Eina_Unicode vari
{
gl = mapfix[(i << 1) + 1];
FTLOCK();
if (variation_sequence)
result.index = FT_Face_GetCharVariantIndex(fi->src->ft.face, gl, variation_sequence);
else
result.index = FT_Get_Char_Index(fi->src->ft.face, gl);
result.index = FT_Get_Char_Index(fi->src->ft.face, gl);
FTUNLOCK();
break;
}
@ -995,49 +799,20 @@ evas_common_get_char_index(RGBA_Font_Int* fi, Eina_Unicode gl, Eina_Unicode vari
return result.index;
}
/*
* @internal
* Search for unicode glyph inside all font files, and return font and glyph index
*
* @param[in] fn the font to use.
* @param[out] fi_ret founded font.
* @param[in] gl unicode glyph to search for
* @param[in] variation_sequence for the gl glyph
* @param[in] evas_font_search_options search options when searching font files
*
*/
EAPI 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)
evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, Eina_Unicode gl)
{
Eina_List *l;
if (fn->fash)
{
const Fash_Item_Index_Map *fm = _fash_int_find(fn->fash, gl, variation_sequence);
Fash_Item_Index_Map *fm = _fash_int_find(fn->fash, gl);
if (fm)
{
if (fm->fint)
{
if (evas_font_search_options == EVAS_FONT_SEARCH_OPTION_NONE)
{
*fi_ret = fm->fint;
return fm->index;
}
else if( (evas_font_search_options & EVAS_FONT_SEARCH_OPTION_SKIP_COLOR) == EVAS_FONT_SEARCH_OPTION_SKIP_COLOR)
{
if (!fm->fint->src->ft.face)
{
evas_common_font_int_reload(fm->fint);
}
if (fm->fint->src->ft.face && !FT_HAS_COLOR(fm->fint->src->ft.face))
{
*fi_ret = fm->fint;
return fm->index;
}
}
*fi_ret = fm->fint;
return fm->index;
}
else if (fm->index == -1) return 0;
}
@ -1076,35 +851,20 @@ evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, Eina_Unicod
}
if (fi->src->ft.face)
{
Eina_Bool is_color_only = (evas_font_search_options & EVAS_FONT_SEARCH_OPTION_SKIP_COLOR) == EVAS_FONT_SEARCH_OPTION_SKIP_COLOR &&
FT_HAS_COLOR(fi->src->ft.face);
if (is_color_only)
{
/* This is color font ignore it */
continue;
}
idx = (int) evas_common_get_char_index(fi, gl, variation_sequence);
idx = evas_common_get_char_index(fi, gl);
if (idx != 0)
{
if (!fi->ft.size)
evas_common_font_int_load_complete(fi);
if (!is_color_only)
{
if (!fn->fash) fn->fash = _fash_int_new();
if (fn->fash) _fash_int_add(fn->fash, gl, fi, idx, variation_sequence);
}
if (!fn->fash) fn->fash = _fash_int_new();
if (fn->fash) _fash_int_add(fn->fash, gl, fi, idx);
*fi_ret = fi;
return idx;
}
else
{
if (!is_color_only)
{
if (!fn->fash) fn->fash = _fash_int_new();
if (fn->fash) _fash_int_add(fn->fash, gl, NULL, -1, variation_sequence);
}
if (!fn->fash) fn->fash = _fash_int_new();
if (fn->fash) _fash_int_add(fn->fash, gl, NULL, -1);
}
}
}

View File

@ -32,9 +32,6 @@ evas_common_font_query_run_font_end_get(RGBA_Font *fn, RGBA_Font_Int **script_fi
(evas_common_language_char_script_get(*base_char) != script) ;
base_char++)
;
/* If counter reach variation sequence it is safe to pick default font */
if(VAR_SEQ(*base_char) || (base_char != run_end && VAR_SEQ(*(base_char+1)))) goto get_top_font;
if (base_char == run_end) base_char = text;
/* 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
/* 0x1F is the last ASCII contral char, just a hack in
* the meanwhile. */
if ((*base_char > 0x1F) &&
evas_common_font_glyph_search(fn, &fi, *base_char, 0, EVAS_FONT_SEARCH_OPTION_NONE))
evas_common_font_glyph_search(fn, &fi, *base_char))
break;
base_char++;
}
@ -52,8 +49,7 @@ evas_common_font_query_run_font_end_get(RGBA_Font *fn, RGBA_Font_Int **script_fi
/* If everything else fails, at least try to find a font for the
* replacement char */
if (base_char == run_end)
evas_common_font_glyph_search(fn, &fi, REPLACEMENT_CHAR, 0, EVAS_FONT_SEARCH_OPTION_NONE);
get_top_font:
evas_common_font_glyph_search(fn, &fi, REPLACEMENT_CHAR);
if (!fi)
fi = fn->fonts->data;
@ -84,17 +80,15 @@ get_top_font:
if (evas_common_language_char_script_get(*itr) == EVAS_SCRIPT_INHERITED)
continue;
Eina_Unicode variation_sequence = VAR_SEQ(*(itr+1));
/* Break if either it's not in the font, or if it is in the
* script's font. */
if (!evas_common_get_char_index(fi, *itr, variation_sequence))
break;
if (!evas_common_get_char_index(fi, *itr))
break;
if (fi != *script_fi)
{
if (evas_common_get_char_index(*script_fi, *itr, variation_sequence))
break;
if (evas_common_get_char_index(*script_fi, *itr))
break;
}
}
@ -108,25 +102,10 @@ get_top_font:
/* If we can find a font, use it. Otherwise, find the first
* char the run of chars that can't be rendered until the first
* one that can. */
Eina_Unicode variation_sequence = VAR_SEQ(*(itr+1));
if (evas_common_font_glyph_search(fn, &tmp_fi, *itr, variation_sequence, EVAS_FONT_SEARCH_OPTION_NONE))
if (evas_common_font_glyph_search(fn, &tmp_fi, *itr))
{
fi = tmp_fi;
}
else if ( (variation_sequence == VARIATION_TEXT_PRESENTATION) && evas_common_font_glyph_search(fn, &tmp_fi, *itr, 0, EVAS_FONT_SEARCH_OPTION_SKIP_COLOR))
{
/* If we can not find unicode with variation sequence, then we will
Search and find for non color glyph because variation sequence is Text
*/
fi = tmp_fi;
}
else if ( variation_sequence && evas_common_font_glyph_search(fn, &tmp_fi, *itr, 0, EVAS_FONT_SEARCH_OPTION_NONE))
{
/* If we can not find unicode with variation sequence, then we will
Search and find glyph without the variation sequence
*/
fi = tmp_fi;
}
else
{
itr++;
@ -134,13 +113,9 @@ get_top_font:
* font */
for ( ; itr < run_end ; itr++)
{
if(VAR_SEQ(*itr))
continue;
Eina_Unicode variation_sequence = VAR_SEQ(*(itr+1));
tmp_fi = fi;
if (evas_common_get_char_index(fi, *itr, variation_sequence) ||
evas_common_font_glyph_search(fn, &tmp_fi, *itr, variation_sequence, EVAS_FONT_SEARCH_OPTION_NONE))
if (evas_common_get_char_index(fi, *itr) ||
evas_common_font_glyph_search(fn, &tmp_fi, *itr))
{
fi = tmp_fi;
break;
@ -152,9 +127,9 @@ get_top_font:
* find a font most suitable for the replacement char and
* break */
if ((itr == run_end) ||
!evas_common_get_char_index(fi, REPLACEMENT_CHAR, 0))
!evas_common_get_char_index(fi, REPLACEMENT_CHAR))
{
evas_common_font_glyph_search(fn, &fi, REPLACEMENT_CHAR, 0, EVAS_FONT_SEARCH_OPTION_NONE);
evas_common_font_glyph_search(fn, &fi, REPLACEMENT_CHAR);
break;
}
}
@ -165,11 +140,8 @@ get_top_font:
/* If this char is not renderable by any font, but the replacement
* char can be rendered using the currentfont, continue this
* run. */
Eina_Unicode variation_sequence = VAR_SEQ(*(itr+1));
if (!evas_common_font_glyph_search(fn, &tmp_fi, *itr, variation_sequence, EVAS_FONT_SEARCH_OPTION_NONE) &&
(variation_sequence ? !evas_common_font_glyph_search(fn, &tmp_fi, *itr, 0, EVAS_FONT_SEARCH_OPTION_NONE) : 1) &&
evas_common_get_char_index(fi, REPLACEMENT_CHAR, 0))
if (!evas_common_font_glyph_search(fn, &tmp_fi, *itr) &&
evas_common_get_char_index(fi, REPLACEMENT_CHAR))
{
itr++;
}

View File

@ -1066,7 +1066,7 @@ _content_create_ot(RGBA_Font_Int *fi, const Eina_Unicode *text,
/* If we got a malformed index, show the replacement char instead */
if (gl_itr->index == 0)
{
gl_itr->index = evas_common_get_char_index(fi, REPLACEMENT_CHAR, 0);
gl_itr->index = evas_common_get_char_index(fi, REPLACEMENT_CHAR);
is_replacement = EINA_TRUE;
}
idx = gl_itr->index;
@ -1172,10 +1172,10 @@ _content_create_regular(RGBA_Font_Int *fi, const Eina_Unicode *text,
_gl = *text;
if (_gl == 0) break;
idx = evas_common_get_char_index(fi, _gl, 0);
idx = evas_common_get_char_index(fi, _gl);
if (idx == 0)
{
idx = evas_common_get_char_index(fi, REPLACEMENT_CHAR, 0);
idx = evas_common_get_char_index(fi, REPLACEMENT_CHAR);
}
fg = evas_common_font_int_cache_glyph_get(fi, idx);

View File

@ -1,6 +1,6 @@
/*
* TODO:
* * Test different font loading mechanisms.
* * Test different font lodaing mechanisms.
*/
#ifdef HAVE_CONFIG_H
@ -4129,23 +4129,6 @@ EFL_START_TEST(evas_textblock_obstacle)
}
EFL_END_TEST;
EFL_START_TEST(evas_textblock_variation_sequence)
{
START_TB_TEST();
evas_font_path_global_prepend("..");
const char *str1 = "8&#xfe0f;&#x262a;&#xfe0f;";
const char *str2 = "8&#xfe0e;&#x262a;&#xfe0e;";
Evas_Coord fw, fh,fw_new, fh_new;
evas_object_textblock_text_markup_set(tb, str1);
evas_object_textblock_size_formatted_get(tb, &fw, &fh);
evas_object_textblock_text_markup_set(tb, str2);
evas_object_textblock_size_formatted_get(tb, &fw_new, &fh_new);
fail_if(fw_new == fw && fh_new == fh);
END_TB_TEST();
}
EFL_END_TEST;
#ifdef HAVE_HYPHEN
static void
_hyphenation_width_stress(Evas_Object *tb, Evas_Textblock_Cursor *cur)
@ -4746,7 +4729,6 @@ void evas_test_textblock(TCase *tc)
tcase_add_test(tc, evas_textblock_items);
tcase_add_test(tc, evas_textblock_delete);
tcase_add_test(tc, evas_textblock_obstacle);
tcase_add_test(tc, evas_textblock_variation_sequence);
#ifdef HAVE_HYPHEN
tcase_add_test(tc, evas_textblock_hyphenation);
#endif