From 598b3978eca66b70b9445f5c2c977228d5ed6af5 Mon Sep 17 00:00:00 2001 From: tasn Date: Wed, 20 Apr 2011 14:20:51 +0000 Subject: [PATCH] Evas font-engine: Cache pen position instead of advance. We only really use adavnce for calculating the pen position, so it makes more sense to just cache the pen_position instead and calculate advance from that if ever needed. This means size/advance calculations are now O(1) because we don't need to walk the strings anymore. git-svn-id: http://svn.enlightenment.org/svn/e/trunk/evas@58756 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- src/lib/engines/common/evas_font_default_walk.x | 14 +++-- src/lib/engines/common/evas_font_ot.c | 7 ++- src/lib/engines/common/evas_font_query.c | 70 ++++++++++++------------- src/lib/engines/common/evas_text_utils.c | 62 +++++++++++++++------- src/lib/engines/common/evas_text_utils.h | 5 +- 5 files changed, 98 insertions(+), 60 deletions(-) diff --git a/src/lib/engines/common/evas_font_default_walk.x b/src/lib/engines/common/evas_font_default_walk.x index 704db21..a1f60f2 100644 --- a/src/lib/engines/common/evas_font_default_walk.x +++ b/src/lib/engines/common/evas_font_default_walk.x @@ -13,6 +13,9 @@ */ # define EVAS_FONT_WALK_TEXT_INIT() \ int _pen_x = 0, _pen_y = 0; \ + Evas_Coord _start_pen = (text_props->info && \ + (text_props->start > 0)) ? \ + text_props->info->glyph[text_props -> start - 1].pen_after : 0 ; \ size_t char_index; \ (void) _pen_y; /* Sometimes it won't be used */ @@ -149,13 +152,14 @@ #define EVAS_FONT_WALK_IS_VISIBLE (_glyph_itr->index != 0) #define EVAS_FONT_WALK_X_BEAR (_glyph_itr->x_bear) #define EVAS_FONT_WALK_Y_BEAR (fg->glyph_out->top) -#define _EVAS_FONT_WALK_X_ADV (_glyph_itr->advance) +#define EVAS_FONT_WALK_X_ADV ((_glyph_itr > text_props->info->glyph) ? \ + _glyph_itr->pen_after - (_glyph_itr - 1)->pen_after : \ + _glyph_itr->pen_after) #define EVAS_FONT_WALK_WIDTH (_glyph_itr->width) #define EVAS_FONT_WALK_INDEX (_glyph_itr->index) -#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_X (_pen_x) +#define EVAS_FONT_WALK_PEN_X_AFTER (_glyph_itr->pen_after - _start_pen) #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 \ @@ -186,7 +190,7 @@ #define EVAS_FONT_WALK_TEXT_END() \ if (EVAS_FONT_WALK_IS_VISIBLE) \ { \ - _pen_x += _EVAS_FONT_WALK_X_ADV; \ + _pen_x = _glyph_itr->pen_after - _start_pen; \ } \ } \ } \ diff --git a/src/lib/engines/common/evas_font_ot.c b/src/lib/engines/common/evas_font_ot.c index 6a6a4e4..ba7da6b 100644 --- a/src/lib/engines/common/evas_font_ot.c +++ b/src/lib/engines/common/evas_font_ot.c @@ -196,6 +196,7 @@ evas_common_font_ot_populate_text_props(void *_fn, const Eina_Unicode *text, unsigned int i; Evas_Font_Glyph_Info *gl_itr; Evas_Font_OT_Info *ot_itr; + Evas_Coord pen_x = 0; fi = fn->fonts->data; /* Load the font needed for this script */ @@ -252,11 +253,15 @@ evas_common_font_ot_populate_text_props(void *_fn, const Eina_Unicode *text, ot_itr = props->info->ot; for (i = 0 ; i < props->len ; i++) { + Evas_Coord adv; ot_itr->source_cluster = infos->cluster; ot_itr->x_offset = positions->x_offset; ot_itr->y_offset = positions->y_offset; gl_itr->index = infos->codepoint; - gl_itr->advance = positions->x_advance; + adv = positions->x_advance; + + pen_x += adv; + gl_itr->pen_after = EVAS_FONT_ROUND_26_6_TO_INT(pen_x); ot_itr++; gl_itr++; diff --git a/src/lib/engines/common/evas_font_query.c b/src/lib/engines/common/evas_font_query.c index 8fc1cd9..4a32062 100644 --- a/src/lib/engines/common/evas_font_query.c +++ b/src/lib/engines/common/evas_font_query.c @@ -79,10 +79,12 @@ evas_common_font_query_right_inset(RGBA_Font *fn __UNUSED__, const Evas_Text_Pro if (gli->width == 0) return 0; - return EVAS_FONT_ROUND_26_6_TO_INT(gli->advance) - + return ((gli > text_props->info->glyph) ? + gli->pen_after - (gli - 1)->pen_after : gli->pen_after) - (gli->width + gli->x_bear #ifdef OT_SUPPORT - + text_props->info->ot[text_props->start + text_props->len - 1].x_offset + + EVAS_FONT_ROUND_26_6_TO_INT(EVAS_FONT_OT_X_OFF_GET( + text_props->info->ot[text_props->start + text_props->len - 1])) #endif ); } @@ -97,32 +99,29 @@ evas_common_font_query_right_inset(RGBA_Font *fn __UNUSED__, const Evas_Text_Pro EAPI void evas_common_font_query_size(RGBA_Font *fn, const Evas_Text_Props *text_props, int *w, int *h) { - int keep_width = 0; - int prev_pen_x = 0; - EVAS_FONT_WALK_TEXT_INIT(); + Evas_Coord ret_w = 0; - EVAS_FONT_WALK_TEXT_VISUAL_START() + if (text_props->len > 0) { - EVAS_FONT_WALK_TEXT_WORK(); - if (!EVAS_FONT_WALK_IS_VISIBLE) continue; - /* Keep the width because we'll need it for the last char */ - 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_TEXT_END(); + const Evas_Font_Glyph_Info *glyph = text_props->info->glyph + + text_props->start; + const Evas_Font_Glyph_Info *last_glyph = glyph; - /* If the last char is a whitespace, we use the advance as the size */ - if (keep_width > 0) - { - if (w) *w = prev_pen_x + keep_width; - } - else - { - if (w) *w = EVAS_FONT_WALK_PEN_X; + if (text_props->len > 1) + { + last_glyph += text_props->len - 1; + ret_w = last_glyph[-1].pen_after; + if (text_props->start > 0) + ret_w -= glyph[-1].pen_after; + } +#ifdef OT_SUPPORT + ret_w += EVAS_FONT_ROUND_26_6_TO_INT(EVAS_FONT_OT_X_OFF_GET( + text_props->info->ot[text_props->start + text_props->len - 1])); +#endif + ret_w += last_glyph->width + last_glyph->x_bear; } + + if (w) *w = ret_w; if (h) *h = evas_common_font_max_ascent_get(fn) + evas_common_font_max_descent_get(fn); } @@ -135,17 +134,18 @@ evas_common_font_query_size(RGBA_Font *fn, const Evas_Text_Props *text_props, in EAPI void evas_common_font_query_advance(RGBA_Font *fn, const Evas_Text_Props *text_props, int *h_adv, int *v_adv) { - EVAS_FONT_WALK_TEXT_INIT(); - - EVAS_FONT_WALK_TEXT_LOGICAL_START() + Evas_Coord ret_adv = 0; + if (text_props->len > 0) { - EVAS_FONT_WALK_TEXT_WORK(); - if (!EVAS_FONT_WALK_IS_VISIBLE) continue; + const Evas_Font_Glyph_Info *glyph = text_props->info->glyph + + text_props->start; + ret_adv = glyph[text_props->len - 1].pen_after; + if (text_props->start > 0) + ret_adv -= glyph[-1].pen_after; } - EVAS_FONT_WALK_TEXT_END(); + if (h_adv) *h_adv = ret_adv; if (v_adv) *v_adv = evas_common_font_get_line_advance(fn); - if (h_adv) *h_adv = EVAS_FONT_WALK_PEN_X; } /* x y w h for char at char pos for null it returns the position right after @@ -430,8 +430,8 @@ evas_common_font_query_char_at_coords(RGBA_Font *fn, const Evas_Text_Props *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_X_ADV)) && - (y >= -asc) && (y <= desc)) + if ((x >= EVAS_FONT_WALK_PEN_X) && + (x <= (EVAS_FONT_WALK_PEN_X_AFTER)) && (y >= -asc) && (y <= desc)) { #ifdef OT_SUPPORT items = evas_common_font_ot_cluster_size_get(text_props, @@ -496,8 +496,8 @@ evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const Evas_Text_Props *text EVAS_FONT_WALK_TEXT_WORK(); if (!EVAS_FONT_WALK_IS_VISIBLE) continue; - if ((x >= EVAS_FONT_WALK_PEN_X) && (x <= (EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_X_ADV)) && - (y >= -asc) && (y <= desc)) + if ((x >= EVAS_FONT_WALK_PEN_X) && + (x <= (EVAS_FONT_WALK_PEN_X_AFTER)) && (y >= -asc) && (y <= desc)) { ret = EVAS_FONT_WALK_POS; goto end; diff --git a/src/lib/engines/common/evas_text_utils.c b/src/lib/engines/common/evas_text_utils.c index 8cd5ccc..8c2482f 100644 --- a/src/lib/engines/common/evas_text_utils.c +++ b/src/lib/engines/common/evas_text_utils.c @@ -5,9 +5,6 @@ #include "language/evas_language_utils.h" #include "evas_font_ot.h" -/* Used for showing "malformed" or missing chars */ -#define REPLACEMENT_CHAR 0xFFFD - void evas_common_text_props_bidi_set(Evas_Text_Props *props, Evas_BiDi_Paragraph_Props *bidi_par_props, size_t start) @@ -207,6 +204,7 @@ evas_common_text_props_content_create(void *_fn, const Eina_Unicode *text, size_t char_index; Evas_Font_Glyph_Info *gl_itr; const Eina_Unicode *base_char; + Evas_Coord pen_x = 0, adjust_x = 0; (void) par_props; (void) par_pos; @@ -248,14 +246,7 @@ evas_common_text_props_content_create(void *_fn, const Eina_Unicode *text, continue; } LKU(fi->ft_mutex); - if (is_replacement) - { - /* Update the advance accordingly */ - gl_itr->advance = - fg->glyph->advance.x >> 10; - /* FIXME: reload fi, a bit slow, but I have no choice. */ - evas_common_font_glyph_search(fn, &fi, *base_char); - } + gl_itr->x_bear = fg->glyph_out->left; gl_itr->width = fg->glyph_out->bitmap.width; /* text_props->info->glyph[char_index].advance = @@ -263,7 +254,32 @@ evas_common_text_props_content_create(void *_fn, const Eina_Unicode *text, * already done by the ot function */ if (EVAS_FONT_CHARACTER_IS_INVISIBLE( text[text_props->info->ot[char_index].source_cluster])) - gl_itr->index = 0; + { + gl_itr->index = 0; + /* Reduce the current advance */ + if (gl_itr > text_props->info->glyph) + { + adjust_x -= gl_itr->pen_after - (gl_itr - 1)->pen_after; + } + else + { + adjust_x -= gl_itr->pen_after; + } + } + else + { + if (is_replacement) + { + /* Update the advance accordingly */ + adjust_x += (pen_x + (fg->glyph->advance.x >> 16)) - + gl_itr->pen_after; + + /* FIXME: reload fi, a bit slow, but I have no choice. */ + evas_common_font_glyph_search(fn, &fi, *base_char); + } + pen_x = gl_itr->pen_after; + } + gl_itr->pen_after += adjust_x; gl_itr++; } @@ -273,6 +289,7 @@ evas_common_text_props_content_create(void *_fn, const Eina_Unicode *text, Eina_Bool use_kerning; FT_UInt prev_index; FT_Face pface = NULL; + Evas_Coord pen_x = 0; int adv_d, i; #if !defined(OT_SUPPORT) && defined(BIDI_SUPPORT) text = text_props->info->shaped_text = eina_unicode_strndup(text, len); @@ -308,6 +325,7 @@ evas_common_text_props_content_create(void *_fn, const Eina_Unicode *text, FT_UInt index; RGBA_Font_Glyph *fg; int _gl, kern; + Evas_Coord adv; _gl = *text; if (_gl == 0) break; @@ -351,7 +369,7 @@ evas_common_text_props_content_create(void *_fn, const Eina_Unicode *text, { if (evas_common_font_query_kerning(fi, index, prev_index, &kern)) { - (gl_itr - 1)->advance += kern; + (gl_itr - 1)->pen_after += kern; } } else @@ -359,7 +377,7 @@ evas_common_text_props_content_create(void *_fn, const Eina_Unicode *text, { if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) { - (gl_itr - 1)->advance += kern; + (gl_itr - 1)->pen_after += kern; } } } @@ -367,14 +385,22 @@ evas_common_text_props_content_create(void *_fn, const Eina_Unicode *text, pface = fi->src->ft.face; LKU(fi->ft_mutex); - if (EVAS_FONT_CHARACTER_IS_INVISIBLE(_gl)) - gl_itr->index = 0; - gl_itr->index = index; gl_itr->x_bear = fg->glyph_out->left; - gl_itr->advance = fg->glyph->advance.x >> 10; + adv = fg->glyph->advance.x >> 10; gl_itr->width = fg->glyph_out->bitmap.width; + if (EVAS_FONT_CHARACTER_IS_INVISIBLE(_gl)) + { + gl_itr->index = 0; + } + else + { + pen_x += adv; + } + + gl_itr->pen_after = EVAS_FONT_ROUND_26_6_TO_INT(pen_x); + prev_index = index; } text_props->len = len; diff --git a/src/lib/engines/common/evas_text_utils.h b/src/lib/engines/common/evas_text_utils.h index 76efa14..21f8f38 100644 --- a/src/lib/engines/common/evas_text_utils.h +++ b/src/lib/engines/common/evas_text_utils.h @@ -9,6 +9,9 @@ typedef struct _Evas_Font_Glyph_Info Evas_Font_Glyph_Info; # include "language/evas_bidi_utils.h" # include "language/evas_language_utils.h" +/* Used for showing "malformed" or missing chars */ +#define REPLACEMENT_CHAR 0xFFFD + struct _Evas_Text_Props { /* Start and len represent the start offset and the length in the @@ -44,7 +47,7 @@ struct _Evas_Font_Glyph_Info Evas_Coord y_bear; #endif Evas_Coord width; - Evas_Coord advance; + Evas_Coord pen_after; }; -- 2.7.4