#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
{
EINA_INLIST;
};
-#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
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
}
-#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;
EVAS_FONT_WALK_TEXT_START()
LKU(fn->lock);
#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