From 34d5f9141dc23d0ea51cc20c276994056b4ab386 Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Sun, 30 Jan 2011 10:33:24 +0000 Subject: [PATCH] Evas font engine: Merge text walking to a couple of macros, this is more consistent, and the code is smaller and easier to handle. SVN revision: 56426 --- .../src/lib/engines/common/evas_font_draw.c | 67 +-- .../lib/engines/common/evas_font_private.h | 153 ++++- .../src/lib/engines/common/evas_font_query.c | 549 ++++-------------- 3 files changed, 270 insertions(+), 499 deletions(-) diff --git a/legacy/evas/src/lib/engines/common/evas_font_draw.c b/legacy/evas/src/lib/engines/common/evas_font_draw.c index 75214db46b..2b578fb96e 100644 --- a/legacy/evas/src/lib/engines/common/evas_font_draw.c +++ b/legacy/evas/src/lib/engines/common/evas_font_draw.c @@ -405,14 +405,10 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font int ext_h, RGBA_Font_Int *fi, int im_w, int im_h __UNUSED__, int use_kerning ) { - int pen_x, pen_y; - int last_adv; const Eina_Unicode *text = in_text; - FT_Face pface = NULL; - FT_UInt prev_index; DATA32 *im; int c; - int char_index = 0; /* the index of the current char */ + EVAS_FONT_WALK_TEXT_INIT(); #if defined(METRIC_CACHE) || defined(WORD_CACHE) unsigned int len; @@ -522,49 +518,26 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font #else intl_props = NULL; #endif + if (fi->src->current_size != fi->size) + { + FTLOCK(); + FT_Activate_Size(fi->ft.size); + FTUNLOCK(); + fi->src->current_size = fi->size; + } pen_x = x; pen_y = y; - last_adv = 0; - prev_index = 0; im = dst->image.data; - for (char_index = 0, c = 0; *text; text++, char_index++) + c = 0; + EVAS_FONT_WALK_TEXT_START() { - FT_UInt index; - RGBA_Font_Glyph *fg; - int chr_x, chr_y; - int gl, kern; + int chr_x, chr_y, chr_w; - gl = *text; if (EVAS_FONT_CHARACTER_IS_INVISIBLE(gl)) continue; - index = evas_common_font_glyph_search(fn, &fi, gl); - LKL(fi->ft_mutex); - if (fi->src->current_size != fi->size) - { - FTLOCK(); - FT_Activate_Size(fi->ft.size); - FTUNLOCK(); - fi->src->current_size = fi->size; - } - fg = evas_common_font_int_cache_glyph_get(fi, index); - if (!fg) - { - LKU(fi->ft_mutex); - continue; - } - /* 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)) - { - if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) - pen_x += kern; - } - pface = fi->src->ft.face; - LKU(fi->ft_mutex); + EVAS_FONT_WALK_TEXT_WORK(); if (dc->font_ext.func.gl_new) { @@ -572,15 +545,10 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font fg->ext_dat = dc->font_ext.func.gl_new(dc->font_ext.data, fg); fg->ext_dat_free = dc->font_ext.func.gl_free; } - /* If the current one is not a compositing char, do the previous advance - * and set the current advance as the next advance to do */ - if (fg->glyph->advance.x >> 16 > 0) - { - pen_x += last_adv; - last_adv = fg->glyph->advance.x >> 16; - } - chr_x = (pen_x + (fg->glyph_out->left)); - chr_y = (pen_y + (fg->glyph_out->top)); + + chr_x = (pen_x) + bear_x; + chr_y = (pen_y) + bear_y; + chr_w = width; if (chr_x < (ext_x + ext_w)) { @@ -709,9 +677,8 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font } else break; - - prev_index = index; } + EVAS_FONT_WALK_TEXT_END(); #ifdef BIDI_SUPPORT if (visual_text) free(visual_text); #endif diff --git a/legacy/evas/src/lib/engines/common/evas_font_private.h b/legacy/evas/src/lib/engines/common/evas_font_private.h index 57940ee49d..28d566f282 100644 --- a/legacy/evas/src/lib/engines/common/evas_font_private.h +++ b/legacy/evas/src/lib/engines/common/evas_font_private.h @@ -13,11 +13,11 @@ extern LK(lock_bidi); // for fribidi API calls # define BIDILOCK() LKL(lock_bidi) # define BIDIUNLOCK() LKU(lock_bidi) # else -# define FTLOCK(x) -# define FTUNLOCK(x) +# define FTLOCK(x) +# define FTUNLOCK(x) -# define BIDILOCK() -# define BIDIUNLOCK() +# define BIDILOCK() +# define BIDIUNLOCK() # endif void evas_common_font_source_unload(RGBA_Font_Source *fs); @@ -28,5 +28,150 @@ void evas_common_font_int_use_increase(int size); void evas_common_font_int_use_trim(void); void evas_common_font_int_unload(RGBA_Font_Int *fi); void evas_common_font_int_reload(RGBA_Font_Int *fi); +/* Macros for text walking */ +/** + * @def EVAS_FONT_UPDATE_KERN() + * @internal + * This macro updates pen_x and kern according to kerning. + * This macro assumes the following variables exist: + * intl_props, char_index, adv, fi, kern, pen_x + */ +#ifdef BIDI_SUPPORT +#define EVAS_FONT_UPDATE_KERN() \ + 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 && \ + evas_bidi_is_rtl_char(intl_props, char_index) && \ + adv > 0) \ + { \ + 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() \ + do \ + { \ + if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) \ + pen_x += kern; \ + } \ + while (0) +#endif + +/** + * @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; \ + int char_index; \ + int last_adv; \ + FT_UInt prev_index; \ + FT_Face pface = NULL; \ + (void) pen_y; /* Sometimes it won't be used */ + +/** + * @def EVAS_FONT_WALK_TEXT_START + * @internal + * This runs through the variable text while updating char_index, + * which is the current index in the text. This macro exposes (inside + * the loop) the following vars: + * adv - advancement + * gl - the current unicode code point + * bear_x, bear_y, width - info about the bitmap + * pen_x, pen_y - (also available outside of the loop, but updated here) + * fg - the font glyph. + * index, prev_index - font indexes. + * Does not end with a ; + * @see EVAS_FONT_WALK_TEXT_INIT + * @see EVAS_FONT_WALK_TEXT_WORK + * @see EVAS_FONT_WALK_TEXT_END + */ +#define EVAS_FONT_WALK_TEXT_START() \ + do \ + { \ + int adv; \ + prev_index = 0; \ + last_adv = 0; \ + for (char_index = 0 ; *text ; text++, char_index++) \ + { \ + FT_UInt index; \ + RGBA_Font_Glyph *fg; \ + int gl, kern; \ + int bear_x, bear_y, width; \ + gl = *text; \ + if (gl == 0) break; + +/** + * @def EVAS_FONT_WALK_TEXT_WORK + * @internal + * This macro actually updates the values mentioned in EVAS_FONT_WALK_TEXT_START + * according to the current positing in the walk. + * @see EVAS_FONT_WALK_TEXT_START + * @see EVAS_FONT_WALK_TEXT_INIT + * @see EVAS_FONT_WALK_TEXT_END + */ +#define EVAS_FONT_WALK_TEXT_WORK() \ + 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; \ + bear_x = fg->glyph_out->left; \ + bear_y = fg->glyph_out->top; \ + adv = fg->glyph->advance.x >> 16; \ + width = fg->glyph_out->bitmap.width; \ + /* 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(); \ + } \ + \ + pface = fi->src->ft.face; \ + LKU(fi->ft_mutex); \ + /* If the current one is not a compositing char, do the */ \ + /* previous advance and set the current advance as the next */ \ + /* advance to do */ \ + if (adv > 0) \ + { \ + pen_x += last_adv; \ + last_adv = adv; \ + } \ + +/** + * @def EVAS_FONT_WALK_TEXT_END + * @internal + * Closes EVAS_FONT_WALK_TEXT_START, needs to end with a ; + * @see EVAS_FONT_WALK_TEXT_START + * @see EVAS_FONT_WALK_TEXT_INIT + * @see EVAS_FONT_WALK_TEXT_WORK + */ +#define EVAS_FONT_WALK_TEXT_END() \ + prev_index = index; \ + } \ + } \ + while(0) #endif /* !_EVAS_FONT_PRIVATE_H */ diff --git a/legacy/evas/src/lib/engines/common/evas_font_query.c b/legacy/evas/src/lib/engines/common/evas_font_query.c index e6bc70b810..84fbd8cdc4 100644 --- a/legacy/evas/src/lib/engines/common/evas_font_query.c +++ b/legacy/evas/src/lib/engines/common/evas_font_query.c @@ -57,120 +57,6 @@ evas_common_font_query_kerning(RGBA_Font_Int* fi, return error; } -/* size of the string (width and height) in pixels - * BiDi handling: We receive the shaped string + other props from intl_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_BiDi_Props *intl_props __UNUSED__, int *w, int *h) -{ - int use_kerning; - int pen_x, pen_y; - int start_x, end_x; - int chr; - int char_index; - FT_UInt prev_index; - RGBA_Font_Int *fi; - FT_Face pface = NULL; - - fi = fn->fonts->data; - - start_x = 0; - end_x = 0; - - pen_x = 0; - pen_y = 0; -// evas_common_font_size_use(fn); - evas_common_font_int_reload(fi); - use_kerning = FT_HAS_KERNING(fi->src->ft.face); - prev_index = 0; - for (chr = 0, char_index = 0; *text; text++, char_index ++) - { - FT_UInt index; - RGBA_Font_Glyph *fg = NULL; - int chr_x, chr_y, advw; - int gl, kern; - - gl = *text; - index = evas_common_font_glyph_search(fn, &fi, gl); - LKL(fi->ft_mutex); - if (fi->src->current_size != fi->size) - { - FTLOCK(); - FT_Activate_Size(fi->ft.size); - FTUNLOCK(); - fi->src->current_size = fi->size; - } - kern = 0; - /* 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) && (fg) && - (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 (intl_props && - evas_bidi_is_rtl_char(intl_props, char_index) && - ((fg->glyph->advance.x >> 16) > 0)) - { - 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; - } -#else - if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) - pen_x += kern; -#endif - } - - pface = fi->src->ft.face; - fg = evas_common_font_int_cache_glyph_get(fi, index); - LKU(fi->ft_mutex); - if (!fg || !fg->glyph) continue; - - if (kern < 0) kern = 0; - - /* We care about advancing the whole string size, and not the actual - * paint size of each string, so we only care about advancing correctly - * and not the actual glyph width */ - advw = ((fg->glyph->advance.x + (kern << 16)) >> 16); - chr_x = pen_x - kern; - chr_y = pen_y; - /* If it's not a compositing char, i.e it advances, we should also add - * the left/top padding of the glyph. As we don't care about the padding - * as the drawing location remains the same. - */ - if (advw > 0) - { - chr_x += fg->glyph_out->left; - chr_y += fg->glyph_out->top; - } - - - if ((!prev_index) && (chr_x < 0)) - start_x = chr_x; - if ((chr_x + advw) > end_x) - end_x = chr_x + advw; - - pen_x += fg->glyph->advance.x >> 16; - prev_index = index; - } - if (w) *w = end_x - start_x; - if (h) *h = evas_common_font_max_ascent_get(fn) + evas_common_font_max_descent_get(fn); - evas_common_font_int_use_trim(); -} - /* text x inset */ EAPI int evas_common_font_query_inset(RGBA_Font *fn, const Eina_Unicode *text) @@ -214,7 +100,62 @@ evas_common_font_query_inset(RGBA_Font *fn, const Eina_Unicode *text) ); */ evas_common_font_int_use_trim(); - return fg->glyph_out->left; + 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, + * 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_BiDi_Props *intl_props __UNUSED__, int *w, int *h) +{ + int keep_width; + int use_kerning; + RGBA_Font_Int *fi; + EVAS_FONT_WALK_TEXT_INIT(); + _INIT_FI_AND_KERNING(); + + EVAS_FONT_WALK_TEXT_START() + { + EVAS_FONT_WALK_TEXT_WORK(); + /* Keep the width because we'll need it for the last char */ + keep_width = width; + } + EVAS_FONT_WALK_TEXT_END(); + if (w) *w = 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 @@ -223,94 +164,26 @@ evas_common_font_query_inset(RGBA_Font *fn, const Eina_Unicode *text) * 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_BiDi_Props *intl_props, int *h_adv, int *v_adv) { + int keep_adv; int use_kerning; - int pen_x, pen_y; - int start_x; - int char_index; - FT_UInt prev_index; RGBA_Font_Int *fi; - FT_Face pface = NULL; + EVAS_FONT_WALK_TEXT_INIT(); + _INIT_FI_AND_KERNING(); - fi = fn->fonts->data; - - start_x = 0; - pen_x = 0; - pen_y = 0; -// evas_common_font_size_use(fn); - evas_common_font_int_reload(fi); - FTLOCK(); - use_kerning = FT_HAS_KERNING(fi->src->ft.face); - FTUNLOCK(); - prev_index = 0; - for (char_index = 0 ; *text ; text++, char_index++) + EVAS_FONT_WALK_TEXT_START() { - 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); - if (fi->src->current_size != fi->size) - { - FTLOCK(); - FT_Activate_Size(fi->ft.size); - FTUNLOCK(); - fi->src->current_size = fi->size; - } - fg = evas_common_font_int_cache_glyph_get(fi, index); - if (!fg) - { - LKU(fi->ft_mutex); - continue; - } - // FIXME: Why no FT_Activate_Size here ? - kern = 0; - /* 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) && (fg) && - (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 (intl_props && - evas_bidi_is_rtl_char(intl_props, char_index) && - fg->glyph->advance.x >> 16 > 0) - { - 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; - } -#else - if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) - pen_x += kern; -#endif - } - - pface = fi->src->ft.face; - LKU(fi->ft_mutex); - - pen_x += fg->glyph->advance.x >> 16; - prev_index = index; + EVAS_FONT_WALK_TEXT_WORK(); + /* Keep the advancement because we want to also do the last + * advancement */ + keep_adv = adv; } + EVAS_FONT_WALK_TEXT_END(); + if (v_adv) *v_adv = evas_common_font_get_line_advance(fn); - if (h_adv) *h_adv = pen_x - start_x; -#ifndef BIDI_SUPPORT - intl_props = NULL; -#endif + if (h_adv) *h_adv = pen_x + keep_adv; evas_common_font_int_use_trim(); } @@ -327,18 +200,14 @@ 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_BiDi_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch) { - int use_kerning; - int pen_x, pen_y; - int prev_chr_end; int asc, desc; - int char_index = 0; /* the index of the current char */ int position = 0; const Eina_Unicode *text = in_text; int ret_val = 0; - int last_adv; - FT_UInt prev_index; + int use_kerning; RGBA_Font_Int *fi; - FT_Face pface = NULL; + EVAS_FONT_WALK_TEXT_INIT(); + _INIT_FI_AND_KERNING(); #ifdef BIDI_SUPPORT int len = 0; @@ -360,22 +229,6 @@ evas_common_font_query_char_coords(RGBA_Font *fn, const Eina_Unicode *in_text, c len = eina_unicode_strlen(text); #endif - fi = fn->fonts->data; - - pen_x = 0; - pen_y = 0; - evas_common_font_int_reload(fi); -// evas_common_font_size_use(fn); - if (fi->src->current_size != fi->size) - { - FTLOCK(); - FT_Activate_Size(fi->ft.size); - FTUNLOCK(); - fi->src->current_size = fi->size; - } - use_kerning = FT_HAS_KERNING(fi->src->ft.face); - prev_index = 0; - prev_chr_end = 0; asc = evas_common_font_max_ascent_get(fn); desc = evas_common_font_max_descent_get(fn); @@ -407,66 +260,18 @@ evas_common_font_query_char_coords(RGBA_Font *fn, const Eina_Unicode *in_text, c goto end; } - last_adv = 0; - for (char_index = 0; *text ; text++, char_index++) + EVAS_FONT_WALK_TEXT_START() { - FT_UInt index; - RGBA_Font_Glyph *fg; int chr_x, chr_y, chr_w; - 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; - } - // FIXME: Why no FT_Activate_Size here ? - kern = 0; - /* 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)) - { - if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) - pen_x += kern; - } + EVAS_FONT_WALK_TEXT_WORK(); - pface = fi->src->ft.face; - LKU(fi->ft_mutex); - /* If the current one is not a compositing char, do the previous advance - * and set the current advance as the next advance to do */ - if (fg->glyph->advance.x >> 16 > 0) - { - pen_x += last_adv; - last_adv = fg->glyph->advance.x >> 16; - } - if (kern < 0) kern = 0; - chr_x = (pen_x - kern) + (fg->glyph_out->left); - chr_y = (pen_y) + (fg->glyph_out->top); - chr_w = fg->glyph_out->bitmap.width + (kern); -/* if (text[chr]) */ - { - int advw; - advw = ((fg->glyph->advance.x + (kern << 16)) >> 16); - if (chr_w < advw) chr_w = advw; - } -#if 0 /* This looks like a hack, we don't want it. - leaving it here in case - * I'm wrong */ - if (chr_x > prev_chr_end) - { - chr_w += (chr_x - prev_chr_end); - chr_x = prev_chr_end; - } -#endif + chr_x = (pen_x) + bear_x; + chr_y = (pen_y) + bear_y; + chr_w = width; /* we need to see if the char at the visual position is the char wanted */ if (char_index == position) - { + { if (cx) *cx = chr_x; if (cy) *cy = -asc; if (cw) *cw = chr_w; @@ -474,9 +279,8 @@ evas_common_font_query_char_coords(RGBA_Font *fn, const Eina_Unicode *in_text, c ret_val = 1; goto end; } - prev_chr_end = chr_x + chr_w; - prev_index = index; } + EVAS_FONT_WALK_TEXT_END(); end: #ifdef BIDI_SUPPORT @@ -498,17 +302,13 @@ end: EAPI int evas_common_font_query_char_at_coords(RGBA_Font *fn, const Eina_Unicode *in_text, const Evas_BiDi_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch) { - int use_kerning; - int pen_x, pen_y; - int prev_chr_end; int asc, desc; - int char_index = 0; /* the index of the current char */ const Eina_Unicode *text = in_text; - int last_adv; int ret_val = -1; - FT_UInt prev_index; + int use_kerning; RGBA_Font_Int *fi; - FT_Face pface = NULL; + EVAS_FONT_WALK_TEXT_INIT(); + _INIT_FI_AND_KERNING(); #ifdef BIDI_SUPPORT int len = 0; @@ -531,86 +331,21 @@ evas_common_font_query_char_at_coords(RGBA_Font *fn, const Eina_Unicode *in_text len = eina_unicode_strlen(text); #endif - fi = fn->fonts->data; - - pen_x = 0; - pen_y = 0; - evas_common_font_int_reload(fi); -// evas_common_font_size_use(fn); - if (fi->src->current_size != fi->size) - { - FTLOCK(); - FT_Activate_Size(fi->ft.size); - FTUNLOCK(); - fi->src->current_size = fi->size; - } - use_kerning = FT_HAS_KERNING(fi->src->ft.face); - last_adv = 0; - prev_index = 0; - prev_chr_end = 0; asc = evas_common_font_max_ascent_get(fn); desc = evas_common_font_max_descent_get(fn); - for (char_index = 0; *text; text++, char_index++) + EVAS_FONT_WALK_TEXT_START() { - FT_UInt index; - RGBA_Font_Glyph *fg; - int chr_x, chr_y, chr_w; - int gl, kern; + int chr_x, chr_w; - 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; - } - - // FIXME: Why not FT_Activate_Size here ? - kern = 0; - /* 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)) - { - if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) - pen_x += kern; - } - pface = fi->src->ft.face; - LKU(fi->ft_mutex); - /* If the current one is not a compositing char, do the previous advance - * and set the current advance as the next advance to do */ - if (fg->glyph->advance.x >> 16 > 0) - { - pen_x += last_adv; - last_adv = fg->glyph->advance.x >> 16; - } - if (kern < 0) kern = 0; + EVAS_FONT_WALK_TEXT_WORK(); - chr_x = ((pen_x - kern) + (fg->glyph_out->left)); - chr_y = (pen_y + (fg->glyph_out->top)); - chr_w = fg->glyph_out->bitmap.width + kern; - -/* if (text[chr]) */ - { - int advw; - - advw = ((fg->glyph->advance.x + (kern << 16)) >> 16); - if (chr_w < advw) chr_w = advw; - } -#if 0 /* This looks like a hack, we don't want it. - leaving it here in case - * I'm wrong */ - if (chr_x > prev_chr_end) - { - chr_w += (chr_x - prev_chr_end); - chr_x = prev_chr_end; - } -#endif - if ((x >= chr_x) && (x <= (chr_x + chr_w)) && + chr_x = (pen_x) + bear_x; + chr_w = width; + /* 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 >= pen_x) && (x <= (pen_x + adv)) && (y >= -asc) && (y <= desc)) { int position = char_index; @@ -622,22 +357,19 @@ evas_common_font_query_char_at_coords(RGBA_Font *fn, const Eina_Unicode *in_text /* we found the char position of the wanted char in the * visual string, we now need to translate it to the * position in the logical string */ - position = evas_bidi_position_visual_to_logical(visual_to_logical, position); + position = evas_bidi_position_visual_to_logical(visual_to_logical, + position); #endif ret_val = position; goto end; } - prev_chr_end = chr_x + chr_w; - prev_index = index; } - + EVAS_FONT_WALK_TEXT_END(); + end: - #ifdef BIDI_SUPPORT if (visual_to_logical) free(visual_to_logical); if (visual_text) free(visual_text); -#else - intl_props = NULL; #endif evas_common_font_int_use_trim(); @@ -654,110 +386,37 @@ end: EAPI int evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const Eina_Unicode *in_text, const Evas_BiDi_Props *intl_props __UNUSED__, int x, int y) { - int use_kerning; - int pen_x, pen_y; - int prev_chr_end; - int char_index; int asc, desc; int ret=-1; const Eina_Unicode *text = in_text; - FT_UInt prev_index; + int use_kerning; RGBA_Font_Int *fi; - FT_Face pface = NULL; + EVAS_FONT_WALK_TEXT_INIT(); + _INIT_FI_AND_KERNING(); - fi = fn->fonts->data; - - pen_x = 0; - pen_y = 0; - evas_common_font_int_reload(fi); -// evas_common_font_size_use(fn); - use_kerning = FT_HAS_KERNING(fi->src->ft.face); - prev_index = 0; - prev_chr_end = 0; asc = evas_common_font_max_ascent_get(fn); desc = evas_common_font_max_descent_get(fn); - for (char_index = 0; *text; text++, char_index++) + EVAS_FONT_WALK_TEXT_START() { - FT_UInt index; - RGBA_Font_Glyph *fg = NULL; int chr_x, chr_y, chr_w; - int gl, kern; - gl = *text; - if (gl == 0) break; - index = evas_common_font_glyph_search(fn, &fi, gl); - LKL(fi->ft_mutex); - if (fi->src->current_size != fi->size) - { - FTLOCK(); - FT_Activate_Size(fi->ft.size); - FTUNLOCK(); - fi->src->current_size = fi->size; - } - kern = 0; - /* 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) && (fg) && - (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 (intl_props && - evas_bidi_is_rtl_char(intl_props, char_index) && - ((fg->glyph->advance.x >> 16) > 0)) - { - 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; - } -#else - if (evas_common_font_query_kerning(fi, prev_index, index, - &kern)) - pen_x += kern; -#endif - } - pface = fi->src->ft.face; - fg = evas_common_font_int_cache_glyph_get(fi, index); - LKU(fi->ft_mutex); + EVAS_FONT_WALK_TEXT_WORK(); - if (kern < 0) kern = 0; - chr_x = ((pen_x - kern) + (fg->glyph_out->left)); - chr_y = (pen_y + (fg->glyph_out->top)); - chr_w = fg->glyph_out->bitmap.width + kern; -/* if (text[chr]) */ - { - int advw; + chr_x = (pen_x) + bear_x; + chr_y = (pen_y) + bear_y; + chr_w = width; - advw = ((fg->glyph->advance.x + (kern << 16)) >> 16); - if (chr_w < advw) chr_w = advw; - } - if (chr_x > prev_chr_end) - { - chr_w += (chr_x - prev_chr_end); - chr_x = prev_chr_end; - } if ((x >= chr_x) && (x <= (chr_x + chr_w)) && (y >= -asc) && (y <= desc)) { ret = char_index; goto end; } - prev_chr_end = chr_x + chr_w; - pen_x += fg->glyph->advance.x >> 16; - prev_index = index; } + EVAS_FONT_WALK_TEXT_END(); + end: evas_common_font_int_use_trim(); - return ret; + return ret; }