forked from enlightenment/efl
evas: remove WORD_CACHE and METRIC_CACHE.
Note: this two were broken. Current plan to bring that feature back in, is to attach this information to Evas_Text_Prop during the prepare stage. This would improve both single and multiple core rendering without increasing the number of lock and the complexity of the code. SVN revision: 70501
This commit is contained in:
parent
5965fb4282
commit
9dbaea6dd1
|
@ -711,4 +711,4 @@
|
||||||
2012-04-26 Cedric Bail
|
2012-04-26 Cedric Bail
|
||||||
|
|
||||||
* Lock less font rendering.
|
* Lock less font rendering.
|
||||||
* Removing EVAS_SLI.
|
* Removing EVAS_SLI, METRIC_CACHE and WORD_CACHE.
|
||||||
|
|
|
@ -7,7 +7,7 @@ Improvements:
|
||||||
* Lock less font rendering.
|
* Lock less font rendering.
|
||||||
|
|
||||||
Removal:
|
Removal:
|
||||||
* Remove EVAS_SLI.
|
* Remove EVAS_SLI, METRIC_CACHE and WORD_CACHE.
|
||||||
|
|
||||||
Evas 1.2.0
|
Evas 1.2.0
|
||||||
|
|
||||||
|
|
|
@ -7,21 +7,6 @@
|
||||||
|
|
||||||
#include "evas_font_ot.h"
|
#include "evas_font_ot.h"
|
||||||
|
|
||||||
/* Forcibly disable the broken word/metric caching. */
|
|
||||||
#ifdef METRIC_CACHE
|
|
||||||
# undef METRIC_CACHE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WORD_CACHE
|
|
||||||
# undef WORD_CACHE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define WORD_CACHE_MAXLEN 50
|
|
||||||
/* How many to cache */
|
|
||||||
#define WORD_CACHE_NWORDS 40
|
|
||||||
|
|
||||||
static int max_cached_words = WORD_CACHE_NWORDS;
|
|
||||||
|
|
||||||
struct prword
|
struct prword
|
||||||
{
|
{
|
||||||
EINA_INLIST;
|
EINA_INLIST;
|
||||||
|
@ -52,26 +37,9 @@ 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 Evas_Text_Props *text_props);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
EAPI void
|
EAPI void
|
||||||
evas_common_font_draw_init(void)
|
evas_common_font_draw_init(void)
|
||||||
{
|
{
|
||||||
char *p;
|
|
||||||
int tmp;
|
|
||||||
|
|
||||||
if ((p = getenv("EVAS_WORD_CACHE_MAX_WORDS")))
|
|
||||||
{
|
|
||||||
tmp = strtol(p,NULL,10);
|
|
||||||
/* 0 to disable of course */
|
|
||||||
if (tmp > -1 && tmp < 500){
|
|
||||||
max_cached_words = tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef EVAS_FRAME_QUEUING
|
#ifdef EVAS_FRAME_QUEUING
|
||||||
|
@ -110,97 +78,6 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, in
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if defined(METRIC_CACHE) || defined(WORD_CACHE)
|
|
||||||
unsigned int len;
|
|
||||||
|
|
||||||
len = text_props->len;
|
|
||||||
|
|
||||||
if (len > 2 && (len < WORD_CACHE_MAXLEN))
|
|
||||||
{
|
|
||||||
struct prword *word;
|
|
||||||
|
|
||||||
word =
|
|
||||||
evas_font_word_prerender(dc, text_props);
|
|
||||||
if (word)
|
|
||||||
{
|
|
||||||
int j, rowstart, rowend, xstart, xrun;
|
|
||||||
|
|
||||||
im = dst->image.data;
|
|
||||||
xrun = word->width;
|
|
||||||
y -= word->baseline;
|
|
||||||
xstart = 0;
|
|
||||||
rowstart = 0;
|
|
||||||
rowend = word->height;
|
|
||||||
/* Clip to extent */
|
|
||||||
if (x + xrun > ext_x + ext_w)
|
|
||||||
{
|
|
||||||
xrun -= x + xrun - ext_x - ext_w;
|
|
||||||
}
|
|
||||||
if (x < ext_x)
|
|
||||||
{
|
|
||||||
int excess = ext_x - x;
|
|
||||||
xstart = excess - 1;
|
|
||||||
xrun -= excess;
|
|
||||||
x = ext_x;
|
|
||||||
}
|
|
||||||
if (y + rowend > ext_y + ext_h)
|
|
||||||
{
|
|
||||||
rowend -= (y - ext_y + rowend - ext_h);
|
|
||||||
}
|
|
||||||
if (y < ext_y)
|
|
||||||
{
|
|
||||||
int excess = ext_y - y;
|
|
||||||
rowstart += excess;
|
|
||||||
//rowend -= excess;
|
|
||||||
// y = ext_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xrun < 1) return;
|
|
||||||
/* For some reason, metric and word chache are exactly the same except for
|
|
||||||
* this piece of code that makes metric go nuts. ATM, we'll just go the
|
|
||||||
* WORD_CACHE path. */
|
|
||||||
#if defined(METRIC_CACHE) || defined(WORD_CACHE)
|
|
||||||
if (word->im)
|
|
||||||
{
|
|
||||||
for (j = rowstart ; j < rowend ; j ++)
|
|
||||||
{
|
|
||||||
func(NULL, word->im + (word->roww * j) + xstart, dc->col.col,
|
|
||||||
im + ((y + j) * im_w) + x, xrun);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
# elif defined(METRIC_CACHE)
|
|
||||||
unsigned int ind;
|
|
||||||
|
|
||||||
y += word->baseline;
|
|
||||||
for (ind = 0 ; ind < len ; ind ++)
|
|
||||||
{
|
|
||||||
// FIXME Do we need to draw?
|
|
||||||
struct cinfo *ci = word->cinfo + ind;
|
|
||||||
for (j = rowstart ; j < rowend ; j ++)
|
|
||||||
{
|
|
||||||
if ((ci->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, ci->fg,
|
|
||||||
x + ci->pos.x,
|
|
||||||
y - ci->bm.h + j);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
func(NULL, word->im + (word->roww * j) + xstart,
|
|
||||||
dc->col.col, im + ((y + j) * im_w) + x, xrun);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
im = dst->image.data;
|
im = dst->image.data;
|
||||||
|
|
||||||
EVAS_FONT_WALK_TEXT_START()
|
EVAS_FONT_WALK_TEXT_START()
|
||||||
|
@ -500,177 +377,3 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int
|
||||||
LKU(fn->lock);
|
LKU(fn->lock);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only used if cache is on */
|
|
||||||
#if defined(METRIC_CACHE) || defined(WORD_CACHE)
|
|
||||||
|
|
||||||
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;
|
|
||||||
unsigned char *im;
|
|
||||||
int width;
|
|
||||||
int height, above, below, baseline, descent;
|
|
||||||
unsigned int i,j;
|
|
||||||
struct prword *w;
|
|
||||||
int last_delta = 0;
|
|
||||||
Eina_Unicode gl;
|
|
||||||
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();
|
|
||||||
|
|
||||||
# ifndef METRIC_CACHE
|
|
||||||
gl = dc->font_ext.func.gl_new ? 1: 0;
|
|
||||||
if (gl) return NULL;
|
|
||||||
# endif
|
|
||||||
|
|
||||||
LKL(lock_words);
|
|
||||||
EINA_INLIST_FOREACH(words,w)
|
|
||||||
{
|
|
||||||
if (_evas_font_word_prerender_text_props_equal(&w->text_props,
|
|
||||||
text_props))
|
|
||||||
{
|
|
||||||
words = eina_inlist_promote(words, EINA_INLIST_GET(w));
|
|
||||||
LKU(lock_words);
|
|
||||||
return w;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LKU(lock_words);
|
|
||||||
|
|
||||||
gl = dc->font_ext.func.gl_new ? 1: 0;
|
|
||||||
|
|
||||||
above = 0; below = 0; baseline = 0; height = 0; descent = 0;
|
|
||||||
|
|
||||||
/* First pass: Work out how big and populate */
|
|
||||||
metrics = malloc(sizeof(struct cinfo) * len);
|
|
||||||
ci = metrics;
|
|
||||||
EVAS_FONT_WALK_TEXT_START()
|
|
||||||
{
|
|
||||||
FT_UInt index;
|
|
||||||
RGBA_Font_Glyph *fg;
|
|
||||||
index = EVAS_FONT_WALK_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);
|
|
||||||
EVAS_FONT_WALK_TEXT_WORK();
|
|
||||||
/* Currently broken with invisible chars if (!EVAS_FONT_WALK_IS_VISIBLE) continue; */
|
|
||||||
ci->index = index;
|
|
||||||
ci->fg = fg;
|
|
||||||
|
|
||||||
if (gl)
|
|
||||||
{
|
|
||||||
ci->fg->ext_dat =dc->font_ext.func.gl_new(dc->font_ext.data,ci->fg);
|
|
||||||
ci->fg->ext_dat_free = dc->font_ext.func.gl_free;
|
|
||||||
}
|
|
||||||
ci->bm.data = ci->fg->glyph_out->bitmap.buffer;
|
|
||||||
ci->bm.w = MAX(ci->fg->glyph_out->bitmap.pitch,
|
|
||||||
ci->fg->glyph_out->bitmap.width);
|
|
||||||
ci->bm.rows = ci->fg->glyph_out->bitmap.rows;
|
|
||||||
ci->bm.h = ci->fg->glyph_out->top;
|
|
||||||
above = ci->bm.rows - (ci->bm.rows - ci->bm.h);
|
|
||||||
below = ci->bm.rows - ci->bm.h;
|
|
||||||
if (below > descent) descent = below;
|
|
||||||
if (above > baseline) baseline = above;
|
|
||||||
ci->pos.x = EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_X_OFF + EVAS_FONT_WALK_X_BEAR;
|
|
||||||
ci->pos.y = EVAS_FONT_WALK_PEN_Y + EVAS_FONT_WALK_Y_OFF + EVAS_FONT_WALK_Y_BEAR;
|
|
||||||
last_delta = EVAS_FONT_WALK_X_ADV -
|
|
||||||
(ci->bm.w + ci->fg->glyph_out->left);
|
|
||||||
ci++;
|
|
||||||
}
|
|
||||||
EVAS_FONT_WALK_TEXT_END();
|
|
||||||
|
|
||||||
/* First loop done */
|
|
||||||
width = EVAS_FONT_WALK_PEN_X;
|
|
||||||
if (last_delta < 0)
|
|
||||||
width -= last_delta;
|
|
||||||
width = (width & 0x7) ? width + (8 - (width & 0x7)) : width;
|
|
||||||
|
|
||||||
height = baseline + descent;
|
|
||||||
if (!gl)
|
|
||||||
{
|
|
||||||
im = calloc(height, width);
|
|
||||||
for (i = 0 ; i < len ; i ++)
|
|
||||||
{
|
|
||||||
struct cinfo *cin = metrics + i;
|
|
||||||
|
|
||||||
for (j = 0 ; j < cin->bm.rows ; j ++)
|
|
||||||
{
|
|
||||||
int correction; /* Used to remove negative inset and such */
|
|
||||||
if (cin->pos.x < 0)
|
|
||||||
correction = -cin->pos.x;
|
|
||||||
else
|
|
||||||
correction = 0;
|
|
||||||
|
|
||||||
memcpy(im + cin->pos.x + (j + baseline - cin->bm.h) * width +
|
|
||||||
correction,
|
|
||||||
cin->bm.data + j * cin->bm.w + correction,
|
|
||||||
cin->bm.w - correction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
im = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Save it */
|
|
||||||
struct prword *save;
|
|
||||||
|
|
||||||
save = malloc(sizeof(struct prword));
|
|
||||||
save->cinfo = metrics;
|
|
||||||
evas_common_text_props_content_copy_and_ref(&save->text_props, text_props);
|
|
||||||
save->im = im;
|
|
||||||
save->width = EVAS_FONT_WALK_PEN_X;
|
|
||||||
if (last_delta < 0)
|
|
||||||
save->width += last_delta;
|
|
||||||
save->roww = width;
|
|
||||||
save->height = height;
|
|
||||||
save->baseline = baseline;
|
|
||||||
LKL(lock_words);
|
|
||||||
words = eina_inlist_prepend(words, EINA_INLIST_GET(save));
|
|
||||||
|
|
||||||
/* Clean up if too long */
|
|
||||||
if (eina_inlist_count(words) > max_cached_words)
|
|
||||||
{
|
|
||||||
struct prword *last = (struct prword *)(words->last);
|
|
||||||
|
|
||||||
if (last)
|
|
||||||
{
|
|
||||||
if (last->im) free(last->im);
|
|
||||||
if (last->cinfo) free(last->cinfo);
|
|
||||||
evas_common_text_props_content_unref(&last->text_props);
|
|
||||||
words = eina_inlist_remove(words, EINA_INLIST_GET(last));
|
|
||||||
free(last);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LKU(lock_words);
|
|
||||||
|
|
||||||
return save;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
Loading…
Reference in New Issue