forked from enlightenment/efl
Evas font-engine: Fixed font fallback in the same script run.
SVN revision: 59777
This commit is contained in:
parent
ca1fc26a0e
commit
81b217f8c4
|
@ -459,23 +459,24 @@ evas_object_text_font_get(const Evas_Object *obj, const char **font, Evas_Font_S
|
|||
*/
|
||||
static Evas_Object_Text_Item *
|
||||
_evas_object_text_item_new(Evas_Object *obj, Evas_Object_Text *o,
|
||||
const Eina_Unicode *str,
|
||||
void *fi, const Eina_Unicode *str, Evas_Script_Type script,
|
||||
size_t pos, size_t visual_pos, size_t len)
|
||||
{
|
||||
Evas_Object_Text_Item *it;
|
||||
const Eina_Unicode *text = str + pos;
|
||||
|
||||
it = calloc(1, sizeof(Evas_Object_Text_Item));
|
||||
it->text_pos = pos;
|
||||
it->visual_pos = visual_pos;
|
||||
evas_common_text_props_bidi_set(&it->text_props, o->bidi_par_props,
|
||||
it->text_pos);
|
||||
evas_common_text_props_script_set(&it->text_props, text, len);
|
||||
evas_common_text_props_script_set(&it->text_props, script);
|
||||
|
||||
if (o->engine_data)
|
||||
{
|
||||
ENFN->font_text_props_info_create(ENDT,
|
||||
o->engine_data, text, &it->text_props,
|
||||
fi, str + pos, &it->text_props,
|
||||
o->bidi_par_props, it->text_pos, len);
|
||||
|
||||
ENFN->font_string_size_get(ENDT,
|
||||
o->engine_data,
|
||||
&it->text_props,
|
||||
|
@ -554,7 +555,6 @@ _evas_object_text_layout(Evas_Object *obj, Evas_Object_Text *o, const Eina_Unico
|
|||
{
|
||||
EvasBiDiStrIndex *v_to_l = NULL;
|
||||
size_t pos, visual_pos;
|
||||
int cutoff;
|
||||
int len = eina_unicode_strlen(text);
|
||||
#ifdef BIDI_SUPPORT
|
||||
int *segment_idxs = NULL;
|
||||
|
@ -567,32 +567,44 @@ _evas_object_text_layout(Evas_Object *obj, Evas_Object_Text *o, const Eina_Unico
|
|||
#endif
|
||||
visual_pos = pos = 0;
|
||||
|
||||
do
|
||||
while (len > 0)
|
||||
{
|
||||
cutoff = evas_common_language_script_end_of_run_get(
|
||||
void *script_fi = NULL;
|
||||
int script_len = len, tmp_cut;
|
||||
Evas_Script_Type script;
|
||||
tmp_cut = evas_common_language_script_end_of_run_get(
|
||||
text + pos,
|
||||
o->bidi_par_props,
|
||||
pos, len - pos);
|
||||
if (cutoff > 0)
|
||||
pos, len);
|
||||
if (tmp_cut > 0)
|
||||
script_len = tmp_cut;
|
||||
|
||||
script = evas_common_language_script_type_get(text, script_len);
|
||||
|
||||
while (script_len > 0)
|
||||
{
|
||||
void *cur_fi;
|
||||
int run_len = script_len;
|
||||
if (o->engine_data)
|
||||
{
|
||||
run_len = ENFN->font_run_end_get(ENDT,
|
||||
o->engine_data, &script_fi, &cur_fi,
|
||||
script, text + pos, script_len);
|
||||
}
|
||||
#ifdef BIDI_SUPPORT
|
||||
visual_pos = evas_bidi_position_logical_to_visual(
|
||||
v_to_l, len, pos);
|
||||
v_to_l, run_len, pos);
|
||||
#else
|
||||
visual_pos = pos;
|
||||
#endif
|
||||
_evas_object_text_item_new(obj, o, text, pos, visual_pos, cutoff);
|
||||
pos += cutoff;
|
||||
_evas_object_text_item_new(obj, o, cur_fi, text, script,
|
||||
pos, visual_pos, run_len);
|
||||
|
||||
pos += run_len;
|
||||
script_len -= run_len;
|
||||
len -= run_len;
|
||||
}
|
||||
}
|
||||
while (cutoff > 0);
|
||||
#ifdef BIDI_SUPPORT
|
||||
visual_pos = evas_bidi_position_logical_to_visual(
|
||||
v_to_l, len, pos);
|
||||
#else
|
||||
visual_pos = pos;
|
||||
#endif
|
||||
_evas_object_text_item_new(obj, o, text, pos, visual_pos, len - pos);
|
||||
|
||||
_evas_object_text_item_order(obj, o);
|
||||
|
||||
|
|
|
@ -2816,43 +2816,75 @@ skip:
|
|||
empty_item = 0;
|
||||
|
||||
|
||||
/* If there's no parent text node, only create an empty item */
|
||||
if (!n)
|
||||
{
|
||||
ti = _layout_text_item_new(c, fmt);
|
||||
ti->parent.text_node = NULL;
|
||||
ti->parent.text_pos = 0;
|
||||
_layout_text_add_logical_item(c, ti, NULL);
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
while (str)
|
||||
{
|
||||
int tmp_len;
|
||||
void *script_fi = NULL;
|
||||
int script_len, tmp_cut;
|
||||
Evas_Script_Type script;
|
||||
|
||||
ti = _layout_text_item_new(c, fmt);
|
||||
ti->parent.text_node = n;
|
||||
ti->parent.text_pos = start + str - tbase;
|
||||
tmp_len = off - (str - tbase);
|
||||
if (ti->parent.text_node)
|
||||
script_len = off - (str - tbase);
|
||||
|
||||
tmp_cut = evas_common_language_script_end_of_run_get(str,
|
||||
c->par->bidi_props, start + str - tbase, script_len);
|
||||
if (tmp_cut > 0)
|
||||
{
|
||||
int tmp_cut;
|
||||
tmp_cut = evas_common_language_script_end_of_run_get(str,
|
||||
c->par->bidi_props, ti->parent.text_pos, tmp_len);
|
||||
if (tmp_cut > 0)
|
||||
script_len = tmp_cut;
|
||||
}
|
||||
|
||||
script = evas_common_language_script_type_get(str, script_len);
|
||||
|
||||
|
||||
while (script_len > 0)
|
||||
{
|
||||
void *cur_fi;
|
||||
int run_len = script_len;
|
||||
ti = _layout_text_item_new(c, fmt);
|
||||
ti->parent.text_node = n;
|
||||
ti->parent.text_pos = start + str - tbase;
|
||||
|
||||
if (ti->parent.format->font.font)
|
||||
{
|
||||
tmp_len = tmp_cut;
|
||||
run_len = c->ENFN->font_run_end_get(c->ENDT,
|
||||
ti->parent.format->font.font, &script_fi, &cur_fi,
|
||||
script, str, script_len);
|
||||
}
|
||||
|
||||
evas_common_text_props_bidi_set(&ti->text_props,
|
||||
c->par->bidi_props, ti->parent.text_pos);
|
||||
evas_common_text_props_script_set(&ti->text_props, str, tmp_len);
|
||||
evas_common_text_props_script_set(&ti->text_props, script);
|
||||
|
||||
if (ti->parent.format->font.font)
|
||||
{
|
||||
c->ENFN->font_text_props_info_create(c->ENDT,
|
||||
ti->parent.format->font.font, str, &ti->text_props,
|
||||
c->par->bidi_props, ti->parent.text_pos, tmp_len);
|
||||
cur_fi, str, &ti->text_props, c->par->bidi_props,
|
||||
ti->parent.text_pos, run_len);
|
||||
}
|
||||
str += run_len;
|
||||
cur_len -= run_len;
|
||||
script_len -= run_len;
|
||||
|
||||
_layout_text_add_logical_item(c, ti, NULL);
|
||||
}
|
||||
str += tmp_len;
|
||||
cur_len -= tmp_len;
|
||||
|
||||
_layout_text_add_logical_item(c, ti, NULL);
|
||||
|
||||
/* Break if we reached the end. */
|
||||
/* Break if we reached the end. We do it here
|
||||
* because we want at least one run if it's an empty string. */
|
||||
if (!*str)
|
||||
break;
|
||||
}
|
||||
|
||||
end:
|
||||
if (alloc_str) free(alloc_str);
|
||||
}
|
||||
|
||||
|
@ -3283,21 +3315,33 @@ static Evas_Object_Textblock_Text_Item *
|
|||
_layout_ellipsis_item_new(Ctxt *c, const Evas_Object_Textblock_Item *cur_it)
|
||||
{
|
||||
Evas_Object_Textblock_Text_Item *ellip_ti;
|
||||
Evas_Script_Type script;
|
||||
void *script_fi = NULL, *cur_fi;
|
||||
size_t len = 1; /* The length of _ellip_str */
|
||||
ellip_ti = _layout_text_item_new(c,
|
||||
eina_list_data_get(eina_list_last(c->format_stack)));
|
||||
ellip_ti->parent.text_node = cur_it->text_node;
|
||||
ellip_ti->parent.text_pos = cur_it->text_pos;
|
||||
script = evas_common_language_script_type_get(_ellip_str, len);
|
||||
|
||||
evas_common_text_props_bidi_set(&ellip_ti->text_props,
|
||||
c->par->bidi_props, ellip_ti->parent.text_pos);
|
||||
evas_common_text_props_script_set (&ellip_ti->text_props,
|
||||
_ellip_str, len);
|
||||
c->ENFN->font_text_props_info_create(c->ENDT,
|
||||
ellip_ti->parent.format->font.font,
|
||||
_ellip_str, &ellip_ti->text_props,
|
||||
c->par->bidi_props,
|
||||
ellip_ti->parent.text_pos, len);
|
||||
evas_common_text_props_script_set (&ellip_ti->text_props, script);
|
||||
|
||||
if (ellip_ti->parent.format->font.font)
|
||||
{
|
||||
/* It's only 1 char anyway, we don't need the run end. */
|
||||
(void) c->ENFN->font_run_end_get(c->ENDT,
|
||||
ellip_ti->parent.format->font.font, &script_fi, &cur_fi,
|
||||
script, _ellip_str, len);
|
||||
|
||||
c->ENFN->font_text_props_info_create(c->ENDT,
|
||||
ellip_ti->parent.format->font.font,
|
||||
_ellip_str, &ellip_ti->text_props,
|
||||
c->par->bidi_props,
|
||||
ellip_ti->parent.text_pos, len);
|
||||
}
|
||||
|
||||
_text_item_update_sizes(c, ellip_ti);
|
||||
|
||||
if (cur_it->type == EVAS_TEXTBLOCK_ITEM_TEXT)
|
||||
|
|
|
@ -64,6 +64,7 @@ EAPI int evas_common_font_query_char_coords (RGBA_Font *fn, con
|
|||
EAPI int evas_common_font_query_pen_coords (RGBA_Font *fn, const Evas_Text_Props *intl_props, int pos, int *cpen_x, int *cy, int *cadv, int *ch);
|
||||
EAPI int evas_common_font_query_char_at_coords (RGBA_Font *fn, const Evas_Text_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch);
|
||||
EAPI int evas_common_font_query_last_up_to_pos (RGBA_Font *fn, const Evas_Text_Props *intl_props, int x, int y);
|
||||
EAPI int evas_common_font_query_run_font_end_get(RGBA_Font *fn, RGBA_Font_Int **script_fi, RGBA_Font_Int **cur_fi, Evas_Script_Type script, const Eina_Unicode *text, int run_len);
|
||||
|
||||
#ifdef EVAS_FRAME_QUEUING
|
||||
EAPI void evas_common_font_draw_finish(void);
|
||||
|
|
|
@ -262,8 +262,8 @@ _evas_common_font_ot_shape(hb_buffer_t *buffer, RGBA_Font_Int *fi)
|
|||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
evas_common_font_ot_populate_text_props(void *_fn __UNUSED__,
|
||||
const Eina_Unicode *text, Evas_Text_Props *props, int len)
|
||||
evas_common_font_ot_populate_text_props(const Eina_Unicode *text,
|
||||
Evas_Text_Props *props, int len)
|
||||
{
|
||||
RGBA_Font_Int *fi;
|
||||
hb_buffer_t *buffer;
|
||||
|
|
|
@ -39,7 +39,7 @@ EAPI int
|
|||
evas_common_font_ot_cluster_size_get(const Evas_Text_Props *props, size_t char_index);
|
||||
|
||||
EAPI Eina_Bool
|
||||
evas_common_font_ot_populate_text_props(void *fn, const Eina_Unicode *text,
|
||||
evas_common_font_ot_populate_text_props(const Eina_Unicode *text,
|
||||
Evas_Text_Props *props, int len);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -3,6 +3,145 @@
|
|||
#include "evas_font_private.h" /* for Frame-Queuing support */
|
||||
#include "evas_font_ot.h"
|
||||
|
||||
|
||||
/* FIXME: Check coverage according to the font and not by actually loading */
|
||||
/**
|
||||
* @internal
|
||||
* Find the end of a run according to font coverage, and return the base script
|
||||
* font and the current wanted font.
|
||||
*
|
||||
* @param[in] fn the font to use.
|
||||
* @param script_fi The base font instance to be used with the script. If NULL, then it's calculated and returned in this variable, if not NULL, it's used and not modified.
|
||||
* @param[out] cur_fi The font instance found for the current run.
|
||||
* @param[in] script the base script
|
||||
* @param[in] text the text to work on.
|
||||
* @param[in] run_let the current run len, i.e "search limit".
|
||||
* @return length of the run found.
|
||||
*/
|
||||
EAPI int
|
||||
evas_common_font_query_run_font_end_get(RGBA_Font *fn, RGBA_Font_Int **script_fi, RGBA_Font_Int **cur_fi, Evas_Script_Type script, const Eina_Unicode *text, int run_len)
|
||||
{
|
||||
RGBA_Font_Int *fi;
|
||||
const Eina_Unicode *run_end = text + run_len;
|
||||
const Eina_Unicode *itr;
|
||||
|
||||
/* If there's no current script_fi, find it first */
|
||||
if (!*script_fi)
|
||||
{
|
||||
const Eina_Unicode *base_char = NULL;
|
||||
/* Skip common chars */
|
||||
for (base_char = text ;
|
||||
(base_char < run_end) &&
|
||||
(evas_common_language_char_script_get(*base_char) != script) ;
|
||||
base_char++)
|
||||
;
|
||||
if (base_char == run_end) base_char = text;
|
||||
|
||||
/* Find the first renderable char */
|
||||
while (base_char < run_end)
|
||||
{
|
||||
/* 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))
|
||||
break;
|
||||
base_char++;
|
||||
}
|
||||
|
||||
|
||||
/* 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);
|
||||
|
||||
*script_fi = fi;
|
||||
}
|
||||
else
|
||||
{
|
||||
fi = *script_fi;
|
||||
}
|
||||
|
||||
/* Find the longest run of the same font starting from the start position
|
||||
* and update cur_fi accordingly. */
|
||||
itr = text;
|
||||
while (itr < run_end)
|
||||
{
|
||||
RGBA_Font_Int *tmp_fi;
|
||||
/* Itr will end up being the first of the next run */
|
||||
for ( ; itr < run_end ; itr++)
|
||||
{
|
||||
/* Break if either it's not in the font, or if it is in the
|
||||
* script's font. */
|
||||
if (fi == *script_fi)
|
||||
{
|
||||
if (!evas_common_get_char_index(fi, *itr))
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (evas_common_get_char_index(*script_fi, *itr))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the script font doesn't fit even one char, find a new font. */
|
||||
if (itr == text)
|
||||
{
|
||||
/* 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. */
|
||||
if (evas_common_font_glyph_search(fn, &tmp_fi, *itr))
|
||||
{
|
||||
fi = tmp_fi;
|
||||
}
|
||||
else
|
||||
{
|
||||
itr++;
|
||||
/* Go through all the chars that can't be rendered with any
|
||||
* font */
|
||||
for ( ; itr < run_end ; itr++)
|
||||
{
|
||||
if (evas_common_get_char_index(fi, *itr) ||
|
||||
evas_common_font_glyph_search(fn, &fi, *itr))
|
||||
break;
|
||||
}
|
||||
|
||||
/* If we found a renderable character and the found font
|
||||
* can render the replacement char, continue, otherwise
|
||||
* find a font most suitable for the replacement char and
|
||||
* break */
|
||||
if ((itr == run_end) ||
|
||||
!evas_common_get_char_index(fi, REPLACEMENT_CHAR))
|
||||
{
|
||||
evas_common_font_glyph_search(fn, &fi, REPLACEMENT_CHAR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
itr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If this char is not renderable by any font, but the replacement
|
||||
* char can be rendered using the currentfont, continue this
|
||||
* run. */
|
||||
if (!evas_common_font_glyph_search(fn, &tmp_fi, *itr) &&
|
||||
evas_common_get_char_index(fi, REPLACEMENT_CHAR))
|
||||
{
|
||||
itr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Done, we did as much as possible */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*cur_fi = fi;
|
||||
|
||||
return itr - text;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Calculate the kerning between "left" and "right.
|
||||
|
|
|
@ -22,10 +22,9 @@ evas_common_text_props_bidi_set(Evas_Text_Props *props,
|
|||
}
|
||||
|
||||
void
|
||||
evas_common_text_props_script_set(Evas_Text_Props *props,
|
||||
const Eina_Unicode *str, size_t len)
|
||||
evas_common_text_props_script_set(Evas_Text_Props *props, Evas_Script_Type scr)
|
||||
{
|
||||
props->script = evas_common_language_script_type_get(str, len);
|
||||
props->script = scr;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -195,12 +194,11 @@ evas_common_text_props_merge(Evas_Text_Props *item1,
|
|||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
evas_common_text_props_content_create(void *_fn, const Eina_Unicode *text,
|
||||
evas_common_text_props_content_create(void *_fi, const Eina_Unicode *text,
|
||||
Evas_Text_Props *text_props, const Evas_BiDi_Paragraph_Props *par_props,
|
||||
size_t par_pos, int len)
|
||||
{
|
||||
RGBA_Font *fn = (RGBA_Font *) _fn;
|
||||
RGBA_Font_Int *fi;
|
||||
RGBA_Font_Int *fi = (RGBA_Font_Int *) _fi;
|
||||
|
||||
if (text_props->info)
|
||||
{
|
||||
|
@ -213,35 +211,6 @@ evas_common_text_props_content_create(void *_fn, const Eina_Unicode *text,
|
|||
}
|
||||
text_props->info = calloc(1, sizeof(Evas_Text_Props_Info));
|
||||
|
||||
fi = fn->fonts->data;
|
||||
/* Load the glyph according to the first letter of the script, pretty
|
||||
* bad, but will have to do */
|
||||
{
|
||||
const Eina_Unicode *base_char;
|
||||
/* Skip common chars */
|
||||
for (base_char = text ;
|
||||
*base_char &&
|
||||
(evas_common_language_char_script_get(*base_char) !=
|
||||
text_props->script) ;
|
||||
base_char++)
|
||||
;
|
||||
if (!*base_char) base_char = text;
|
||||
|
||||
/* Find the first renderable char, and if there is none, find
|
||||
* one that can show the replacement char. */
|
||||
while (*base_char)
|
||||
{
|
||||
/* 0x1F is the last ASCII contral char. */
|
||||
if ((*base_char > 0x1F) &&
|
||||
evas_common_font_glyph_search(fn, &fi, *base_char))
|
||||
break;
|
||||
base_char++;
|
||||
}
|
||||
|
||||
if (!*base_char)
|
||||
evas_common_font_glyph_search(fn, &fi, REPLACEMENT_CHAR);
|
||||
}
|
||||
|
||||
text_props->font_instance = fi;
|
||||
|
||||
evas_common_font_int_reload(fi);
|
||||
|
@ -260,7 +229,7 @@ evas_common_text_props_content_create(void *_fn, const Eina_Unicode *text,
|
|||
(void) par_props;
|
||||
(void) par_pos;
|
||||
|
||||
evas_common_font_ot_populate_text_props(fn, text, text_props, len);
|
||||
evas_common_font_ot_populate_text_props(text, text_props, len);
|
||||
|
||||
gl_itr = text_props->info->glyph;
|
||||
for (char_index = 0 ; char_index < text_props->len ; char_index++)
|
||||
|
|
|
@ -54,11 +54,10 @@ evas_common_text_props_bidi_set(Evas_Text_Props *props,
|
|||
Evas_BiDi_Paragraph_Props *bidi_par_props, size_t start);
|
||||
|
||||
void
|
||||
evas_common_text_props_script_set(Evas_Text_Props *props,
|
||||
const Eina_Unicode *str, size_t len);
|
||||
evas_common_text_props_script_set(Evas_Text_Props *props, Evas_Script_Type scr);
|
||||
|
||||
EAPI Eina_Bool
|
||||
evas_common_text_props_content_create(void *_fn, const Eina_Unicode *text,
|
||||
evas_common_text_props_content_create(void *_fi, const Eina_Unicode *text,
|
||||
Evas_Text_Props *text_props, const Evas_BiDi_Paragraph_Props *par_props,
|
||||
size_t par_pos, int len);
|
||||
|
||||
|
|
|
@ -733,6 +733,7 @@ struct _Evas_Func
|
|||
int (*gl_native_surface_get) (void *data, void *surface, void *native_surface);
|
||||
void *(*gl_api_get) (void *data);
|
||||
int (*image_load_error_get) (void *data, void *image);
|
||||
int (*font_run_end_get) (void *data __UNUSED__, void *fn, void **script_fi, void **cur_fi, Evas_Script_Type script, const Eina_Unicode *text, int run_len);
|
||||
};
|
||||
|
||||
struct _Evas_Image_Load_Func
|
||||
|
|
|
@ -799,6 +799,14 @@ eng_font_last_up_to_pos(void *data __UNUSED__, void *font, const Evas_Text_Props
|
|||
return evas_common_font_query_last_up_to_pos(font, text_props, x, y);
|
||||
}
|
||||
|
||||
static int
|
||||
eng_font_run_font_end_get(void *data __UNUSED__, void *fn, void **script_fi, void **cur_fi, Evas_Script_Type script, const Eina_Unicode *text, int run_len)
|
||||
{
|
||||
return evas_common_font_query_run_font_end_get(fn,
|
||||
(RGBA_Font_Int **) script_fi, (RGBA_Font_Int **) cur_fi,
|
||||
script, text, run_len);
|
||||
}
|
||||
|
||||
static void
|
||||
eng_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Evas_Text_Props *text_props)
|
||||
{
|
||||
|
@ -1081,7 +1089,8 @@ static Evas_Func func =
|
|||
NULL, // FIXME: need software mesa for gl rendering <- gl_proc_address_get
|
||||
NULL, // FIXME: need software mesa for gl rendering <- gl_native_surface_get
|
||||
NULL, // FIXME: need software mesa for gl rendering <- gl_api_get
|
||||
eng_image_load_error_get
|
||||
eng_image_load_error_get,
|
||||
eng_font_run_font_end_get
|
||||
/* FUTURE software generic calls go here */
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue