Snapshot.

SVN revision: 56552
This commit is contained in:
Tom Hacohen 2011-01-30 13:55:04 +00:00
parent debf4d9428
commit d6feccdebb
16 changed files with 844 additions and 1177 deletions

View File

@ -63,6 +63,7 @@ language/evas_bidi_utils.c \
language/evas_language_utils.c \
evas_text_utils.c \
evas_font_ot.c \
evas_font_glyph_info.c \
evas_map_image.c \
evas_map_image.h
@ -105,6 +106,7 @@ language/evas_bidi_utils.h \
language/evas_language_utils.h \
evas_text_utils.h \
evas_font_ot.h \
evas_font_glyph_info.h \
evas_map_image_internal.c \
evas_map_image_core.c \
evas_map_image_loop.c

View File

@ -3,190 +3,163 @@
/* Macros for text walking */
/**
* @def EVAS_FONT_UPDATE_KERN()
* @def EVAS_FONT_WALK_TEXT_INIT
* @internal
* This macro updates kern according to kerning.
* This macro assumes the following variables exist:
* intl_props, char_index, fi, kern, index, prev_index
* This macro defines the variables that will later be used with the following
* macros, and by font handling functions.
* @see EVAS_FONT_WALK_TEXT_START
* @see EVAS_FONT_WALK_TEXT_WORK
* @see EVAS_FONT_WALK_TEXT_END
*/
#ifdef BIDI_SUPPORT
#define EVAS_FONT_UPDATE_KERN(is_visual) \
do \
{ \
/* if it's rtl, the kerning matching should be reversed, */ \
/* i.e prev index is now the index and the other way */ \
/* around. There is a slight exception when there are */ \
/* compositing chars involved.*/ \
if (intl_props && (intl_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) && \
visible && !is_visual) \
{ \
if (evas_common_font_query_kerning(fi, index, prev_index, &kern)) \
_pen_x += kern; \
} \
else \
{ \
if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) \
_pen_x += kern; \
} \
} \
while (0)
#else
#define EVAS_FONT_UPDATE_KERN(is_visual) \
do \
{ \
(void) is_visual; \
if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) \
_pen_x += kern; \
} \
while (0)
#endif
# define EVAS_FONT_WALK_TEXT_INIT() \
int _pen_x = 0, _pen_y = 0; \
size_t char_index; \
(void) _pen_y; /* Sometimes it won't be used */
/**
* @def EVAS_FONT_WALK_DEFAULT_TEXT_VISUAL_START
* @def EVAS_FONT_WALK_TEXT_VISUAL_START
* @internal
* This runs through the text in visual order while updating char_index,
* which is the current index in the text.
* Does not end with a ;
* Take a look at EVAS_FONT_WALK_DEFAULT_X_OFF and the like.
* @see EVAS_FONT_WALK_DEFAULT_TEXT_INIT
* @see EVAS_FONT_WALK_DEFAULT_TEXT_WORK
* @see EVAS_FONT_WALK_DEFAULT_TEXT_END
* @see EVAS_FONT_WALK_DEFAULT_TEXT_LOGICAL_START
* Take a look at EVAS_FONT_WALK_X_OFF and the like.
* @see EVAS_FONT_WALK_TEXT_INIT
* @see EVAS_FONT_WALK_TEXT_WORK
* @see EVAS_FONT_WALK_TEXT_END
* @see EVAS_FONT_WALK_TEXT_LOGICAL_START
*/
#define EVAS_FONT_WALK_DEFAULT_TEXT_VISUAL_START() \
#define EVAS_FONT_WALK_TEXT_VISUAL_START() \
do \
{ \
const Eina_Unicode *_base_text; \
int _char_index_d, _i; \
int visible; \
prev_index = 0; \
_base_text = text; \
for ( ; *text ; text++); \
_i = text - _base_text; \
if (intl_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) \
int visible = 1; \
for (char_index = 0 ; char_index < text_props->len ; char_index++) \
{
/**
* @def EVAS_FONT_WALK_TEXT_LOGICAL_START
* @internal
* This runs through the text in logical order while updating char_index,
* which is the current index in the text.
* Does not end with a ;
* Take a look at EVAS_FONT_WALK_X_OFF and the like.
* @see EVAS_FONT_WALK_TEXT_INIT
* @see EVAS_FONT_WALK_TEXT_WORK
* @see EVAS_FONT_WALK_TEXT_END
* @see EVAS_FONT_WALK_TEXT_VISUAL_START
*/
#ifdef BIDI_SUPPORT
#define EVAS_FONT_WALK_TEXT_LOGICAL_START() \
do \
{ \
char_index = text - _base_text - 1; \
text--; \
int _char_index_d, _i; \
int visible = 1; \
_i = text_props->len; \
if (text_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) \
{ \
char_index = text_props->len - 1; \
_char_index_d = -1; \
} \
else \
{ \
char_index = 0; \
text = _base_text; \
_char_index_d = 1; \
} \
for ( ; _i > 0 ; char_index += _char_index_d, text += _char_index_d, _i--) \
{ \
FT_UInt index; \
RGBA_Font_Glyph *fg; \
int _gl, kern; \
_gl = *text; \
if (_gl == 0) break;
/**
* @def EVAS_FONT_WALK_DEFAULT_TEXT_LOGICAL_START
* @internal
* This runs through the text in logical order while updating char_index,
* which is the current index in the text.
* Does not end with a ;
* Take a look at EVAS_FONT_WALK_DEFAULT_X_OFF and the like.
* @see EVAS_FONT_WALK_DEFAULT_TEXT_INIT
* @see EVAS_FONT_WALK_DEFAULT_TEXT_WORK
* @see EVAS_FONT_WALK_DEFAULT_TEXT_END
* @see EVAS_FONT_WALK_DEFAULT_TEXT_VISUAL_START
*/
#define EVAS_FONT_WALK_DEFAULT_TEXT_LOGICAL_START() \
do \
{ \
int visible; \
prev_index = 0; \
for (char_index = 0 ; *text ; text++, char_index++) \
{ \
FT_UInt index; \
RGBA_Font_Glyph *fg; \
int _gl, kern; \
_gl = *text; \
if (_gl == 0) break;
for ( ; _i > 0 ; char_index += _char_index_d, _i--) \
{
#else
#define EVAS_FONT_WALK_TEXT_LOGICAL_START() EVAS_FONT_WALK_TEXT_VISUAL_START()
#endif
/*FIXME: doc */
#define EVAS_FONT_WALK_DEFAULT_X_OFF (0)
#define EVAS_FONT_WALK_DEFAULT_Y_OFF (0)
#define EVAS_FONT_WALK_DEFAULT_X_BEAR (fg->glyph_out->left)
#define EVAS_FONT_WALK_DEFAULT_Y_BEAR (fg->glyph_out->top)
#define _EVAS_FONT_WALK_DEFAULT_X_ADV (fg->glyph->advance.x >> 10)
#define EVAS_FONT_WALK_DEFAULT_X_ADV \
(EVAS_FONT_ROUND_26_6_TO_INT(_EVAS_FONT_WALK_DEFAULT_X_ADV))
#define EVAS_FONT_WALK_DEFAULT_Y_ADV (0)
#define EVAS_FONT_WALK_DEFAULT_WIDTH (fg->glyph_out->bitmap.width)
#define EVAS_FONT_WALK_DEFAULT_POS (char_index)
#define EVAS_FONT_WALK_DEFAULT_IS_LAST \
(!text[char_index])
#define EVAS_FONT_WALK_DEFAULT_IS_FIRST \
#ifdef OT_SUPPORT
# define EVAS_FONT_WALK_X_OFF \
((text_props->info->ot) ? \
(EVAS_FONT_ROUND_26_6_TO_INT( \
EVAS_FONT_OT_X_OFF_GET( \
text_props->info->ot[char_index]))) : \
(0))
# define EVAS_FONT_WALK_Y_OFF \
((text_props->info->ot) ? \
(EVAS_FONT_ROUND_26_6_TO_INT( \
EVAS_FONT_OT_Y_OFF_GET( \
text_props->info->ot[char_index]))) : \
(0))
# define EVAS_FONT_WALK_POS \
((text_props->info->ot) ? \
(EVAS_FONT_OT_POS_GET( \
text_props->info->ot[char_index])) : \
(char_index))
# define EVAS_FONT_WALK_POS_NEXT \
((text_props->info->ot) ? \
((!EVAS_FONT_WALK_IS_LAST) ? \
EVAS_FONT_OT_POS_GET( \
text_props->info->ot[char_index + 1]) : \
EVAS_FONT_WALK_POS \
) : \
((!EVAS_FONT_WALK_IS_LAST) ? \
(char_index + 1) : EVAS_FONT_WALK_POS))
# define EVAS_FONT_WALK_POS_PREV \
((text_props->info->ot) ? \
((char_index > 0) ? \
EVAS_FONT_OT_POS_GET( \
text_props->info->ot[char_index - 1]) : \
EVAS_FONT_WALK_POS \
) : \
((char_index > 0) ? \
(char_index - 1) : EVAS_FONT_WALK_POS))
#else
# define EVAS_FONT_WALK_X_OFF 0
# define EVAS_FONT_WALK_Y_OFF 0
# define EVAS_FONT_WALK_POS (char_index)
# define EVAS_FONT_WALK_POS_NEXT \
((!EVAS_FONT_WALK_IS_LAST) ? \
(char_index + 1) : EVAS_FONT_WALK_POS)
# define EVAS_FONT_WALK_POS_PREV \
((char_index > 0) ? \
(char_index - 1) : EVAS_FONT_WALK_POS)
#endif
#define EVAS_FONT_WALK_X_BEAR (text_props->info->glyph[char_index].x_bear)
#define EVAS_FONT_WALK_Y_BEAR (fg->glyph_out->top)
#define _EVAS_FONT_WALK_X_ADV \
(text_props->info->glyph[char_index].advance)
#define EVAS_FONT_WALK_WIDTH (text_props->info->glyph[char_index].width)
#define EVAS_FONT_WALK_X_ADV \
(EVAS_FONT_ROUND_26_6_TO_INT(_EVAS_FONT_WALK_X_ADV))
#define EVAS_FONT_WALK_PEN_X (EVAS_FONT_ROUND_26_6_TO_INT(_pen_x))
#define EVAS_FONT_WALK_PEN_Y (EVAS_FONT_ROUND_26_6_TO_INT(_pen_y))
#define EVAS_FONT_WALK_Y_ADV (0)
#define EVAS_FONT_WALK_IS_LAST \
(char_index + 1 == text_props->len)
#define EVAS_FONT_WALK_IS_FIRST \
(!char_index)
#define EVAS_FONT_WALK_DEFAULT_POS_NEXT \
((!EVAS_FONT_WALK_DEFAULT_IS_LAST) ? \
(char_index + 1) : \
(char_index) \
)
#define EVAS_FONT_WALK_DEFAULT_POS_PREV \
((!EVAS_FONT_WALK_DEFAULT_IS_FIRST) ? \
(char_index - 1) : \
EVAS_FONT_WALK_DEFAULT_POS \
)
#define EVAS_FONT_WALK_DEFAULT_LEN (EVAS_FONT_WALK_ORIG_LEN)
/**
* @def EVAS_FONT_WALK_DEFAULT_TEXT_WORK
* @internal
* This macro actually updates the values mentioned in EVAS_FONT_WALK_DEFAULT_TEXT_VISUAL_START
* according to the current positing in the walk.
* @see EVAS_FONT_WALK_DEFAULT_TEXT_VISUAL_START
* @see EVAS_FONT_WALK_DEFAULT_TEXT_INIT
* @see EVAS_FONT_WALK_DEFAULT_TEXT_END
*/
#define EVAS_FONT_WALK_DEFAULT_TEXT_WORK(is_visual) \
index = evas_common_font_glyph_search(fn, &fi, _gl); \
LKL(fi->ft_mutex); \
fg = evas_common_font_int_cache_glyph_get(fi, index); \
if (!fg) \
{ \
LKU(fi->ft_mutex); \
continue; \
} \
kern = 0; \
if (EVAS_FONT_CHARACTER_IS_INVISIBLE(_gl)) \
{ \
visible = 0; \
} \
else \
{ \
visible = 1; \
} \
/* hmmm kerning means i can't sanely do my own cached metric */ \
/* tables! grrr - this means font face sharing is kinda... not */ \
/* an option if you want performance */ \
if ((use_kerning) && (prev_index) && (index) && \
(pface == fi->src->ft.face)) \
{ \
EVAS_FONT_UPDATE_KERN(is_visual); \
} \
\
pface = fi->src->ft.face; \
LKU(fi->ft_mutex); \
#define EVAS_FONT_WALK_LEN (text_props->len)
/**
* @def EVAS_FONT_WALK_DEFAULT_TEXT_END
* @def EVAS_FONT_WALK_TEXT_WORK
* @internal
* Closes EVAS_FONT_WALK_DEFAULT_TEXT_VISUAL_START, needs to end with a ;
* @see EVAS_FONT_WALK_DEFAULT_TEXT_VISUAL_START
* @see EVAS_FONT_WALK_DEFAULT_TEXT_INIT
* @see EVAS_FONT_WALK_DEFAULT_TEXT_WORK
* This macro actually updates the values mentioned in EVAS_FONT_WALK_TEXT_VISUAL_START
* according to the current positing in the walk.
* @see EVAS_FONT_WALK_TEXT_VISUAL_START
* @see EVAS_FONT_WALK_TEXT_INIT
* @see EVAS_FONT_WALK_TEXT_END
*/
#define EVAS_FONT_WALK_DEFAULT_TEXT_END() \
#define EVAS_FONT_WALK_TEXT_WORK() do {} while(0);
/**
* @def EVAS_FONT_WALK_TEXT_END
* @internal
* Closes EVAS_FONT_WALK_TEXT_VISUAL_START, needs to end with a ;
* @see EVAS_FONT_WALK_TEXT_VISUAL_START
* @see EVAS_FONT_WALK_TEXT_INIT
* @see EVAS_FONT_WALK_TEXT_WORK
*/
#define EVAS_FONT_WALK_TEXT_END() \
if (visible) \
{ \
_pen_x += _EVAS_FONT_WALK_DEFAULT_X_ADV; \
_pen_x += _EVAS_FONT_WALK_X_ADV; \
} \
prev_index = index; \
} \
} \
while(0)

View File

@ -49,7 +49,7 @@ struct cinfo
#if defined(METRIC_CACHE) || defined(WORD_CACHE)
LK(lock_words); // for word cache call
static Eina_Inlist *words = NULL;
static struct prword *evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *text, const Evas_Text_Props *intl_props, int len, RGBA_Font *fn, RGBA_Font_Int *fi,int use_kerning);
static struct prword *evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *text, const Evas_Text_Props *text_props, int len, RGBA_Font *fn, RGBA_Font_Int *fi,int use_kerning);
#endif
EAPI void
@ -389,19 +389,20 @@ evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, int gl)
}
/*
* BiDi handling: We receive the shaped string + other props from intl_props,
* BiDi handling: We receive the shaped string + other props from text_props,
* we need to reorder it so we'll have the visual string (the way we draw)
* and then for kerning we have to switch the order of the kerning query (as the prev
* is on the right, and not on the left).
*/
static void
evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const Eina_Unicode *in_text,
const Evas_Text_Props *intl_props, RGBA_Gfx_Func func, int ext_x, int ext_y, int ext_w,
const Evas_Text_Props *text_props, RGBA_Gfx_Func func, int ext_x, int ext_y, int ext_w,
int ext_h, RGBA_Font_Int *fi, int im_w, int im_h __UNUSED__, int use_kerning
)
{
const Eina_Unicode *text = in_text;
DATA32 *im;
FT_Face pface = NULL;
EVAS_FONT_WALK_TEXT_INIT();
#if defined(METRIC_CACHE) || defined(WORD_CACHE)
@ -415,7 +416,7 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
struct prword *word;
word =
evas_font_word_prerender(dc, text, intl_props,
evas_font_word_prerender(dc, text, text_props,
len, fn, fi, use_kerning);
if (word)
{
@ -492,6 +493,8 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
# endif
}
}
#else
(void) use_kerning;
#endif
if (fi->src->current_size != fi->size)
@ -504,14 +507,45 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
im = dst->image.data;
#ifdef OT_SUPPORT
if (evas_common_font_ot_is_enabled() && intl_props->ot_data)
/* Load the glyph according to the first letter of the script, preety
* bad, but will have to do */
{
EVAS_FONT_WALK_OT_TEXT_VISUAL_START()
/* Skip common chars */
const Eina_Unicode *tmp;
for (tmp = text ;
*tmp &&
evas_common_language_char_script_get(*tmp) ==
EVAS_SCRIPT_COMMON ;
tmp++)
;
if (!*tmp && (tmp > text)) tmp--;
evas_common_font_glyph_search(fn, &fi, *tmp);
}
EVAS_FONT_WALK_TEXT_VISUAL_START()
{
FT_UInt index;
RGBA_Font_Glyph *fg;
int chr_x, chr_y, chr_w;
EVAS_FONT_WALK_OT_TEXT_WORK(EINA_TRUE);
index = text_props->info->glyph[char_index].index;
LKL(fi->ft_mutex);
fg = evas_common_font_int_cache_glyph_get(fi, index);
if (!fg)
{
LKU(fi->ft_mutex);
continue;
}
if (EVAS_FONT_CHARACTER_IS_INVISIBLE(text[EVAS_FONT_WALK_POS]))
{
visible = 0;
}
else
{
visible = 1;
}
pface = fi->src->ft.face;
LKU(fi->ft_mutex);
if (dc->font_ext.func.gl_new)
{
@ -520,9 +554,9 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
fg->ext_dat_free = dc->font_ext.func.gl_free;
}
chr_x = x + EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_OT_X_OFF + EVAS_FONT_WALK_OT_X_BEAR;
chr_y = y + EVAS_FONT_WALK_PEN_Y + EVAS_FONT_WALK_OT_Y_OFF + EVAS_FONT_WALK_OT_Y_BEAR;
chr_w = EVAS_FONT_WALK_OT_WIDTH;
chr_x = x + EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_X_OFF + EVAS_FONT_WALK_X_BEAR;
chr_y = y + EVAS_FONT_WALK_PEN_Y + EVAS_FONT_WALK_Y_OFF + EVAS_FONT_WALK_Y_BEAR;
chr_w = EVAS_FONT_WALK_WIDTH;
if (chr_x < (ext_x + ext_w))
{
@ -651,163 +685,13 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
else
break;
}
EVAS_FONT_WALK_OT_TEXT_END();
}
else
#endif
{
EVAS_FONT_WALK_DEFAULT_TEXT_VISUAL_START()
{
int chr_x, chr_y, chr_w;
EVAS_FONT_WALK_DEFAULT_TEXT_WORK(EINA_TRUE);
if (dc->font_ext.func.gl_new)
{
/* extension calls */
fg->ext_dat = dc->font_ext.func.gl_new(dc->font_ext.data, fg);
fg->ext_dat_free = dc->font_ext.func.gl_free;
}
chr_x = x + EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_DEFAULT_X_OFF + EVAS_FONT_WALK_DEFAULT_X_BEAR;
chr_y = y + EVAS_FONT_WALK_PEN_Y + EVAS_FONT_WALK_DEFAULT_Y_OFF + EVAS_FONT_WALK_DEFAULT_Y_BEAR;
chr_w = EVAS_FONT_WALK_DEFAULT_WIDTH;
if (chr_x < (ext_x + ext_w))
{
DATA8 *data;
int i, j, w, h;
data = fg->glyph_out->bitmap.buffer;
j = fg->glyph_out->bitmap.pitch;
w = fg->glyph_out->bitmap.width;
if (j < w) j = w;
h = fg->glyph_out->bitmap.rows;
/*
if ((fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays)
&& (fg->glyph_out->bitmap.num_grays == 256)
)
*/
{
if ((j > 0) && (chr_x + w > ext_x))
{
if ((fg->ext_dat) && (dc->font_ext.func.gl_draw))
{
/* ext glyph draw */
dc->font_ext.func.gl_draw(dc->font_ext.data,
(void *)dst,
dc, fg, chr_x,
y - (chr_y - y));
}
else
{
if ((fg->glyph_out->bitmap.num_grays == 256) &&
(fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays))
{
for (i = 0; i < h; i++)
{
int dx, dy;
int in_x, in_w;
in_x = 0;
in_w = 0;
dx = chr_x;
dy = y - (chr_y - i - y);
#ifdef EVAS_SLI
if (((dy) % dc->sli.h) == dc->sli.y)
#endif
{
if ((dx < (ext_x + ext_w)) &&
(dy >= (ext_y)) &&
(dy < (ext_y + ext_h)))
{
if (dx + w > (ext_x + ext_w))
in_w += (dx + w) - (ext_x + ext_w);
if (dx < ext_x)
{
in_w += ext_x - dx;
in_x = ext_x - dx;
dx = ext_x;
}
if (in_w < w)
{
func(NULL, data + (i * j) + in_x, dc->col.col,
im + (dy * im_w) + dx, w - in_w);
}
}
}
}
}
else
{
DATA8 *tmpbuf = NULL, *dp, *tp, bits;
int bi, bj;
const DATA8 bitrepl[2] = {0x0, 0xff};
tmpbuf = alloca(w);
for (i = 0; i < h; i++)
{
int dx, dy;
int in_x, in_w, end;
in_x = 0;
in_w = 0;
dx = chr_x;
dy = y - (chr_y - i - y);
#ifdef EVAS_SLI
if (((dy) % dc->sli.h) == dc->sli.y)
#endif
{
tp = tmpbuf;
dp = data + (i * fg->glyph_out->bitmap.pitch);
for (bi = 0; bi < w; bi += 8)
{
bits = *dp;
if ((w - bi) < 8) end = w - bi;
else end = 8;
for (bj = 0; bj < end; bj++)
{
*tp = bitrepl[(bits >> (7 - bj)) & 0x1];
tp++;
}
dp++;
}
if ((dx < (ext_x + ext_w)) &&
(dy >= (ext_y)) &&
(dy < (ext_y + ext_h)))
{
if (dx + w > (ext_x + ext_w))
in_w += (dx + w) - (ext_x + ext_w);
if (dx < ext_x)
{
in_w += ext_x - dx;
in_x = ext_x - dx;
dx = ext_x;
}
if (in_w < w)
{
func(NULL, tmpbuf + in_x, dc->col.col,
im + (dy * im_w) + dx, w - in_w);
}
}
}
}
}
}
}
}
}
else
break;
}
EVAS_FONT_WALK_DEFAULT_TEXT_END();
}
EVAS_FONT_WALK_TEXT_END();
evas_common_font_int_use_trim();
}
EAPI void
evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const Eina_Unicode *text,
const Evas_Text_Props *intl_props)
const Evas_Text_Props *text_props)
{
int ext_x, ext_y, ext_w, ext_h;
int im_w, im_h;
@ -859,7 +743,7 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int
if (!dc->cutout.rects)
{
evas_common_font_draw_internal(dst, dc, fn, x, y, text, intl_props,
evas_common_font_draw_internal(dst, dc, fn, x, y, text, text_props,
func, ext_x, ext_y, ext_w, ext_h, fi,
im_w, im_h, use_kerning);
}
@ -875,7 +759,7 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int
{
r = rects->rects + i;
evas_common_draw_context_set_clip(dc, r->x, r->y, r->w, r->h);
evas_common_font_draw_internal(dst, dc, fn, x, y, text, intl_props,
evas_common_font_draw_internal(dst, dc, fn, x, y, text, text_props,
func, r->x, r->y, r->w, r->h, fi,
im_w, im_h, use_kerning);
}
@ -892,7 +776,7 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int
/* Only used if cache is on */
#if defined(METRIC_CACHE) || defined(WORD_CACHE)
struct prword *
evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *in_text, const Evas_Text_Props *intl_props, int len, RGBA_Font *fn, RGBA_Font_Int *fi,int use_kerning)
evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *in_text, const Evas_Text_Props *text_props, int len, RGBA_Font *fn, RGBA_Font_Int *fi,int use_kerning)
{
struct cinfo *metrics;
const Eina_Unicode *text = in_text;
@ -930,14 +814,14 @@ evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *in_text, con
/* It's a bit hackish to use index and fg here as they are internal,
* but that'll have to be good enough ATM */
#ifdef OT_SUPPORT
if (evas_common_font_ot_is_enabled() && intl_props->ot_data)
if (evas_common_font_ot_is_enabled())
{
len = intl_props->ot_data->len;
len = text_props->info->ot_data->len;
metrics = malloc(sizeof(struct cinfo) * len);
EVAS_FONT_WALK_OT_TEXT_VISUAL_START()
EVAS_FONT_WALK_TEXT_VISUAL_START()
{
struct cinfo *ci = metrics + char_index;
EVAS_FONT_WALK_OT_TEXT_WORK(EINA_FALSE);
EVAS_FONT_WALK_TEXT_WORK(EINA_FALSE);
/* Currently broken with invisible chars if (!visible) continue; */
ci->index = index;
ci->fg = fg;
@ -958,19 +842,19 @@ evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *in_text, con
if (above > baseline) baseline = above;
ci->pos.x = EVAS_FONT_WALK_PEN_X + ci->fg->glyph_out->left;
ci->pos.y = EVAS_FONT_WALK_PEN_Y + ci->fg->glyph_out->top;
last_delta = EVAS_FONT_WALK_OT_X_ADV -
last_delta = EVAS_FONT_WALK_X_ADV -
(ci->bm.w + ci->fg->glyph_out->left);
}
EVAS_FONT_WALK_OT_TEXT_END();
EVAS_FONT_WALK_TEXT_END();
}
else
#endif
{
metrics = malloc(sizeof(struct cinfo) * len);
EVAS_FONT_WALK_DEFAULT_TEXT_LOGICAL_START()
EVAS_FONT_WALK_TEXT_LOGICAL_START()
{
struct cinfo *ci = metrics + char_index;
EVAS_FONT_WALK_DEFAULT_TEXT_WORK(EINA_FALSE);
EVAS_FONT_WALK_TEXT_WORK(EINA_FALSE);
/* Currently broken with invisible chars if (!visible) continue; */
ci->index = index;
ci->fg = fg;
@ -991,10 +875,10 @@ evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *in_text, con
if (above > baseline) baseline = above;
ci->pos.x = EVAS_FONT_WALK_PEN_X + ci->fg->glyph_out->left;
ci->pos.y = EVAS_FONT_WALK_PEN_Y + ci->fg->glyph_out->top;
last_delta = EVAS_FONT_WALK_DEFAULT_X_ADV -
last_delta = EVAS_FONT_WALK_X_ADV -
(ci->bm.w + ci->fg->glyph_out->left);
}
EVAS_FONT_WALK_DEFAULT_TEXT_END();
EVAS_FONT_WALK_TEXT_END();
}
/* First loop done */

View File

@ -0,0 +1,166 @@
#include "evas_common.h"
#include "evas_font_private.h" /* for Frame-Queuing support */
#include "evas_font_ot.h"
#include "evas_font_glyph_info.h"
EAPI Eina_Bool
evas_common_font_glyph_info_create(void *_fn, const Eina_Unicode *text,
Evas_Text_Props *text_props, int len)
{
RGBA_Font *fn = (RGBA_Font *) _fn;
RGBA_Font_Int *fi;
size_t char_index;
if (text_props->info)
{
evas_common_text_props_content_unref(text_props);
}
text_props->info = calloc(1, sizeof(Evas_Text_Props_Info));
fi = fn->fonts->data;
/* evas_common_font_size_use(fn); */
evas_common_font_int_reload(fi);
if (fi->src->current_size != fi->size)
{
FTLOCK();
FT_Activate_Size(fi->ft.size);
FTUNLOCK();
fi->src->current_size = fi->size;
}
#ifdef OT_SUPPORT
if (evas_common_font_ot_is_enabled())
{
evas_common_font_ot_populate_text_props(fn, text, text_props, len);
/* Load the glyph according to the first letter of the script, preety
* bad, but will have to do */
{
/* Skip common chars */
const Eina_Unicode *tmp;
for (tmp = text ;
*tmp &&
evas_common_language_char_script_get(*tmp) ==
EVAS_SCRIPT_COMMON ;
tmp++)
;
if (!*tmp && (tmp > text)) tmp--;
evas_common_font_glyph_search(fn, &fi, *tmp);
}
for (char_index = 0 ; char_index < text_props->len ; char_index++)
{
FT_UInt index;
RGBA_Font_Glyph *fg;
index = text_props->info->glyph[char_index].index;
LKL(fi->ft_mutex);
fg = evas_common_font_int_cache_glyph_get(fi, index);
if (!fg)
{
LKU(fi->ft_mutex);
continue;
}
LKU(fi->ft_mutex);
text_props->info->glyph[char_index].x_bear =
fg->glyph_out->left;
text_props->info->glyph[char_index].width =
fg->glyph_out->bitmap.width;
/* text_props->info->glyph[char_index].advance =
* text_props->info->glyph[char_index].index =
* already done by the ot function */
/* FIXME add visible handling */
}
}
else
#endif
{
/* We are walking the string in visual ordering */
Eina_Bool use_kerning;
FT_UInt prev_index;
FT_Face pface = NULL;
int adv_d, i;
FTLOCK();
use_kerning = FT_HAS_KERNING(fi->src->ft.face);
FTUNLOCK();
prev_index = 0;
i = len;
text_props->info->glyph = calloc(len,
sizeof(Evas_Font_Glyph_Info));
if (text_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL)
{
text += len - 1;
adv_d = -1;
}
else
{
adv_d = 1;
}
char_index = 0;
for ( ; i > 0 ; char_index++, text += adv_d, i--)
{
FT_UInt index;
RGBA_Font_Glyph *fg;
int _gl, kern;
_gl = *text;
if (_gl == 0) break;
index = evas_common_font_glyph_search(fn, &fi, _gl);
LKL(fi->ft_mutex);
fg = evas_common_font_int_cache_glyph_get(fi, index);
if (!fg)
{
LKU(fi->ft_mutex);
continue;
}
kern = 0;
if ((use_kerning) && (prev_index) && (index) &&
(pface == fi->src->ft.face))
{
#ifdef BIDI_SUPPORT
/* if it's rtl, the kerning matching should be reversed, */
/* i.e prev index is now the index and the other way */
/* around. There is a slight exception when there are */
/* compositing chars involved.*/
if (text_props &&
(text_props->bidi.dir != EVAS_BIDI_DIRECTION_RTL))
{
if (evas_common_font_query_kerning(fi, index, prev_index, &kern))
{
text_props->info->glyph[char_index - 1].advance +=
kern;
}
}
else
#endif
{
if (evas_common_font_query_kerning(fi, prev_index, index, &kern))
{
text_props->info->glyph[char_index - 1].advance +=
kern;
}
}
}
pface = fi->src->ft.face;
LKU(fi->ft_mutex);
text_props->info->glyph[char_index].index = index;
text_props->info->glyph[char_index].x_bear =
fg->glyph_out->left;
text_props->info->glyph[char_index].advance =
fg->glyph->advance.x >> 10;
text_props->info->glyph[char_index].width =
fg->glyph_out->bitmap.width;
prev_index = index;
}
text_props->len = len;
}
text_props->info->refcount = 1;
return EINA_TRUE;
}

View File

@ -0,0 +1,25 @@
#ifndef _EVAS_FONT_METRICS_H
# define _EVAS_FONT_METRICS_H
/* Sorted in visual order when created */
struct _Evas_Font_Glyph_Info
{
unsigned int index; /* Should conform to FT */
Evas_Coord x_bear;
#if 0
/* This one is rarely used, only in draw, in which we already get the glyph
* so it doesn't really save time. Leaving it here just so no one will
* add it thinking it was accidentally skipped */
Evas_Coord y_bear;
#endif
Evas_Coord width;
Evas_Coord advance;
};
typedef struct _Evas_Font_Glyph_Info Evas_Font_Glyph_Info;
EAPI Eina_Bool
evas_common_font_glyph_info_create(void *_fn, const Eina_Unicode *text,
Evas_Text_Props *text_props, int len);
#endif

View File

@ -34,21 +34,22 @@ evas_common_font_ot_is_enabled(void)
#ifdef OT_SUPPORT
/* FIXME: doc. returns #items */
EAPI int
evas_common_font_ot_cluster_size_get(const Evas_Text_Props *props, size_t char_index, int orig_len)
evas_common_font_ot_cluster_size_get(const Evas_Text_Props *props, size_t char_index)
{
int i;
int items;
int left_bound, right_bound;
size_t base_cluster = EVAS_FONT_OT_POS_GET(props->ot_data->items[char_index]);
char_index += props->start;
size_t base_cluster = EVAS_FONT_OT_POS_GET(props->info->ot[char_index]);
for (i = (int) char_index ;
(i >= 0) &&
(EVAS_FONT_OT_POS_GET(props->ot_data->items[i]) == base_cluster) ;
(i >= (int) props->start) &&
(EVAS_FONT_OT_POS_GET(props->info->ot[i]) == base_cluster) ;
i--)
;
left_bound = i;
for (i = (int) char_index + 1;
(i < (int) props->ot_data->len) &&
(EVAS_FONT_OT_POS_GET(props->ot_data->items[i]) == base_cluster) ;
(i < (int) (props->start + props->len)) &&
(EVAS_FONT_OT_POS_GET(props->info->ot[i]) == base_cluster) ;
i++)
;
right_bound = i;
@ -60,26 +61,26 @@ evas_common_font_ot_cluster_size_get(const Evas_Text_Props *props, size_t char_i
{
if (left_bound < 0)
{
items = orig_len -
props->ot_data->items[left_bound + 1].source_cluster;
items = props->start + props->len -
props->info->ot[left_bound + 1].source_cluster;
}
else
{
items = props->ot_data->items[left_bound].source_cluster -
props->ot_data->items[left_bound + 1].source_cluster;
items = props->info->ot[left_bound].source_cluster -
props->info->ot[left_bound + 1].source_cluster;
}
}
else
{
if (right_bound == (int) props->ot_data->len)
if (right_bound == (int) props->len)
{
items = orig_len -
props->ot_data->items[right_bound - 1].source_cluster;
items = props->start + props->len -
props->info->ot[right_bound - 1].source_cluster;
}
else
{
items = props->ot_data->items[right_bound].source_cluster -
props->ot_data->items[right_bound - 1].source_cluster;
items = props->info->ot[right_bound].source_cluster -
props->info->ot[right_bound - 1].source_cluster;
}
}
return (items > 0) ? items : 1;
@ -114,152 +115,6 @@ _evas_common_font_ot_shape(hb_buffer_t *buffer, RGBA_Font_Source *src)
hb_font_destroy(hb_font);
}
/* Won't work in the middle of ligatures */
EAPI void
evas_common_font_ot_cutoff_text_props(Evas_Text_Props *props, int cutoff)
{
Evas_Font_OT_Data *new_data;
if ((cutoff <= 0) || (!props->ot_data) ||
(((size_t) cutoff) >= props->ot_data->len))
return;
new_data = malloc(sizeof(Evas_Font_OT_Data));
memcpy(new_data, props->ot_data, sizeof(Evas_Font_OT_Data));
new_data->refcount = 1;
new_data->len = cutoff;
new_data->items = malloc(cutoff * sizeof(Evas_Font_OT_Data_Item));
if (props->bidi.dir == EVAS_BIDI_DIRECTION_RTL)
{
memcpy(new_data->items,
props->ot_data->items + (props->ot_data->len - cutoff),
cutoff * sizeof(Evas_Font_OT_Data_Item));
}
else
{
memcpy(new_data->items,
props->ot_data->items,
cutoff * sizeof(Evas_Font_OT_Data_Item));
}
evas_common_font_ot_props_unref(props->ot_data);
props->ot_data = new_data;
}
/* Won't work in the middle of ligatures
* aissumes ext doesn't have an already init ot_data
* we assume there's at least one char in each part */
EAPI void
evas_common_font_ot_split_text_props(Evas_Text_Props *base,
Evas_Text_Props *ext, int cutoff)
{
Evas_Font_OT_Data *new_data;
int i;
if ((cutoff <= 0) || (!base->ot_data) ||
(((size_t) cutoff) >= base->ot_data->len))
return;
ext->ot_data = calloc(1, sizeof(Evas_Font_OT_Data));
ext->ot_data->refcount = 1;
ext->ot_data->len = base->ot_data->len - cutoff;
ext->ot_data->items = calloc(ext->ot_data->len,
sizeof(Evas_Font_OT_Data_Item));
new_data = malloc(sizeof(Evas_Font_OT_Data));
memcpy(new_data, base->ot_data, sizeof(Evas_Font_OT_Data));
new_data->refcount = 1;
new_data->items = malloc(cutoff * sizeof(Evas_Font_OT_Data_Item));
new_data->len = cutoff;
if (base->bidi.dir == EVAS_BIDI_DIRECTION_RTL)
{
memcpy(ext->ot_data->items, base->ot_data->items,
ext->ot_data->len * sizeof(Evas_Font_OT_Data_Item));
memcpy(new_data->items,
base->ot_data->items + ext->ot_data->len,
cutoff * sizeof(Evas_Font_OT_Data_Item));
}
else
{
memcpy(ext->ot_data->items, base->ot_data->items + cutoff,
ext->ot_data->len * sizeof(Evas_Font_OT_Data_Item));
memcpy(new_data->items, base->ot_data->items,
cutoff * sizeof(Evas_Font_OT_Data_Item));
}
evas_common_font_ot_props_unref(base->ot_data);
base->ot_data = new_data;
/* Adjust the offset of the clusters */
{
size_t min;
min = ext->ot_data->items[0].source_cluster;
for (i = 1 ; i < (int) ext->ot_data->len ; i++)
{
if (ext->ot_data->items[i].source_cluster < min)
{
min = ext->ot_data->items[i].source_cluster;
}
}
for (i = 0 ; i < (int) ext->ot_data->len ; i++)
{
ext->ot_data->items[i].source_cluster -= min;
}
ext->ot_data->offset = base->ot_data->offset + min;
}
}
/* Won't work in the middle of ligatures
* assumes both are init correctly and that both are from the
* same origin item, i.e both have the same script + direction.
* assume item1 is logically first */
EAPI void
evas_common_font_ot_merge_text_props(Evas_Text_Props *item1,
const Evas_Text_Props *item2)
{
Evas_Font_OT_Data *new_data;
Evas_Font_OT_Data_Item *itr; /* Itr will be used for adding back
the offsets */
size_t len;
if (!item1->ot_data || !item2->ot_data)
return;
len = item1->ot_data->len + item2->ot_data->len;
new_data = malloc(sizeof(Evas_Font_OT_Data));
memcpy(new_data, item1->ot_data, sizeof(Evas_Font_OT_Data));
new_data->refcount = 1;
new_data->items = malloc(len * sizeof(Evas_Font_OT_Data_Item));
new_data->len = len;
if (item1->bidi.dir == EVAS_BIDI_DIRECTION_RTL)
{
memcpy(new_data->items, item2->ot_data->items,
item2->ot_data->len * sizeof(Evas_Font_OT_Data_Item));
memcpy(new_data->items + item2->ot_data->len, item1->ot_data->items,
item1->ot_data->len * sizeof(Evas_Font_OT_Data_Item));
itr = new_data->items;
}
else
{
memcpy(new_data->items, item1->ot_data->items,
item1->ot_data->len * sizeof(Evas_Font_OT_Data_Item));
memcpy(new_data->items + item1->ot_data->len, item2->ot_data->items,
item2->ot_data->len * sizeof(Evas_Font_OT_Data_Item));
itr = new_data->items + item1->ot_data->len;
}
evas_common_font_ot_props_unref(item1->ot_data);
item1->ot_data = new_data;
/* Add back the offset of item2 to the newly created */
if (item2->ot_data->offset > 0)
{
int i;
for (i = 0 ; i < (int) item2->ot_data->len ; i++, itr++)
{
/* This must be > 0, just because this is how it works */
itr->source_cluster += item2->ot_data->offset -
item1->ot_data->offset;
}
}
}
EAPI Eina_Bool
evas_common_font_ot_populate_text_props(void *_fn, const Eina_Unicode *text,
Evas_Text_Props *props, int len)
@ -272,12 +127,6 @@ evas_common_font_ot_populate_text_props(void *_fn, const Eina_Unicode *text,
int slen;
unsigned int i;
if (!evas_common_font_ot_is_enabled()) return EINA_TRUE;
if (props->ot_data)
{
evas_common_font_ot_props_unref(props->ot_data);
}
props->ot_data = calloc(1, sizeof(Evas_Font_OT_Data));
props->ot_data->refcount = 1;
fi = fn->fonts->data;
/* Load the font needed for this script */
@ -323,18 +172,20 @@ evas_common_font_ot_populate_text_props(void *_fn, const Eina_Unicode *text,
_evas_common_font_ot_shape(buffer, fi->src);
props->ot_data->len = hb_buffer_get_length(buffer);
props->ot_data->items = calloc(props->ot_data->len,
sizeof(Evas_Font_OT_Data_Item));
props->len = hb_buffer_get_length(buffer);
props->info->ot = calloc(props->len,
sizeof(Evas_Font_OT_Info));
props->info->glyph = calloc(props->len,
sizeof(Evas_Font_Glyph_Info));
positions = hb_buffer_get_glyph_positions(buffer);
infos = hb_buffer_get_glyph_infos(buffer);
for (i = 0 ; i < props->ot_data->len ; i++)
for (i = 0 ; i < props->len ; i++)
{
props->ot_data->items[i].index = infos[i].codepoint;
props->ot_data->items[i].source_cluster = infos[i].cluster;
props->ot_data->items[i].x_advance = positions[i].x_advance;
props->ot_data->items[i].x_offset = positions[i].x_offset;
props->ot_data->items[i].y_offset = positions[i].y_offset;
props->info->ot[i].source_cluster = infos[i].cluster;
props->info->ot[i].x_offset = positions[i].x_offset;
props->info->ot[i].y_offset = positions[i].y_offset;
props->info->glyph[i].index = infos[i].codepoint;
props->info->glyph[i].advance = positions[i].x_advance;
}
hb_buffer_destroy(buffer);
@ -343,23 +194,5 @@ evas_common_font_ot_populate_text_props(void *_fn, const Eina_Unicode *text,
return EINA_FALSE;
}
EAPI void
evas_common_font_ot_props_ref(Evas_Font_OT_Data *data)
{
data->refcount++;
}
EAPI void
evas_common_font_ot_props_unref(Evas_Font_OT_Data *data)
{
OTLOCK();
if (--data->refcount == 0)
{
if (data->items)
free(data->items);
free(data);
}
OTUNLOCK();
}
#endif

View File

@ -12,58 +12,31 @@
# ifdef OT_SUPPORT
# include <stdlib.h>
typedef struct _Evas_Font_OT_Data Evas_Font_OT_Data;
typedef struct _Evas_Font_OT_Data_Item Evas_Font_OT_Data_Item;
struct _Evas_Font_OT_Data
{
int refcount;
size_t len;
Evas_Font_OT_Data_Item *items;
size_t offset; /* The offset from the start of the script segment,
this is useful when it's a split item */
};
typedef struct _Evas_Font_OT_Info Evas_Font_OT_Info;
# else
typedef void *Evas_Font_OT_Data;
typedef void *Evas_Font_OT_Info;
# endif
# include "Evas.h"
# ifdef OT_SUPPORT
struct _Evas_Font_OT_Data_Item
struct _Evas_Font_OT_Info
{
unsigned int index; /* Should conform to FT */
size_t source_cluster;
Evas_Coord x_offset;
Evas_Coord y_offset;
Evas_Coord x_advance;
};
# endif
# ifdef OT_SUPPORT
# define EVAS_FONT_OT_X_OFF_GET(a) ((a).x_offset)
# define EVAS_FONT_OT_Y_OFF_GET(a) ((a).y_offset)
# define EVAS_FONT_OT_X_ADV_GET(a) ((a).x_advance)
//# define EVAS_FONT_OT_Y_ADV_GET(a) ((a).y_advance)
# define EVAS_FONT_OT_INDEX_GET(a) ((a).index)
# define EVAS_FONT_OT_POS_GET(a) ((a).source_cluster)
# else
# define EVAS_FONT_OT_X_OFF_GET(a) (0)
# define EVAS_FONT_OT_Y_OFF_GET(a) (0)
# define EVAS_FONT_OT_X_ADV_GET(a) (0)
//# define EVAS_FONT_OT_POS_Y_ADV_GET(a) (0)
# define EVAS_FONT_OT_INDEX_GET(a) (0) /* FIXME!!! */
# define EVAS_FONT_OT_POS_GET(a) (0) /* FIXME!!! */
# endif
EAPI Eina_Bool
evas_common_font_ot_is_enabled(void);
EAPI void
evas_common_font_ot_props_ref(Evas_Font_OT_Data *data);
EAPI void
evas_common_font_ot_props_unref(Evas_Font_OT_Data *data);
EAPI void
evas_common_font_ot_load_face(void *_font);
@ -72,7 +45,7 @@ evas_common_font_ot_unload_face(void *_font);
# include "evas_text_utils.h"
EAPI int
evas_common_font_ot_cluster_size_get(const Evas_Text_Props *props, size_t char_index, int orig_len);
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,

View File

@ -36,7 +36,7 @@
if (!*tmp && (tmp > text)) tmp--; \
evas_common_font_glyph_search(fn, &fi, *tmp); \
} \
for (char_index = 0 ; char_index < intl_props->ot_data->len ; char_index++) \
for (char_index = 0 ; char_index < intl_props->len ; char_index++) \
{ \
FT_UInt index; \
RGBA_Font_Glyph *fg; \
@ -72,10 +72,10 @@
evas_common_font_glyph_search(fn, &fi, *tmp); \
} \
prev_index = 0; \
_i = intl_props->ot_data->len; \
_i = intl_props->len; \
if (intl_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) \
{ \
char_index = intl_props->ot_data->len - 1; \
char_index = intl_props->len - 1; \
_char_index_d = -1; \
} \
else \
@ -92,39 +92,39 @@
#define EVAS_FONT_WALK_OT_X_OFF \
(EVAS_FONT_ROUND_26_6_TO_INT( \
EVAS_FONT_OT_X_OFF_GET( \
intl_props->ot_data->items[char_index])))
intl_props->info->ot[char_index])))
#define EVAS_FONT_WALK_OT_Y_OFF \
(EVAS_FONT_ROUND_26_6_TO_INT( \
EVAS_FONT_OT_Y_OFF_GET( \
intl_props->ot_data->items[char_index])))
#define EVAS_FONT_WALK_OT_X_BEAR (fg->glyph_out->left)
intl_props->info->ot[char_index])))
#define EVAS_FONT_WALK_OT_X_BEAR (intl_props->info->glyph[char_index].x_bear)
#define EVAS_FONT_WALK_OT_Y_BEAR (fg->glyph_out->top)
#define _EVAS_FONT_WALK_OT_X_ADV \
(EVAS_FONT_OT_X_ADV_GET( \
intl_props->ot_data->items[char_index]))
(intl_props->info->glyph[char_index].advance)
#define EVAS_FONT_WALK_OT_X_ADV \
(EVAS_FONT_ROUND_26_6_TO_INT(_EVAS_FONT_WALK_OT_X_ADV))
#define EVAS_FONT_WALK_OT_WIDTH (fg->glyph_out->bitmap.width)
(EVAS_FONT_ROUND_26_6_TO_INT( \
_EVAS_FONT_WALK_OT_X_ADV))
#define EVAS_FONT_WALK_OT_WIDTH (intl_props->info->glyph[char_index].width)
#define EVAS_FONT_WALK_OT_POS \
(EVAS_FONT_OT_POS_GET( \
intl_props->ot_data->items[char_index]))
intl_props->info->ot[char_index]))
#define EVAS_FONT_WALK_OT_IS_LAST \
(char_index + 1 == intl_props->ot_data->len)
(char_index + 1 == intl_props->len)
#define EVAS_FONT_WALK_OT_IS_FIRST \
(!char_index)
#define EVAS_FONT_WALK_OT_POS_NEXT \
((!EVAS_FONT_WALK_OT_IS_LAST) ? \
EVAS_FONT_OT_POS_GET( \
intl_props->ot_data->items[char_index + 1]) : \
intl_props->info->ot[char_index + 1]) : \
EVAS_FONT_WALK_OT_POS \
)
#define EVAS_FONT_WALK_OT_POS_PREV \
((char_index > 0) ? \
EVAS_FONT_OT_POS_GET( \
intl_props->ot_data->items[char_index - 1]) : \
intl_props->info->ot[char_index - 1]) : \
EVAS_FONT_WALK_OT_POS \
)
#define EVAS_FONT_WALK_OT_LEN (intl_props->ot_data->len)
#define EVAS_FONT_WALK_OT_LEN (intl_props->len)
/**
* @def EVAS_FONT_WALK_OT_TEXT_WORK
* @internal
@ -135,7 +135,7 @@
* @see EVAS_FONT_WALK_OT_TEXT_END
*/
#define EVAS_FONT_WALK_OT_TEXT_WORK(is_visual) \
index = EVAS_FONT_OT_INDEX_GET(intl_props->ot_data->items[char_index]); \
index = intl_props->info->glyph[char_index].index; \
LKL(fi->ft_mutex); \
fg = evas_common_font_int_cache_glyph_get(fi, index); \
if (!fg) \

View File

@ -54,26 +54,4 @@ void evas_common_font_int_reload(RGBA_Font_Int *fi);
# endif
# include "evas_font_default_walk.x"
/**
* @def EVAS_FONT_WALK_TEXT_INIT
* @internal
* This macro defines the variables that will later be used with the following
* macros, and by font handling functions.
* @see EVAS_FONT_WALK_TEXT_START
* @see EVAS_FONT_WALK_TEXT_WORK
* @see EVAS_FONT_WALK_TEXT_END
*/
# define EVAS_FONT_WALK_TEXT_INIT() \
int _pen_x = 0, _pen_y = 0; \
size_t char_index; \
FT_UInt prev_index; \
FT_Face pface = NULL; \
int _len = eina_unicode_strlen(text); \
(void) _len; /* We don't have to use it */ \
(void) _pen_y; /* Sometimes it won't be used */
# define EVAS_FONT_WALK_PEN_X (EVAS_FONT_ROUND_26_6_TO_INT(_pen_x))
# define EVAS_FONT_WALK_PEN_Y (EVAS_FONT_ROUND_26_6_TO_INT(_pen_y))
#endif /* !_EVAS_FONT_PRIVATE_H */

View File

@ -1,6 +1,7 @@
#include "evas_common.h"
#include "language/evas_bidi_utils.h" /*defines BIDI_SUPPORT if possible */
#include "evas_font_private.h" /* for Frame-Queuing support */
#include "evas_font_ot.h"
EAPI int
evas_common_font_query_kerning(RGBA_Font_Int* fi,
@ -104,132 +105,62 @@ evas_common_font_query_inset(RGBA_Font *fn, const Eina_Unicode *text)
return fg->glyph_out->left;
}
/**
* @def _INIT_FI_AND_KERNINNG()
* @internal
* This macro inits fi and use_kerning.
* Assumes the following variables exist:
* fi, fn and use_kerning.
*/
#define _INIT_FI_AND_KERNING() \
do \
{ \
fi = fn->fonts->data; \
/* evas_common_font_size_use(fn); */ \
evas_common_font_int_reload(fi); \
if (fi->src->current_size != fi->size) \
{ \
FTLOCK(); \
FT_Activate_Size(fi->ft.size); \
FTUNLOCK(); \
fi->src->current_size = fi->size; \
} \
FTLOCK(); \
use_kerning = FT_HAS_KERNING(fi->src->ft.face); \
FTUNLOCK(); \
} \
while (0)
/* size of the string (width and height) in pixels
* BiDi handling: We receive the shaped string + other props from intl_props,
* BiDi handling: We receive the shaped string + other props from text_props,
* We only care about the size, and the size does not depend on the visual order.
* As long as we follow the logical string and get kerning data like we should,
* we are fine.
*/
EAPI void
evas_common_font_query_size(RGBA_Font *fn, const Eina_Unicode *text, const Evas_Text_Props *intl_props __UNUSED__, int *w, int *h)
evas_common_font_query_size(RGBA_Font *fn, const Eina_Unicode *text, const Evas_Text_Props *text_props __UNUSED__, int *w, int *h)
{
int keep_width = 0;
int prev_pen_x = 0;
int use_kerning;
RGBA_Font_Int *fi;
EVAS_FONT_WALK_TEXT_INIT();
_INIT_FI_AND_KERNING();
#ifdef OT_SUPPORT
if (evas_common_font_ot_is_enabled() && intl_props->ot_data)
EVAS_FONT_WALK_TEXT_VISUAL_START()
{
EVAS_FONT_WALK_OT_TEXT_VISUAL_START()
{
EVAS_FONT_WALK_OT_TEXT_WORK(EINA_FALSE);
EVAS_FONT_WALK_TEXT_WORK();
if (!visible) continue;
/* Keep the width because we'll need it for the last char */
keep_width = EVAS_FONT_WALK_OT_WIDTH + EVAS_FONT_WALK_OT_X_OFF +
EVAS_FONT_WALK_OT_X_BEAR;
keep_width = EVAS_FONT_WALK_WIDTH +
EVAS_FONT_WALK_X_OFF +
EVAS_FONT_WALK_X_BEAR;
/* Keep the previous EVAS_FONT_WALK_PEN_X, before it's advanced in TEXT_END */
prev_pen_x = EVAS_FONT_WALK_PEN_X;
}
EVAS_FONT_WALK_OT_TEXT_END();
}
else
#endif
{
EVAS_FONT_WALK_DEFAULT_TEXT_VISUAL_START()
{
EVAS_FONT_WALK_DEFAULT_TEXT_WORK(EINA_FALSE);
if (!visible) continue;
/* Keep the width because we'll need it for the last char */
keep_width = EVAS_FONT_WALK_DEFAULT_WIDTH +
EVAS_FONT_WALK_DEFAULT_X_OFF +
EVAS_FONT_WALK_DEFAULT_X_BEAR;
/* Keep the previous EVAS_FONT_WALK_PEN_X, before it's advanced in TEXT_END */
prev_pen_x = EVAS_FONT_WALK_PEN_X;
}
EVAS_FONT_WALK_DEFAULT_TEXT_END();
}
EVAS_FONT_WALK_TEXT_END();
if (w) *w = prev_pen_x + keep_width;
if (h) *h = evas_common_font_max_ascent_get(fn) + evas_common_font_max_descent_get(fn);
evas_common_font_int_use_trim();
}
/* h & v advance
* BiDi handling: We receive the shaped string + other props from intl_props,
* BiDi handling: We receive the shaped string + other props from text_props,
* We don't care about the order, as heights will remain the same (we already did
* shaping) and as long as we go through the logical string and match the kerning
* this way, we are safe.
*/
EAPI void
evas_common_font_query_advance(RGBA_Font *fn, const Eina_Unicode *text, const Evas_Text_Props *intl_props, int *h_adv, int *v_adv)
evas_common_font_query_advance(RGBA_Font *fn, const Eina_Unicode *text, const Evas_Text_Props *text_props, int *h_adv, int *v_adv)
{
int use_kerning;
RGBA_Font_Int *fi;
EVAS_FONT_WALK_TEXT_INIT();
_INIT_FI_AND_KERNING();
#ifndef BIDI_SUPPORT
/* Suppress warnings */
(void) intl_props;
#endif
#ifdef OT_SUPPORT
if (evas_common_font_ot_is_enabled() && intl_props->ot_data)
EVAS_FONT_WALK_TEXT_LOGICAL_START()
{
EVAS_FONT_WALK_OT_TEXT_VISUAL_START()
{
EVAS_FONT_WALK_OT_TEXT_WORK(EINA_FALSE);
EVAS_FONT_WALK_TEXT_WORK();
if (!visible) continue;
}
EVAS_FONT_WALK_OT_TEXT_END();
}
else
#endif
{
EVAS_FONT_WALK_DEFAULT_TEXT_LOGICAL_START()
{
EVAS_FONT_WALK_DEFAULT_TEXT_WORK(EINA_FALSE);
if (!visible) continue;
}
EVAS_FONT_WALK_DEFAULT_TEXT_END();
}
EVAS_FONT_WALK_TEXT_END();
if (v_adv) *v_adv = evas_common_font_get_line_advance(fn);
if (h_adv) *h_adv = EVAS_FONT_WALK_PEN_X;
evas_common_font_int_use_trim();
}
/* x y w h for char at char pos for null it returns the position right after
* the last char with 0 as width and height.
* BiDi handling: We receive the shaped string + other props from intl_props,
* BiDi handling: We receive the shaped string + other props from text_props,
* We care about the actual drawing location of the string, this is why we need
* the visual string. We need to know how it's printed. After that we need to calculate
* the reverse kerning in case of rtl parts. "pos" passed to this function is an
@ -238,28 +169,24 @@ evas_common_font_query_advance(RGBA_Font *fn, const Eina_Unicode *text, const Ev
*/
EAPI int
evas_common_font_query_char_coords(RGBA_Font *fn, const Eina_Unicode *in_text, const Evas_Text_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch)
evas_common_font_query_char_coords(RGBA_Font *fn, const Eina_Unicode *in_text, const Evas_Text_Props *text_props, int pos, int *cx, int *cy, int *cw, int *ch)
{
int asc, desc;
int position = 0;
const Eina_Unicode *text = in_text;
int ret_val = 0;
int use_kerning;
RGBA_Font_Int *fi;
EVAS_FONT_WALK_TEXT_INIT();
_INIT_FI_AND_KERNING();
asc = evas_common_font_max_ascent_get(fn);
desc = evas_common_font_max_descent_get(fn);
position = pos;
/* If it's the null, choose location according to the direction. */
if (!text[position])
if (text_props->len == position)
{
/* if it's rtl then the location is the left of the string,
* otherwise, the right. */
#ifdef BIDI_SUPPORT
if (intl_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL)
if (text_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL)
{
if (cx) *cx = 0;
if (ch) *ch = asc + desc;
@ -267,7 +194,7 @@ evas_common_font_query_char_coords(RGBA_Font *fn, const Eina_Unicode *in_text, c
else
#endif
{
evas_common_font_query_advance(fn, in_text, intl_props, cx, ch);
evas_common_font_query_advance(fn, in_text, text_props, cx, ch);
}
if (cy) *cy = 0;
if (cw) *cw = 0;
@ -275,18 +202,15 @@ evas_common_font_query_char_coords(RGBA_Font *fn, const Eina_Unicode *in_text, c
goto end;
}
#ifdef OT_SUPPORT
if (evas_common_font_ot_is_enabled() && intl_props->ot_data)
{
Evas_Coord cluster_start, last_end;
int prev_cluster = -1;
int found = 0, items = 0, item_pos = 1;
int found = 0, items = 1, item_pos = 1;
int last_is_visible;
EVAS_FONT_WALK_OT_TEXT_VISUAL_START()
EVAS_FONT_WALK_TEXT_VISUAL_START()
{
EVAS_FONT_WALK_OT_TEXT_WORK(EINA_TRUE);
EVAS_FONT_WALK_TEXT_WORK();
if (prev_cluster != (int) EVAS_FONT_WALK_OT_POS)
if (prev_cluster != (int) EVAS_FONT_WALK_POS)
{
if (found)
{
@ -295,38 +219,48 @@ evas_common_font_query_char_coords(RGBA_Font *fn, const Eina_Unicode *in_text, c
else
{
cluster_start = EVAS_FONT_WALK_PEN_X +
EVAS_FONT_WALK_OT_X_OFF +
EVAS_FONT_WALK_OT_X_BEAR;
EVAS_FONT_WALK_X_OFF +
EVAS_FONT_WALK_X_BEAR;
}
}
last_is_visible = visible;
last_end = EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_OT_X_OFF +
EVAS_FONT_WALK_OT_X_BEAR + EVAS_FONT_WALK_OT_WIDTH;
last_end = EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_X_OFF +
EVAS_FONT_WALK_X_BEAR + EVAS_FONT_WALK_WIDTH;
/* we need to see if the char at the visual position is the char wanted */
if ((intl_props->bidi.dir == EVAS_BIDI_DIRECTION_LTR) &&
(EVAS_FONT_WALK_OT_POS <= (size_t) position) &&
((((size_t) position) < EVAS_FONT_WALK_OT_POS_NEXT) ||
(EVAS_FONT_WALK_OT_IS_LAST)))
if ((text_props->bidi.dir == EVAS_BIDI_DIRECTION_LTR) &&
(EVAS_FONT_WALK_POS <= (size_t) position) &&
((((size_t) position) < EVAS_FONT_WALK_POS_NEXT) ||
(EVAS_FONT_WALK_IS_LAST)))
{
found = 1;
items = evas_common_font_ot_cluster_size_get(intl_props,
char_index, EVAS_FONT_WALK_ORIG_LEN);
item_pos = position - EVAS_FONT_WALK_OT_POS + 1;
#ifdef OT_SUPPORT
if (evas_common_font_ot_is_enabled())
{
items = evas_common_font_ot_cluster_size_get(text_props,
char_index);
}
else if ((intl_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) &&
((EVAS_FONT_WALK_OT_POS_PREV > (size_t) position) ||
(EVAS_FONT_WALK_OT_IS_FIRST)) &&
(((size_t) position) >= EVAS_FONT_WALK_OT_POS))
#endif
item_pos = position - EVAS_FONT_WALK_POS + 1;
}
else if ((text_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) &&
((EVAS_FONT_WALK_POS_PREV > (size_t) position) ||
(EVAS_FONT_WALK_IS_FIRST)) &&
(((size_t) position) >= EVAS_FONT_WALK_POS))
{
found = 1;
items = evas_common_font_ot_cluster_size_get(intl_props,
char_index, EVAS_FONT_WALK_ORIG_LEN);
item_pos = items - (position - EVAS_FONT_WALK_OT_POS);
#ifdef OT_SUPPORT
if (evas_common_font_ot_is_enabled())
{
items = evas_common_font_ot_cluster_size_get(text_props,
char_index);
}
#endif
item_pos = items - (position - EVAS_FONT_WALK_POS);
}
prev_cluster = EVAS_FONT_WALK_OT_POS;
prev_cluster = EVAS_FONT_WALK_POS;
}
EVAS_FONT_WALK_OT_TEXT_END();
EVAS_FONT_WALK_TEXT_END();
if (found)
{
Evas_Coord cluster_w;
@ -348,49 +282,15 @@ evas_common_font_query_char_coords(RGBA_Font *fn, const Eina_Unicode *in_text, c
ret_val = 1;
goto end;
}
}
else
#endif
{
EVAS_FONT_WALK_DEFAULT_TEXT_VISUAL_START()
{
int chr_x, chr_w;
EVAS_FONT_WALK_DEFAULT_TEXT_WORK(EINA_TRUE);
if (visible)
{
chr_x = (EVAS_FONT_WALK_PEN_X) + EVAS_FONT_WALK_DEFAULT_X_OFF +
EVAS_FONT_WALK_DEFAULT_X_BEAR;
chr_w = EVAS_FONT_WALK_DEFAULT_WIDTH;
}
else
{
chr_x = EVAS_FONT_WALK_PEN_X;
chr_w = 0;
}
/* we need to see if the char at the visual position is the char wanted */
if (EVAS_FONT_WALK_DEFAULT_POS == (size_t) position)
{
if (cx) *cx = chr_x;
if (cy) *cy = -asc;
if (cw) *cw = chr_w;
if (ch) *ch = asc + desc;
ret_val = 1;
goto end;
}
}
EVAS_FONT_WALK_DEFAULT_TEXT_END();
}
end:
evas_common_font_int_use_trim();
return ret_val;
}
/* x y w h for pen at char pos for null it returns the position right after
* the last char with 0 as width and height. This is the same as char_coords
* but it returns the pen_x and adv instead of x and w.
* BiDi handling: We receive the shaped string + other props from intl_props,
* BiDi handling: We receive the shaped string + other props from text_props,
* We care about the actual drawing location of the string, this is why we need
* the visual string. We need to know how it's printed. After that we need to calculate
* the reverse kerning in case of rtl parts. "pos" passed to this function is an
@ -399,28 +299,24 @@ end:
*/
EAPI int
evas_common_font_query_pen_coords(RGBA_Font *fn, const Eina_Unicode *in_text, const Evas_Text_Props *intl_props, int pos, int *cpen_x, int *cy, int *cadv, int *ch)
evas_common_font_query_pen_coords(RGBA_Font *fn, const Eina_Unicode *in_text, const Evas_Text_Props *text_props, int pos, int *cpen_x, int *cy, int *cadv, int *ch)
{
int asc, desc;
int position = 0;
const Eina_Unicode *text = in_text;
int ret_val = 0;
int use_kerning;
RGBA_Font_Int *fi;
EVAS_FONT_WALK_TEXT_INIT();
_INIT_FI_AND_KERNING();
asc = evas_common_font_max_ascent_get(fn);
desc = evas_common_font_max_descent_get(fn);
position = pos;
/* If it's the null, choose location according to the direction. */
if (!text[position])
if (text_props->len == position)
{
/* if it's rtl then the location is the left of the string,
* otherwise, the right. */
#ifdef BIDI_SUPPORT
if (intl_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL)
if (text_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL)
{
if (cpen_x) *cpen_x = 0;
if (ch) *ch = asc + desc;
@ -428,25 +324,22 @@ evas_common_font_query_pen_coords(RGBA_Font *fn, const Eina_Unicode *in_text, co
else
#endif
{
evas_common_font_query_advance(fn, in_text, intl_props, cpen_x, ch);
evas_common_font_query_advance(fn, in_text, text_props, cpen_x, ch);
}
if (cy) *cy = 0;
if (cadv) *cadv = 0;
ret_val = 1;
goto end;
}
#ifdef OT_SUPPORT
if (evas_common_font_ot_is_enabled() && intl_props->ot_data)
{
Evas_Coord cluster_start;
int prev_cluster = -1;
int found = 0, items = 0, item_pos = 1;
int found = 0, items = 1, item_pos = 1;
int last_is_visible = 1;
EVAS_FONT_WALK_OT_TEXT_VISUAL_START()
EVAS_FONT_WALK_TEXT_VISUAL_START()
{
EVAS_FONT_WALK_OT_TEXT_WORK(EINA_TRUE);
EVAS_FONT_WALK_TEXT_WORK();
if (prev_cluster != (int) EVAS_FONT_WALK_OT_POS)
if (prev_cluster != (int) EVAS_FONT_WALK_POS)
{
if (found)
{
@ -459,30 +352,40 @@ evas_common_font_query_pen_coords(RGBA_Font *fn, const Eina_Unicode *in_text, co
}
last_is_visible = visible;
if ((intl_props->bidi.dir == EVAS_BIDI_DIRECTION_LTR) &&
(EVAS_FONT_WALK_OT_POS <= (size_t) position) &&
((((size_t) position) < EVAS_FONT_WALK_OT_POS_NEXT) ||
(EVAS_FONT_WALK_OT_IS_LAST)))
if ((text_props->bidi.dir == EVAS_BIDI_DIRECTION_LTR) &&
(EVAS_FONT_WALK_POS <= (size_t) position) &&
((((size_t) position) < EVAS_FONT_WALK_POS_NEXT) ||
(EVAS_FONT_WALK_IS_LAST)))
{
found = 1;
items = evas_common_font_ot_cluster_size_get(intl_props,
char_index, EVAS_FONT_WALK_ORIG_LEN);
item_pos = position - EVAS_FONT_WALK_OT_POS + 1;
#ifdef OT_SUPPORT
if (evas_common_font_ot_is_enabled())
{
items = evas_common_font_ot_cluster_size_get(text_props,
char_index);
}
else if ((intl_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) &&
((EVAS_FONT_WALK_OT_POS_PREV > (size_t) position) ||
(EVAS_FONT_WALK_OT_IS_FIRST)) &&
(((size_t) position) >= EVAS_FONT_WALK_OT_POS))
#endif
item_pos = position - EVAS_FONT_WALK_POS + 1;
}
else if ((text_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) &&
((EVAS_FONT_WALK_POS_PREV > (size_t) position) ||
(EVAS_FONT_WALK_IS_FIRST)) &&
(((size_t) position) >= EVAS_FONT_WALK_POS))
{
found = 1;
items = evas_common_font_ot_cluster_size_get(intl_props,
char_index, EVAS_FONT_WALK_ORIG_LEN);
item_pos = items - (position - EVAS_FONT_WALK_OT_POS);
#ifdef OT_SUPPORT
if (evas_common_font_ot_is_enabled())
{
items = evas_common_font_ot_cluster_size_get(text_props,
char_index);
}
#endif
item_pos = items - (position - EVAS_FONT_WALK_POS);
}
prev_cluster = EVAS_FONT_WALK_OT_POS;
prev_cluster = EVAS_FONT_WALK_POS;
}
EVAS_FONT_WALK_OT_TEXT_END();
EVAS_FONT_WALK_TEXT_END();
if (found)
{
@ -505,46 +408,6 @@ evas_common_font_query_pen_coords(RGBA_Font *fn, const Eina_Unicode *in_text, co
ret_val = 1;
goto end;
}
}
else
#endif
{
EVAS_FONT_WALK_DEFAULT_TEXT_VISUAL_START()
{
EVAS_FONT_WALK_DEFAULT_TEXT_WORK(EINA_TRUE);
if ((EVAS_FONT_WALK_DEFAULT_POS == (size_t) position))
{
if (cy) *cy = -asc;
if (ch) *ch = asc + desc;
/* FIXME: A hack to make combining chars work nice, should change
* to take the base char's adv. */
if (visible)
{
if (EVAS_FONT_WALK_DEFAULT_X_ADV > 0)
{
if (cpen_x) *cpen_x = EVAS_FONT_WALK_PEN_X;
if (cadv) *cadv = EVAS_FONT_WALK_DEFAULT_X_ADV;
}
else
{
if (cpen_x) *cpen_x = EVAS_FONT_WALK_PEN_X +
EVAS_FONT_WALK_DEFAULT_X_OFF +
EVAS_FONT_WALK_DEFAULT_X_BEAR;
if (cadv) *cadv = EVAS_FONT_WALK_DEFAULT_WIDTH;
}
}
else
{
if (cpen_x) *cpen_x = EVAS_FONT_WALK_PEN_X;
if (cadv) *cadv = 0;
}
ret_val = 1;
goto end;
}
}
EVAS_FONT_WALK_DEFAULT_TEXT_END();
}
end:
return ret_val;
@ -558,32 +421,21 @@ end:
*/
EAPI int
evas_common_font_query_char_at_coords(RGBA_Font *fn, const Eina_Unicode *in_text, const Evas_Text_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch)
evas_common_font_query_char_at_coords(RGBA_Font *fn, const Eina_Unicode *in_text, const Evas_Text_Props *text_props, int x, int y, int *cx, int *cy, int *cw, int *ch)
{
int asc, desc;
const Eina_Unicode *text = in_text;
int ret_val = -1;
int use_kerning;
RGBA_Font_Int *fi;
EVAS_FONT_WALK_TEXT_INIT();
_INIT_FI_AND_KERNING();
#ifndef BIDI_SUPPORT
/* Suppress warnings */
(void) intl_props;
#endif
asc = evas_common_font_max_ascent_get(fn);
desc = evas_common_font_max_descent_get(fn);
#ifdef OT_SUPPORT
if (evas_common_font_ot_is_enabled() && intl_props->ot_data)
{
Evas_Coord cluster_start;
int prev_cluster = -1;
int found = 0, items = 0;
EVAS_FONT_WALK_OT_TEXT_VISUAL_START()
int found = 0, items = 1;
EVAS_FONT_WALK_TEXT_VISUAL_START()
{
EVAS_FONT_WALK_OT_TEXT_WORK(EINA_TRUE);
if (prev_cluster != (int) EVAS_FONT_WALK_OT_POS)
EVAS_FONT_WALK_TEXT_WORK();
if (prev_cluster != (int) EVAS_FONT_WALK_POS)
{
if (found)
{
@ -600,24 +452,29 @@ evas_common_font_query_char_at_coords(RGBA_Font *fn, const Eina_Unicode *in_text
/* we need to see if the char at the visual position is the char,
* we check that by checking if it's before the current pen
* position and the next */
if ((x >= EVAS_FONT_WALK_PEN_X) && (x <= (EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_OT_X_ADV)) &&
if ((x >= EVAS_FONT_WALK_PEN_X) && (x <= (EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_X_ADV)) &&
(y >= -asc) && (y <= desc))
{
items = evas_common_font_ot_cluster_size_get(intl_props,
char_index, EVAS_FONT_WALK_ORIG_LEN);
#ifdef OT_SUPPORT
if (evas_common_font_ot_is_enabled())
{
items = evas_common_font_ot_cluster_size_get(text_props,
char_index);
}
#endif
found = 1;
}
prev_cluster = EVAS_FONT_WALK_OT_POS;
prev_cluster = EVAS_FONT_WALK_POS;
}
EVAS_FONT_WALK_OT_TEXT_END();
EVAS_FONT_WALK_TEXT_END();
if (found)
{
int item_pos;
Evas_Coord cluster_adv;
cluster_adv = EVAS_FONT_WALK_PEN_X - cluster_start;
if (intl_props->bidi.dir == EVAS_BIDI_DIRECTION_LTR)
if (text_props->bidi.dir == EVAS_BIDI_DIRECTION_LTR)
{
double part;
part = cluster_adv / items;
@ -637,100 +494,44 @@ evas_common_font_query_char_at_coords(RGBA_Font *fn, const Eina_Unicode *in_text
ret_val = prev_cluster + item_pos;
goto end;
}
}
else
#endif
{
EVAS_FONT_WALK_DEFAULT_TEXT_VISUAL_START()
{
EVAS_FONT_WALK_DEFAULT_TEXT_WORK(EINA_TRUE);
if (!visible) continue;
/* we need to see if the char at the visual position is the char,
* we check that by checking if it's before the current pen position
* and the next */
if ((x >= EVAS_FONT_WALK_PEN_X) && (x <= (EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_DEFAULT_X_ADV))
&& (y >= -asc) && (y <= desc))
{
if (cx) *cx = EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_DEFAULT_X_OFF +
EVAS_FONT_WALK_DEFAULT_X_BEAR +
EVAS_FONT_WALK_DEFAULT_X_ADV;
if (cy) *cy = -asc;
if (cw) *cw = EVAS_FONT_WALK_DEFAULT_X_ADV;
if (ch) *ch = asc + desc;
ret_val = EVAS_FONT_WALK_DEFAULT_POS;
goto end;
}
}
EVAS_FONT_WALK_DEFAULT_TEXT_END();
}
end:
evas_common_font_int_use_trim();
return ret_val;
}
/* position of the char after the last char in the text that will fit in xy.
* BiDi handling: We receive the shaped string + other props from intl_props,
* BiDi handling: We receive the shaped string + other props from text_props,
* All we care about is char sizes + kerning so we only really need to get the
* shaped string to utf8, and then just go through it like in english, as it's
* just the logical string, nothing special about that.
*/
EAPI int
evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const Eina_Unicode *in_text, const Evas_Text_Props *intl_props __UNUSED__, int x, int y)
evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const Eina_Unicode *in_text, const Evas_Text_Props *text_props __UNUSED__, int x, int y)
{
int asc, desc;
int ret=-1;
const Eina_Unicode *text = in_text;
int use_kerning;
RGBA_Font_Int *fi;
EVAS_FONT_WALK_TEXT_INIT();
_INIT_FI_AND_KERNING();
asc = evas_common_font_max_ascent_get(fn);
desc = evas_common_font_max_descent_get(fn);
#ifdef OT_SUPPORT
if (evas_common_font_ot_is_enabled() && intl_props->ot_data)
EVAS_FONT_WALK_TEXT_LOGICAL_START()
{
EVAS_FONT_WALK_OT_TEXT_LOGICAL_START()
{
EVAS_FONT_WALK_OT_TEXT_WORK(EINA_FALSE);
EVAS_FONT_WALK_TEXT_WORK();
if (!visible) continue;
if ((x >= EVAS_FONT_WALK_PEN_X) && (x <= (EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_OT_X_ADV)) &&
if ((x >= EVAS_FONT_WALK_PEN_X) && (x <= (EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_X_ADV)) &&
(y >= -asc) && (y <= desc))
{
ret = EVAS_FONT_WALK_OT_POS;
ret = EVAS_FONT_WALK_POS;
goto end;
}
}
EVAS_FONT_WALK_OT_TEXT_END();
}
else
#endif
{
EVAS_FONT_WALK_DEFAULT_TEXT_LOGICAL_START()
{
EVAS_FONT_WALK_DEFAULT_TEXT_WORK(EINA_FALSE);
if (!visible) continue;
if ((x >= EVAS_FONT_WALK_PEN_X) &&
(x <= (EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_DEFAULT_X_ADV)) &&
(y >= -asc) && (y <= desc))
{
ret = char_index;
goto end;
}
}
EVAS_FONT_WALK_DEFAULT_TEXT_END();
}
EVAS_FONT_WALK_TEXT_END();
end:
evas_common_font_int_use_trim();
return ret;
}

View File

@ -1,3 +1,4 @@
#include "evas_common.h"
#include "evas_text_utils.h"
#include "language/evas_bidi_utils.h"
#include "language/evas_language_utils.h"
@ -37,39 +38,34 @@ evas_common_text_props_content_copy_and_ref(Evas_Text_Props *dst,
void
evas_common_text_props_content_ref(Evas_Text_Props *props)
{
#ifdef OT_SUPPORT
if (props->ot_data)
{
evas_common_font_ot_props_ref(props->ot_data);
}
#endif
props->info->refcount++;
}
void
evas_common_text_props_content_unref(Evas_Text_Props *props)
{
#ifdef OT_SUPPORT
if (props->ot_data)
{
evas_common_font_ot_props_unref(props->ot_data);
}
#else
(void) props;
#endif
#ifdef BIDI_SUPPORT
evas_bidi_props_clean(&props->bidi);
#else
(void) props;
#endif
}
/* We allow this, because sometimes we want to have props without info,
* and we don't want to diverge the code paths too much. */
if (!props->info)
return;
/* Won't work in the middle of ligatures */
EAPI void
evas_common_text_props_cutoff(Evas_Text_Props *props, int cutoff)
{
if (props->info->refcount == 0)
{
ERR("Trying to unref props with refount == 0");
return;
}
if (--(props->info->refcount) == 0)
{
if (props->info->glyph)
free(props->info->glyph);
#ifdef OT_SUPPORT
evas_common_font_ot_cutoff_text_props(props, cutoff);
if (props->info->ot)
free(props->info->ot);
#endif
free(props->info);
props->info = NULL;
}
}
/* Won't work in the middle of ligatures */
@ -77,12 +73,20 @@ EAPI void
evas_common_text_props_split(Evas_Text_Props *base,
Evas_Text_Props *ext, int cutoff)
{
/* FIXME: move to their own functions */
memcpy(&ext->bidi, &base->bidi, sizeof(Evas_BiDi_Props));
memcpy(&ext->script, &base->script, sizeof(Evas_Script_Type));
#ifdef OT_SUPPORT
evas_common_font_ot_split_text_props(base, ext, cutoff);
#endif
evas_common_text_props_content_copy_and_ref(ext, base);
if (base->bidi.dir == EVAS_BIDI_DIRECTION_RTL)
{
ext->start = base->start;
base->start = cutoff;
ext->len = cutoff;
base->len = base->len - cutoff;
}
else
{
ext->start = cutoff;
ext->len = base->len - cutoff;
base->len = cutoff;
}
}
/* Won't work in the middle of ligatures */
@ -90,9 +94,16 @@ EAPI void
evas_common_text_props_merge(Evas_Text_Props *item1,
const Evas_Text_Props *item2)
{
#ifdef OT_SUPPORT
evas_common_font_ot_merge_text_props(item1, item2);
#endif
if (item1->info != item2->info)
{
ERR("tried merge back items that weren't together in the first place.");
return;
}
if (item1->bidi.dir == EVAS_BIDI_DIRECTION_RTL)
{
item1->start = item2->start;
}
item1->len += item2->len;
}

View File

@ -2,16 +2,29 @@
# define _EVAS_TEXT_UTILS_H
typedef struct _Evas_Text_Props Evas_Text_Props;
typedef struct _Evas_Text_Props_Info Evas_Text_Props_Info;
# include "evas_font_ot.h"
# include "language/evas_bidi_utils.h"
# include "language/evas_language_utils.h"
# include "evas_font_glyph_info.h"
struct _Evas_Text_Props
{
/* Start and len represent the start offset and the length in the
* glyphs_info and ot_data fields, they are both internal */
size_t start;
size_t len;
Evas_BiDi_Props bidi;
Evas_Script_Type script;
Evas_Font_OT_Data *ot_data;
Evas_Text_Props_Info *info;
};
struct _Evas_Text_Props_Info
{
unsigned int refcount;
Evas_Font_Glyph_Info *glyph;
Evas_Font_OT_Info *ot;
};
void
@ -32,9 +45,6 @@ evas_common_text_props_content_ref(Evas_Text_Props *props);
void
evas_common_text_props_content_unref(Evas_Text_Props *props);
EAPI void
evas_common_text_props_cutoff(Evas_Text_Props *props, int cutoff);
EAPI void
evas_common_text_props_split(Evas_Text_Props *base, Evas_Text_Props *ext,
int cutoff);

View File

@ -1109,9 +1109,9 @@ static Eina_Bool
eng_font_shape(void *data __UNUSED__, void *font, Eina_Unicode *text, Evas_Text_Props *intl_props __UNUSED__, const Evas_BiDi_Paragraph_Props *par_props, size_t pos, size_t len)
{
#ifdef BIDI_SUPPORT
return !evas_bidi_shape_string(text, par_props, pos, len);
evas_bidi_shape_string(text, par_props, pos, len);
#endif
return EINA_TRUE;
return evas_common_font_glyph_info_create(font, text, intl_props, len);
}
static int

View File

@ -543,17 +543,23 @@ eng_font_pen_coords_get(void *data __UNUSED__, void *font, const Eina_Unicode *t
static Eina_Bool
eng_font_shape(void *data __UNUSED__, void *font, Eina_Unicode *text, Evas_Text_Props *intl_props, const Evas_BiDi_Paragraph_Props *par_props, size_t pos, size_t len)
{
(void) font;
(void) text;
(void) intl_props;
(void) par_props;
(void) pos;
(void) len;
#ifdef OT_SUPPORT
if (evas_common_font_ot_is_enabled())
{
return evas_common_font_ot_populate_text_props(font, text,
intl_props, len);
return evas_common_font_glyph_info_create(font, text, intl_props, len);
}
else
#endif
{
#ifdef BIDI_SUPPORT
return !evas_bidi_shape_string(text, par_props, pos, len);
evas_bidi_shape_string(text, par_props, pos, len);
return evas_common_font_glyph_info_create(font, text, intl_props, len);
#endif
}
return EINA_TRUE;

View File

@ -601,17 +601,23 @@ eng_font_pen_coords_get(void *data __UNUSED__, void *font, const Eina_Unicode *t
static Eina_Bool
eng_font_shape(void *data __UNUSED__, void *font, Eina_Unicode *text, Evas_Text_Props *intl_props, const Evas_BiDi_Paragraph_Props *par_props, size_t pos, size_t len)
{
(void) font;
(void) text;
(void) intl_props;
(void) par_props;
(void) pos;
(void) len;
#ifdef OT_SUPPORT
if (evas_common_font_ot_is_enabled())
{
return evas_common_font_ot_populate_text_props(font, text,
intl_props, len);
return evas_common_font_glyph_info_create(font, text, intl_props, len);
}
else
#endif
{
#ifdef BIDI_SUPPORT
return !evas_bidi_shape_string(text, par_props, pos, len);
evas_bidi_shape_string(text, par_props, pos, len);
return evas_common_font_glyph_info_create(font, text, intl_props, len);
#endif
}
return EINA_TRUE;

View File

@ -722,8 +722,7 @@ eng_font_shape(void *data __UNUSED__, void *font, Eina_Unicode *text, Evas_Text_
#ifdef OT_SUPPORT
if (evas_common_font_ot_is_enabled())
{
return evas_common_font_ot_populate_text_props(font, text,
intl_props, len);
return evas_common_font_glyph_info_create(font, text, intl_props, len);
}
else
#endif