Evas font-draw: Fix word-cache to not need text.

SVN revision: 59132
This commit is contained in:
Tom Hacohen 2011-05-02 15:33:38 +00:00
parent 61e340ec6c
commit dad49dd1f2
1 changed files with 62 additions and 69 deletions

View File

@ -18,12 +18,8 @@ static int max_cached_words = WORD_CACHE_NWORDS;
struct prword struct prword
{ {
EINA_INLIST; EINA_INLIST;
/* FIXME: Need to save font/size et al */
int size;
struct cinfo *cinfo; struct cinfo *cinfo;
RGBA_Font *font; Evas_Text_Props text_props;
const Eina_Unicode *str;
int len;
DATA8 *im; DATA8 *im;
int roww; int roww;
int width; int width;
@ -52,7 +48,7 @@ struct cinfo
#if defined(METRIC_CACHE) || defined(WORD_CACHE) #if defined(METRIC_CACHE) || defined(WORD_CACHE)
LK(lock_words); // for word cache call LK(lock_words); // for word cache call
static Eina_Inlist *words = NULL; static Eina_Inlist *words = NULL;
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); static struct prword *evas_font_word_prerender(RGBA_Draw_Context *dc, const Evas_Text_Props *text_props);
#endif #endif
EAPI void EAPI void
@ -410,27 +406,41 @@ evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, int gl)
* is on the right, and not on the left). * is on the right, and not on the left).
*/ */
static void 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, evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn __UNUSED__, int x, int y,
const Evas_Text_Props *text_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 ext_h, int im_w, int im_h __UNUSED__)
{ {
const Eina_Unicode *text = in_text;
DATA32 *im; DATA32 *im;
FT_Face pface = NULL; FT_Face pface = NULL;
RGBA_Font_Int *fi;
EVAS_FONT_WALK_TEXT_INIT(); EVAS_FONT_WALK_TEXT_INIT();
fi = text_props->font_instance;
if (fi)
{
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;
}
}
#if defined(METRIC_CACHE) || defined(WORD_CACHE) #if defined(METRIC_CACHE) || defined(WORD_CACHE)
unsigned int len; unsigned int len;
len = text_props->text_len; len = text_props->len;
if (len > 2 && (len < WORD_CACHE_MAXLEN)) if (len > 2 && (len < WORD_CACHE_MAXLEN))
{ {
struct prword *word; struct prword *word;
word = word =
evas_font_word_prerender(dc, text, text_props, evas_font_word_prerender(dc, text_props);
len, fn, fi);
if (word) if (word)
{ {
int j, rowstart, rowend, xstart, xrun; int j, rowstart, rowend, xstart, xrun;
@ -477,7 +487,7 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
return; return;
} }
# elif defined(METRIC_CACHE) # elif defined(METRIC_CACHE)
int ind; unsigned int ind;
y += word->baseline; y += word->baseline;
for (ind = 0 ; ind < len ; ind ++) for (ind = 0 ; ind < len ; ind ++)
@ -513,20 +523,6 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
im = dst->image.data; im = dst->image.data;
fi = text_props->font_instance;
if (fi)
{
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;
}
}
EVAS_FONT_WALK_TEXT_START() EVAS_FONT_WALK_TEXT_START()
{ {
FT_UInt index; FT_UInt index;
@ -690,20 +686,17 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
} }
EAPI void EAPI void
evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const Eina_Unicode *text, evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const Eina_Unicode *text __UNUSED__,
const Evas_Text_Props *text_props) const Evas_Text_Props *text_props)
{ {
int ext_x, ext_y, ext_w, ext_h; int ext_x, ext_y, ext_w, ext_h;
int im_w, im_h; int im_w, im_h;
RGBA_Gfx_Func func; RGBA_Gfx_Func func;
RGBA_Font_Int *fi;
Cutout_Rects *rects; Cutout_Rects *rects;
Cutout_Rect *r; Cutout_Rect *r;
int c, cx, cy, cw, ch; int c, cx, cy, cw, ch;
int i; int i;
fi = fn->fonts->data;
im_w = dst->cache_entry.w; im_w = dst->cache_entry.w;
im_h = dst->cache_entry.h; im_h = dst->cache_entry.h;
@ -735,14 +728,13 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int
#ifdef EVAS_FRAME_QUEUING #ifdef EVAS_FRAME_QUEUING
LKL(fn->lock); LKL(fn->lock);
#endif #endif
evas_common_font_int_reload(fi);
// evas_common_font_size_use(fn); // evas_common_font_size_use(fn);
func = evas_common_gfx_func_composite_mask_color_span_get(dc->col.col, dst, 1, dc->render_op); func = evas_common_gfx_func_composite_mask_color_span_get(dc->col.col, dst, 1, dc->render_op);
if (!dc->cutout.rects) if (!dc->cutout.rects)
{ {
evas_common_font_draw_internal(dst, dc, fn, x, y, text, text_props, evas_common_font_draw_internal(dst, dc, fn, x, y, text_props,
func, ext_x, ext_y, ext_w, ext_h, fi, func, ext_x, ext_y, ext_w, ext_h,
im_w, im_h); im_w, im_h);
} }
else else
@ -757,8 +749,8 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int
{ {
r = rects->rects + i; r = rects->rects + i;
evas_common_draw_context_set_clip(dc, r->x, r->y, r->w, r->h); 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, text_props, evas_common_font_draw_internal(dst, dc, fn, x, y, text_props,
func, r->x, r->y, r->w, r->h, fi, func, r->x, r->y, r->w, r->h,
im_w, im_h); im_w, im_h);
} }
evas_common_draw_context_apply_clear_cutouts(rects); evas_common_draw_context_apply_clear_cutouts(rects);
@ -770,23 +762,42 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int
#endif #endif
} }
/* FIXME: Where is it freed at? */
/* Only used if cache is on */ /* Only used if cache is on */
#if defined(METRIC_CACHE) || defined(WORD_CACHE) #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 *text_props, int len, RGBA_Font *fn, RGBA_Font_Int *fi) static Eina_Bool
_evas_font_word_prerender_text_props_equal(const Evas_Text_Props *_a, const Evas_Text_Props *_b)
{
Evas_Font_Glyph_Info *gl1, *gl2;
size_t i;
if ((_a->len != _b->len) ||
(_a->font_instance != _b->font_instance))
return EINA_FALSE;
gl1 = _a->info->glyph + _a->start;
gl2 = _b->info->glyph + _b->start;
i = _a->len;
for ( ; (i > 0) && (gl1->index == gl2->index) ; i--, gl1++, gl2++)
;
return (i == 0);
}
static struct prword *
evas_font_word_prerender(RGBA_Draw_Context *dc, const Evas_Text_Props *text_props)
{ {
struct cinfo *metrics; struct cinfo *metrics;
const Eina_Unicode *text = in_text;
(void) text;
unsigned char *im; unsigned char *im;
int width; int width;
int height, above, below, baseline, descent; int height, above, below, baseline, descent;
int i,j; unsigned int i,j;
struct prword *w; struct prword *w;
int last_delta = 0; int last_delta = 0;
int gl; int gl;
struct cinfo *ci; struct cinfo *ci;
unsigned int len = text_props->len;
RGBA_Font_Int *fi = (RGBA_Font_Int *) text_props->font_instance;
EVAS_FONT_WALK_TEXT_INIT(); EVAS_FONT_WALK_TEXT_INIT();
# ifndef METRIC_CACHE # ifndef METRIC_CACHE
@ -797,36 +808,21 @@ evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *in_text, con
LKL(lock_words); LKL(lock_words);
EINA_INLIST_FOREACH(words,w) EINA_INLIST_FOREACH(words,w)
{ {
if (w->len == len && w->font == fn && fi->size == w->size && if (_evas_font_word_prerender_text_props_equal(&w->text_props,
(w->str == in_text || memcmp(w->str, in_text, len * sizeof(Eina_Unicode)) == 0)){ text_props))
words = eina_inlist_promote(words, EINA_INLIST_GET(w)); {
LKU(lock_words); words = eina_inlist_promote(words, EINA_INLIST_GET(w));
return w; LKU(lock_words);
} return w;
}
} }
LKU(lock_words); LKU(lock_words);
gl = dc->font_ext.func.gl_new ? 1: 0; gl = dc->font_ext.func.gl_new ? 1: 0;
above = 0; below = 0; baseline = 0; height = 0; descent = 0; above = 0; below = 0; baseline = 0; height = 0; descent = 0;
fi = text_props->font_instance;
if (fi)
{
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;
}
}
/* First pass: Work out how big and populate */ /* First pass: Work out how big and populate */
/* It's a bit hackish to use index and fg here as they are internal,
* but that'll have to be good enough ATM */
len = text_props->len;
metrics = malloc(sizeof(struct cinfo) * len); metrics = malloc(sizeof(struct cinfo) * len);
ci = metrics; ci = metrics;
EVAS_FONT_WALK_TEXT_START() EVAS_FONT_WALK_TEXT_START()
@ -909,10 +905,7 @@ evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *in_text, con
save = malloc(sizeof(struct prword)); save = malloc(sizeof(struct prword));
save->cinfo = metrics; save->cinfo = metrics;
save->str = eina_ustringshare_add(in_text); evas_common_text_props_content_copy_and_ref(&save->text_props, text_props);
save->font = fn;
save->size = fi->size;
save->len = len;
save->im = im; save->im = im;
save->width = EVAS_FONT_WALK_PEN_X; save->width = EVAS_FONT_WALK_PEN_X;
if (last_delta < 0) if (last_delta < 0)
@ -932,7 +925,7 @@ evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *in_text, con
{ {
if (last->im) free(last->im); if (last->im) free(last->im);
if (last->cinfo) free(last->cinfo); if (last->cinfo) free(last->cinfo);
eina_ustringshare_del(last->str); evas_common_text_props_content_unref(&last->text_props);
words = eina_inlist_remove(words, EINA_INLIST_GET(last)); words = eina_inlist_remove(words, EINA_INLIST_GET(last));
free(last); free(last);
} }