forked from enlightenment/efl
Fix issue when using word-cache: Make sure we have a 'last' word
before trying to free it, else we segfault. Fix compiler warnings wrt const vs non-const of Evas_BiDi_Props. Fix formatting and remove whitespace also. NB: The major change here is in evas_font_word_prerender wrt freeing the 'last' word of the cache. SVN revision: 53166
This commit is contained in:
parent
9910581b1c
commit
2f3b2b99e5
|
@ -5,37 +5,43 @@
|
||||||
#include "evas_bidi_utils.h" /*defines BIDI_SUPPORT if possible */
|
#include "evas_bidi_utils.h" /*defines BIDI_SUPPORT if possible */
|
||||||
#include "evas_font_private.h" /* for Frame-Queuing support */
|
#include "evas_font_private.h" /* for Frame-Queuing support */
|
||||||
|
|
||||||
#define WORD_CACHE_MAXLEN 50
|
#define WORD_CACHE_MAXLEN 50
|
||||||
/* How many to cache */
|
/* How many to cache */
|
||||||
#define WORD_CACHE_NWORDS 40
|
#define WORD_CACHE_NWORDS 40
|
||||||
static int max_cached_words = WORD_CACHE_NWORDS;
|
static int max_cached_words = WORD_CACHE_NWORDS;
|
||||||
|
|
||||||
struct prword {
|
struct prword
|
||||||
EINA_INLIST;
|
{
|
||||||
/* FIXME: Need to save font/size et al */
|
EINA_INLIST;
|
||||||
int size;
|
/* FIXME: Need to save font/size et al */
|
||||||
struct cinfo *cinfo;
|
int size;
|
||||||
RGBA_Font *font;
|
struct cinfo *cinfo;
|
||||||
const Eina_Unicode *str;
|
RGBA_Font *font;
|
||||||
int len;
|
const Eina_Unicode *str;
|
||||||
DATA8 *im;
|
int len;
|
||||||
int roww;
|
DATA8 *im;
|
||||||
int width;
|
int roww;
|
||||||
int height;
|
int width;
|
||||||
int baseline;
|
int height;
|
||||||
|
int baseline;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cinfo {
|
struct cinfo
|
||||||
int gl;
|
{
|
||||||
FT_UInt index;
|
int gl;
|
||||||
struct { int x, y; } pos;
|
FT_UInt index;
|
||||||
int posx;
|
struct
|
||||||
RGBA_Font_Glyph *fg;
|
{
|
||||||
struct {
|
int x, y;
|
||||||
int w,h;
|
} pos;
|
||||||
int rows;
|
int posx;
|
||||||
unsigned char *data;
|
RGBA_Font_Glyph *fg;
|
||||||
} bm;
|
struct
|
||||||
|
{
|
||||||
|
int w,h;
|
||||||
|
int rows;
|
||||||
|
unsigned char *data;
|
||||||
|
} bm;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,6 +56,7 @@ evas_common_font_draw_init(void)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
int tmp;
|
int tmp;
|
||||||
|
|
||||||
if ((p = getenv("EVAS_WORD_CACHE_MAX_WORDS")))
|
if ((p = getenv("EVAS_WORD_CACHE_MAX_WORDS")))
|
||||||
{
|
{
|
||||||
tmp = strtol(p,NULL,10);
|
tmp = strtol(p,NULL,10);
|
||||||
|
@ -71,7 +78,7 @@ static void
|
||||||
_fash_int_free(Fash_Int *fash)
|
_fash_int_free(Fash_Int *fash)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < 256; i++) if (fash->bucket[i]) free(fash->bucket[i]);
|
for (i = 0; i < 256; i++) if (fash->bucket[i]) free(fash->bucket[i]);
|
||||||
free(fash);
|
free(fash);
|
||||||
}
|
}
|
||||||
|
@ -100,7 +107,7 @@ static void
|
||||||
_fash_int_add(Fash_Int *fash, int item, RGBA_Font_Int *fint, int index)
|
_fash_int_add(Fash_Int *fash, int item, RGBA_Font_Int *fint, int index)
|
||||||
{
|
{
|
||||||
int maj, min;
|
int maj, min;
|
||||||
|
|
||||||
item &= 0xffff; // fixme: to do > 65k
|
item &= 0xffff; // fixme: to do > 65k
|
||||||
maj = (item >> 8) & 0xff;
|
maj = (item >> 8) & 0xff;
|
||||||
min = item & 0xff;
|
min = item & 0xff;
|
||||||
|
@ -110,15 +117,11 @@ _fash_int_add(Fash_Int *fash, int item, RGBA_Font_Int *fint, int index)
|
||||||
fash->bucket[maj]->item[min].index = index;
|
fash->bucket[maj]->item[min].index = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_fash_gl_free(Fash_Glyph *fash)
|
_fash_gl_free(Fash_Glyph *fash)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < 256; i++) if (fash->bucket[i]) free(fash->bucket[i]);
|
for (i = 0; i < 256; i++) if (fash->bucket[i]) free(fash->bucket[i]);
|
||||||
free(fash);
|
free(fash);
|
||||||
}
|
}
|
||||||
|
@ -147,7 +150,7 @@ static void
|
||||||
_fash_gl_add(Fash_Glyph *fash, int item, RGBA_Font_Glyph *glyph)
|
_fash_gl_add(Fash_Glyph *fash, int item, RGBA_Font_Glyph *glyph)
|
||||||
{
|
{
|
||||||
int maj, min;
|
int maj, min;
|
||||||
|
|
||||||
item &= 0xffff; // fixme: to do > 65k
|
item &= 0xffff; // fixme: to do > 65k
|
||||||
maj = (item >> 8) & 0xff;
|
maj = (item >> 8) & 0xff;
|
||||||
min = item & 0xff;
|
min = item & 0xff;
|
||||||
|
@ -156,10 +159,6 @@ _fash_gl_add(Fash_Glyph *fash, int item, RGBA_Font_Glyph *glyph)
|
||||||
fash->bucket[maj]->item[min] = glyph;
|
fash->bucket[maj]->item[min] = glyph;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EAPI RGBA_Font_Glyph *
|
EAPI RGBA_Font_Glyph *
|
||||||
evas_common_font_int_cache_glyph_get(RGBA_Font_Int *fi, FT_UInt index)
|
evas_common_font_int_cache_glyph_get(RGBA_Font_Int *fi, FT_UInt index)
|
||||||
{
|
{
|
||||||
|
@ -175,9 +174,9 @@ evas_common_font_int_cache_glyph_get(RGBA_Font_Int *fi, FT_UInt index)
|
||||||
if (fg == (void *)(-1)) return NULL;
|
if (fg == (void *)(-1)) return NULL;
|
||||||
else if (fg) return fg;
|
else if (fg) return fg;
|
||||||
}
|
}
|
||||||
|
|
||||||
hindex = index + (fi->hinting * 500000000);
|
hindex = index + (fi->hinting * 500000000);
|
||||||
|
|
||||||
// fg = eina_hash_find(fi->glyphs, &hindex);
|
// fg = eina_hash_find(fi->glyphs, &hindex);
|
||||||
// if (fg) return fg;
|
// if (fg) return fg;
|
||||||
|
|
||||||
|
@ -214,22 +213,21 @@ evas_common_font_int_cache_glyph_get(RGBA_Font_Int *fi, FT_UInt index)
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
FT_Done_Glyph(fg->glyph);
|
FT_Done_Glyph(fg->glyph);
|
||||||
FTUNLOCK();
|
FTUNLOCK();
|
||||||
free(fg);
|
free(fg);
|
||||||
if (!fi->fash) fi->fash = _fash_gl_new();
|
if (!fi->fash) fi->fash = _fash_gl_new();
|
||||||
if (fi->fash) _fash_gl_add(fi->fash, index, (void *)(-1));
|
if (fi->fash) _fash_gl_add(fi->fash, index, (void *)(-1));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
FTUNLOCK();
|
FTUNLOCK();
|
||||||
}
|
}
|
||||||
fg->glyph_out = (FT_BitmapGlyph)fg->glyph;
|
fg->glyph_out = (FT_BitmapGlyph)fg->glyph;
|
||||||
fg->index = hindex;
|
fg->index = hindex;
|
||||||
|
|
||||||
fg->fi = fi;
|
fg->fi = fi;
|
||||||
|
|
||||||
if (!fi->fash) fi->fash = _fash_gl_new();
|
if (!fi->fash) fi->fash = _fash_gl_new();
|
||||||
if (fi->fash) _fash_gl_add(fi->fash, index, fg);
|
if (fi->fash) _fash_gl_add(fi->fash, index, fg);
|
||||||
|
|
||||||
// eina_hash_direct_add(fi->glyphs, &fg->index, fg);
|
// eina_hash_direct_add(fi->glyphs, &fg->index, fg);
|
||||||
return fg;
|
return fg;
|
||||||
}
|
}
|
||||||
|
@ -295,7 +293,7 @@ evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, int gl)
|
||||||
else if (fm->index == -1) return 0;
|
else if (fm->index == -1) return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (l = fn->fonts; l; l = l->next)
|
for (l = fn->fonts; l; l = l->next)
|
||||||
{
|
{
|
||||||
RGBA_Font_Int *fi;
|
RGBA_Font_Int *fi;
|
||||||
|
@ -318,9 +316,9 @@ evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, int gl)
|
||||||
|
|
||||||
*fi_ret = fi;
|
*fi_ret = fi;
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
*/
|
*/
|
||||||
#endif
|
#endif
|
||||||
if (!fi->src->ft.face) /* Charmap not loaded, FI/FS blank */
|
if (!fi->src->ft.face) /* Charmap not loaded, FI/FS blank */
|
||||||
|
@ -333,8 +331,8 @@ evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, int gl)
|
||||||
if (index == 0)
|
if (index == 0)
|
||||||
{
|
{
|
||||||
// Load Hash
|
// Load Hash
|
||||||
FT_ULong charcode;
|
FT_ULong charcode;
|
||||||
FT_UInt gindex;
|
FT_UInt gindex;
|
||||||
|
|
||||||
fi->src->charmap = evas_array_hash_new();
|
fi->src->charmap = evas_array_hash_new();
|
||||||
charcode = FT_Get_First_Char(fi->src->ft.face, &gindex);
|
charcode = FT_Get_First_Char(fi->src->ft.face, &gindex);
|
||||||
|
@ -380,7 +378,6 @@ evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, int gl)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* BiDi handling: We receive the shaped string + other props from intl_props,
|
* BiDi handling: We receive the shaped string + other props from intl_props,
|
||||||
* we need to reorder it so we'll have the visual string (the way we draw)
|
* we need to reorder it so we'll have the visual string (the way we draw)
|
||||||
|
@ -402,83 +399,94 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
|
||||||
int c;
|
int c;
|
||||||
int char_index = 0; /* the index of the current char */
|
int char_index = 0; /* the index of the current char */
|
||||||
|
|
||||||
|
|
||||||
#if defined(METRIC_CACHE) || defined(WORD_CACHE)
|
#if defined(METRIC_CACHE) || defined(WORD_CACHE)
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
|
|
||||||
/* A fast strNlen would be nice (there is a wcsnlen strangely) */
|
/* A fast strNlen would be nice (there is a wcsnlen strangely) */
|
||||||
len = eina_unicode_strnlen(text,WORD_CACHE_MAXLEN);
|
len = eina_unicode_strnlen(text,WORD_CACHE_MAXLEN);
|
||||||
|
|
||||||
if (len > 2 && len < WORD_CACHE_MAXLEN){
|
if (len > 2 && len < WORD_CACHE_MAXLEN)
|
||||||
struct prword *word = evas_font_word_prerender(dc, text, intl_props, len, fn, fi,
|
{
|
||||||
use_kerning);
|
struct prword *word;
|
||||||
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;
|
word =
|
||||||
|
evas_font_word_prerender(dc, text, (Evas_BiDi_Props *)intl_props,
|
||||||
|
len, fn, fi, use_kerning);
|
||||||
|
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;
|
||||||
# ifdef WORD_CACHE
|
# ifdef WORD_CACHE
|
||||||
if (word->im){
|
if (word->im)
|
||||||
for (j = rowstart ; j < rowend ; j ++){
|
{
|
||||||
func(NULL, word->im + (word->roww * j) + xstart, dc->col.col,
|
for (j = rowstart ; j < rowend ; j ++)
|
||||||
im + ((y + j) * im_w) + x, xrun);
|
{
|
||||||
}
|
func(NULL, word->im + (word->roww * j) + xstart, dc->col.col,
|
||||||
return;
|
im + ((y + j) * im_w) + x, xrun);
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
# elif defined(METRIC_CACHE)
|
# elif defined(METRIC_CACHE)
|
||||||
int ind;
|
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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
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
|
#endif
|
||||||
|
|
||||||
#ifdef BIDI_SUPPORT
|
#ifdef BIDI_SUPPORT
|
||||||
|
@ -499,7 +507,6 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
|
||||||
intl_props = NULL;
|
intl_props = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
pen_x = x;
|
pen_x = x;
|
||||||
pen_y = y;
|
pen_y = y;
|
||||||
last_adv = 0;
|
last_adv = 0;
|
||||||
|
@ -532,169 +539,166 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
|
||||||
/* hmmm kerning means i can't sanely do my own cached metric tables! */
|
/* 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 */
|
/* grrr - this means font face sharing is kinda... not an option if */
|
||||||
/* you want performance */
|
/* you want performance */
|
||||||
if ((use_kerning) && (prev_index) && (index) &&
|
if ((use_kerning) && (prev_index) && (index) &&
|
||||||
(pface == fi->src->ft.face))
|
(pface == fi->src->ft.face))
|
||||||
{
|
{
|
||||||
if (evas_common_font_query_kerning(fi, prev_index, index, &kern))
|
if (evas_common_font_query_kerning(fi, prev_index, index, &kern))
|
||||||
pen_x += kern;
|
pen_x += kern;
|
||||||
}
|
}
|
||||||
pface = fi->src->ft.face;
|
pface = fi->src->ft.face;
|
||||||
LKU(fi->ft_mutex);
|
LKU(fi->ft_mutex);
|
||||||
|
|
||||||
if (dc->font_ext.func.gl_new)
|
if (dc->font_ext.func.gl_new)
|
||||||
{
|
{
|
||||||
/* extension calls */
|
/* extension calls */
|
||||||
fg->ext_dat = dc->font_ext.func.gl_new(dc->font_ext.data, fg);
|
fg->ext_dat = dc->font_ext.func.gl_new(dc->font_ext.data, fg);
|
||||||
fg->ext_dat_free = dc->font_ext.func.gl_free;
|
fg->ext_dat_free = dc->font_ext.func.gl_free;
|
||||||
}
|
}
|
||||||
/* If the current one is not a compositing char, do the previous advance
|
/* If the current one is not a compositing char, do the previous advance
|
||||||
* and set the current advance as the next advance to do */
|
* and set the current advance as the next advance to do */
|
||||||
if (fg->glyph->advance.x >> 16 > 0)
|
if (fg->glyph->advance.x >> 16 > 0)
|
||||||
{
|
{
|
||||||
pen_x += last_adv;
|
pen_x += last_adv;
|
||||||
last_adv = fg->glyph->advance.x >> 16;
|
last_adv = fg->glyph->advance.x >> 16;
|
||||||
}
|
}
|
||||||
chr_x = (pen_x + (fg->glyph_out->left));
|
chr_x = (pen_x + (fg->glyph_out->left));
|
||||||
chr_y = (pen_y + (fg->glyph_out->top));
|
chr_y = (pen_y + (fg->glyph_out->top));
|
||||||
|
|
||||||
if (chr_x < (ext_x + ext_w))
|
if (chr_x < (ext_x + ext_w))
|
||||||
{
|
{
|
||||||
DATA8 *data;
|
DATA8 *data;
|
||||||
int i, j, w, h;
|
int i, j, w, h;
|
||||||
|
|
||||||
data = fg->glyph_out->bitmap.buffer;
|
data = fg->glyph_out->bitmap.buffer;
|
||||||
j = fg->glyph_out->bitmap.pitch;
|
j = fg->glyph_out->bitmap.pitch;
|
||||||
w = fg->glyph_out->bitmap.width;
|
w = fg->glyph_out->bitmap.width;
|
||||||
if (j < w) j = w;
|
if (j < w) j = w;
|
||||||
h = fg->glyph_out->bitmap.rows;
|
h = fg->glyph_out->bitmap.rows;
|
||||||
/*
|
/*
|
||||||
if ((fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays)
|
if ((fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays)
|
||||||
&& (fg->glyph_out->bitmap.num_grays == 256)
|
&& (fg->glyph_out->bitmap.num_grays == 256)
|
||||||
)
|
)
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
if ((j > 0) && (chr_x + w > ext_x))
|
if ((j > 0) && (chr_x + w > ext_x))
|
||||||
{
|
{
|
||||||
if ((fg->ext_dat) && (dc->font_ext.func.gl_draw))
|
if ((fg->ext_dat) && (dc->font_ext.func.gl_draw))
|
||||||
{
|
{
|
||||||
/* ext glyph draw */
|
/* ext glyph draw */
|
||||||
dc->font_ext.func.gl_draw(dc->font_ext.data,
|
dc->font_ext.func.gl_draw(dc->font_ext.data,
|
||||||
(void *)dst,
|
(void *)dst,
|
||||||
dc, fg,
|
dc, fg, chr_x,
|
||||||
chr_x,
|
y - (chr_y - y));
|
||||||
y - (chr_y - y)
|
}
|
||||||
);
|
else
|
||||||
}
|
{
|
||||||
else
|
if ((fg->glyph_out->bitmap.num_grays == 256) &&
|
||||||
{
|
(fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays))
|
||||||
if ((fg->glyph_out->bitmap.num_grays == 256) &&
|
{
|
||||||
(fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays))
|
for (i = 0; i < h; i++)
|
||||||
{
|
{
|
||||||
for (i = 0; i < h; i++)
|
int dx, dy;
|
||||||
{
|
int in_x, in_w;
|
||||||
int dx, dy;
|
|
||||||
int in_x, in_w;
|
|
||||||
|
|
||||||
in_x = 0;
|
in_x = 0;
|
||||||
in_w = 0;
|
in_w = 0;
|
||||||
dx = chr_x;
|
dx = chr_x;
|
||||||
dy = y - (chr_y - i - y);
|
dy = y - (chr_y - i - y);
|
||||||
#ifdef EVAS_SLI
|
#ifdef EVAS_SLI
|
||||||
if (((dy) % dc->sli.h) == dc->sli.y)
|
if (((dy) % dc->sli.h) == dc->sli.y)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if ((dx < (ext_x + ext_w)) &&
|
if ((dx < (ext_x + ext_w)) &&
|
||||||
(dy >= (ext_y)) &&
|
(dy >= (ext_y)) &&
|
||||||
(dy < (ext_y + ext_h)))
|
(dy < (ext_y + ext_h)))
|
||||||
{
|
{
|
||||||
if (dx + w > (ext_x + ext_w))
|
if (dx + w > (ext_x + ext_w))
|
||||||
in_w += (dx + w) - (ext_x + ext_w);
|
in_w += (dx + w) - (ext_x + ext_w);
|
||||||
if (dx < ext_x)
|
if (dx < ext_x)
|
||||||
{
|
{
|
||||||
in_w += ext_x - dx;
|
in_w += ext_x - dx;
|
||||||
in_x = ext_x - dx;
|
in_x = ext_x - dx;
|
||||||
dx = ext_x;
|
dx = ext_x;
|
||||||
}
|
}
|
||||||
if (in_w < w)
|
if (in_w < w)
|
||||||
{
|
{
|
||||||
func(NULL, data + (i * j) + in_x, dc->col.col,
|
func(NULL, data + (i * j) + in_x, dc->col.col,
|
||||||
im + (dy * im_w) + dx, w - in_w);
|
im + (dy * im_w) + dx, w - in_w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DATA8 *tmpbuf = NULL, *dp, *tp, bits;
|
DATA8 *tmpbuf = NULL, *dp, *tp, bits;
|
||||||
int bi, bj;
|
int bi, bj;
|
||||||
const DATA8 bitrepl[2] = {0x0, 0xff};
|
const DATA8 bitrepl[2] = {0x0, 0xff};
|
||||||
|
|
||||||
tmpbuf = alloca(w);
|
tmpbuf = alloca(w);
|
||||||
for (i = 0; i < h; i++)
|
for (i = 0; i < h; i++)
|
||||||
{
|
{
|
||||||
int dx, dy;
|
int dx, dy;
|
||||||
int in_x, in_w, end;
|
int in_x, in_w, end;
|
||||||
|
|
||||||
in_x = 0;
|
in_x = 0;
|
||||||
in_w = 0;
|
in_w = 0;
|
||||||
dx = chr_x;
|
dx = chr_x;
|
||||||
dy = y - (chr_y - i - y);
|
dy = y - (chr_y - i - y);
|
||||||
#ifdef EVAS_SLI
|
#ifdef EVAS_SLI
|
||||||
if (((dy) % dc->sli.h) == dc->sli.y)
|
if (((dy) % dc->sli.h) == dc->sli.y)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
tp = tmpbuf;
|
tp = tmpbuf;
|
||||||
dp = data + (i * fg->glyph_out->bitmap.pitch);
|
dp = data + (i * fg->glyph_out->bitmap.pitch);
|
||||||
for (bi = 0; bi < w; bi += 8)
|
for (bi = 0; bi < w; bi += 8)
|
||||||
{
|
{
|
||||||
bits = *dp;
|
bits = *dp;
|
||||||
if ((w - bi) < 8) end = w - bi;
|
if ((w - bi) < 8) end = w - bi;
|
||||||
else end = 8;
|
else end = 8;
|
||||||
for (bj = 0; bj < end; bj++)
|
for (bj = 0; bj < end; bj++)
|
||||||
{
|
{
|
||||||
*tp = bitrepl[(bits >> (7 - bj)) & 0x1];
|
*tp = bitrepl[(bits >> (7 - bj)) & 0x1];
|
||||||
tp++;
|
tp++;
|
||||||
}
|
}
|
||||||
dp++;
|
dp++;
|
||||||
}
|
}
|
||||||
if ((dx < (ext_x + ext_w)) &&
|
if ((dx < (ext_x + ext_w)) &&
|
||||||
(dy >= (ext_y)) &&
|
(dy >= (ext_y)) &&
|
||||||
(dy < (ext_y + ext_h)))
|
(dy < (ext_y + ext_h)))
|
||||||
{
|
{
|
||||||
if (dx + w > (ext_x + ext_w))
|
if (dx + w > (ext_x + ext_w))
|
||||||
in_w += (dx + w) - (ext_x + ext_w);
|
in_w += (dx + w) - (ext_x + ext_w);
|
||||||
if (dx < ext_x)
|
if (dx < ext_x)
|
||||||
{
|
{
|
||||||
in_w += ext_x - dx;
|
in_w += ext_x - dx;
|
||||||
in_x = ext_x - dx;
|
in_x = ext_x - dx;
|
||||||
dx = ext_x;
|
dx = ext_x;
|
||||||
}
|
}
|
||||||
if (in_w < w)
|
if (in_w < w)
|
||||||
{
|
{
|
||||||
func(NULL, tmpbuf + in_x, dc->col.col,
|
func(NULL, tmpbuf + in_x, dc->col.col,
|
||||||
im + (dy * im_w) + dx, w - in_w);
|
im + (dy * im_w) + dx, w - in_w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
|
||||||
prev_index = index;
|
prev_index = index;
|
||||||
}
|
}
|
||||||
#ifdef BIDI_SUPPORT
|
#ifdef BIDI_SUPPORT
|
||||||
if (visual_text) free(visual_text);
|
if (visual_text) free(visual_text);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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,
|
||||||
const Evas_BiDi_Props *intl_props)
|
const Evas_BiDi_Props *intl_props)
|
||||||
|
@ -706,8 +710,8 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int
|
||||||
RGBA_Font_Int *fi;
|
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;
|
fi = fn->fonts->data;
|
||||||
|
|
||||||
|
@ -750,8 +754,7 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int
|
||||||
{
|
{
|
||||||
evas_common_font_draw_internal(dst, dc, fn, x, y, text, intl_props,
|
evas_common_font_draw_internal(dst, dc, fn, x, y, text, intl_props,
|
||||||
func, ext_x, ext_y, ext_w, ext_h, fi,
|
func, ext_x, ext_y, ext_w, ext_h, fi,
|
||||||
im_w, im_h, use_kerning
|
im_w, im_h, use_kerning);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -767,8 +770,7 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int
|
||||||
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, intl_props,
|
evas_common_font_draw_internal(dst, dc, fn, x, y, text, intl_props,
|
||||||
func, r->x, r->y, r->w, r->h, fi,
|
func, r->x, r->y, r->w, r->h, fi,
|
||||||
im_w, im_h, use_kerning
|
im_w, im_h, use_kerning);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
evas_common_draw_context_apply_clear_cutouts(rects);
|
evas_common_draw_context_apply_clear_cutouts(rects);
|
||||||
}
|
}
|
||||||
|
@ -779,12 +781,12 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* FIXME: Where is it freed at? */
|
/* 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 *
|
struct prword *
|
||||||
evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *in_text, Evas_BiDi_Props *intl_props, int len, RGBA_Font *fn, RGBA_Font_Int *fi,int use_kerning){
|
evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *in_text, Evas_BiDi_Props *intl_props, int len, RGBA_Font *fn, RGBA_Font_Int *fi,int use_kerning)
|
||||||
|
{
|
||||||
int pen_x, pen_y;
|
int pen_x, pen_y;
|
||||||
struct cinfo *metrics;
|
struct cinfo *metrics;
|
||||||
const Eina_Unicode *text = in_text;
|
const Eina_Unicode *text = in_text;
|
||||||
|
@ -805,16 +807,16 @@ evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *in_text, Eva
|
||||||
if (gl) return NULL;
|
if (gl) return NULL;
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
|
||||||
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 (w->len == len && w->font == fn && fi->size == w->size &&
|
||||||
(w->str == in_text || memcmp(w->str, in_text, len * sizeof(Eina_Unicode)) == 0)){
|
(w->str == in_text || memcmp(w->str, in_text, len * sizeof(Eina_Unicode)) == 0)){
|
||||||
words = eina_inlist_promote(words, EINA_INLIST_GET(w));
|
words = eina_inlist_promote(words, EINA_INLIST_GET(w));
|
||||||
LKU(lock_words);
|
LKU(lock_words);
|
||||||
return w;
|
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;
|
||||||
|
@ -822,8 +824,10 @@ evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *in_text, Eva
|
||||||
pen_x = pen_y = 0;
|
pen_x = pen_y = 0;
|
||||||
above = 0; below = 0; baseline = 0; height = 0; descent = 0;
|
above = 0; below = 0; baseline = 0; height = 0; descent = 0;
|
||||||
metrics = malloc(sizeof(struct cinfo) * len);
|
metrics = malloc(sizeof(struct cinfo) * len);
|
||||||
|
|
||||||
/* First pass: Work out how big */
|
/* First pass: Work out how big */
|
||||||
for (char_index = 0, c = 0, chr = 0 ; *text ; text++, char_index ++){
|
for (char_index = 0, c = 0, chr = 0 ; *text ; text++, char_index ++)
|
||||||
|
{
|
||||||
struct cinfo *ci = metrics + char_index;
|
struct cinfo *ci = metrics + char_index;
|
||||||
ci->gl = *text;
|
ci->gl = *text;
|
||||||
ci->index = evas_common_font_glyph_search(fn, &fi, ci->gl);
|
ci->index = evas_common_font_glyph_search(fn, &fi, ci->gl);
|
||||||
|
@ -843,75 +847,79 @@ evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *in_text, Eva
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((use_kerning) && (prev_index) && (ci->index) &&
|
if ((use_kerning) && (prev_index) && (ci->index) &&
|
||||||
(pface == fi->src->ft.face))
|
(pface == fi->src->ft.face))
|
||||||
{
|
{
|
||||||
int kern = 0;
|
int kern = 0;
|
||||||
# ifdef BIDI_SUPPORT
|
# ifdef BIDI_SUPPORT
|
||||||
/* if it's rtl, the kerning matching should be reversed, i.e prev
|
/* if it's rtl, the kerning matching should be reversed, i.e prev
|
||||||
* index is now the index and the other way around.
|
* index is now the index and the other way around.
|
||||||
* There is a slight exception when there are compositing chars
|
* There is a slight exception when there are compositing chars
|
||||||
* involved.*/
|
* involved.*/
|
||||||
if (intl_props && intl_props->props &&
|
if (intl_props && intl_props->props &&
|
||||||
evas_bidi_is_rtl_char(intl_props, char_index) &&
|
evas_bidi_is_rtl_char(intl_props, char_index) &&
|
||||||
ci->fg->glyph->advance.x >> 16 > 0)
|
ci->fg->glyph->advance.x >> 16 > 0)
|
||||||
{
|
{
|
||||||
if (evas_common_font_query_kerning(fi, ci->index, prev_index, &kern))
|
if (evas_common_font_query_kerning(fi, ci->index, prev_index, &kern))
|
||||||
pen_x += kern;
|
pen_x += kern;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (evas_common_font_query_kerning(fi, prev_index, ci->index, &kern))
|
if (evas_common_font_query_kerning(fi, prev_index, ci->index, &kern))
|
||||||
pen_x += kern;
|
pen_x += kern;
|
||||||
}
|
}
|
||||||
# else
|
# else
|
||||||
if (evas_common_font_query_kerning(fi, prev_index, ci->index, &kern))
|
if (evas_common_font_query_kerning(fi, prev_index, ci->index, &kern))
|
||||||
pen_x += kern;
|
pen_x += kern;
|
||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
pface = fi->src->ft.face;
|
|
||||||
|
|
||||||
LKU(fi->ft_mutex);
|
pface = fi->src->ft.face;
|
||||||
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 = pen_x + ci->fg->glyph_out->left;
|
|
||||||
ci->pos.y = pen_y + ci->fg->glyph_out->top;
|
|
||||||
pen_x += ci->fg->glyph->advance.x >> 16;
|
|
||||||
prev_index = ci->index;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* First loop done */
|
|
||||||
width = pen_x;
|
|
||||||
width = (width & 0x7) ? width + (8 - (width & 0x7)) : width;
|
|
||||||
|
|
||||||
height = baseline + descent;
|
|
||||||
if (!gl){
|
|
||||||
im = calloc(height, width);
|
|
||||||
for (i = 0 ; i < char_index ; i ++){
|
|
||||||
struct cinfo *ci = metrics + i;
|
|
||||||
for (j = 0 ; j < ci->bm.rows ; j ++){
|
|
||||||
memcpy(im + ci->pos.x + (j + baseline - ci->bm.h) * width, ci->bm.data + j * ci->bm.w, ci->bm.w);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
LKU(fi->ft_mutex);
|
||||||
|
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 = pen_x + ci->fg->glyph_out->left;
|
||||||
|
ci->pos.y = pen_y + ci->fg->glyph_out->top;
|
||||||
|
pen_x += ci->fg->glyph->advance.x >> 16;
|
||||||
|
prev_index = ci->index;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
im = NULL;
|
/* First loop done */
|
||||||
}
|
width = pen_x;
|
||||||
|
width = (width & 0x7) ? width + (8 - (width & 0x7)) : width;
|
||||||
|
|
||||||
|
height = baseline + descent;
|
||||||
|
if (!gl)
|
||||||
|
{
|
||||||
|
im = calloc(height, width);
|
||||||
|
for (i = 0 ; i < char_index ; i ++)
|
||||||
|
{
|
||||||
|
struct cinfo *ci = metrics + i;
|
||||||
|
|
||||||
|
for (j = 0 ; j < ci->bm.rows ; j ++)
|
||||||
|
memcpy(im + ci->pos.x + (j + baseline - ci->bm.h) * width, ci->bm.data + j * ci->bm.w, ci->bm.w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
im = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Save it */
|
/* Save it */
|
||||||
struct prword *save;
|
struct prword *save;
|
||||||
|
|
||||||
|
|
||||||
save = malloc(sizeof(struct prword));
|
save = malloc(sizeof(struct prword));
|
||||||
save->cinfo = metrics;
|
save->cinfo = metrics;
|
||||||
save->str = eina_ustringshare_add(in_text);
|
save->str = eina_ustringshare_add(in_text);
|
||||||
|
@ -927,19 +935,21 @@ evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *in_text, Eva
|
||||||
words = eina_inlist_prepend(words, EINA_INLIST_GET(save));
|
words = eina_inlist_prepend(words, EINA_INLIST_GET(save));
|
||||||
|
|
||||||
/* Clean up if too long */
|
/* Clean up if too long */
|
||||||
if (eina_inlist_count(words) > max_cached_words){
|
if (eina_inlist_count(words) > max_cached_words)
|
||||||
|
{
|
||||||
struct prword *last = (struct prword *)(words->last);
|
struct prword *last = (struct prword *)(words->last);
|
||||||
if (last->im) free(last->im);
|
|
||||||
if (last->cinfo) free(last->cinfo);
|
if (last)
|
||||||
eina_ustringshare_del(last->str);
|
{
|
||||||
words = eina_inlist_remove(words,EINA_INLIST_GET(last));
|
if (last->im) free(last->im);
|
||||||
free(last);
|
if (last->cinfo) free(last->cinfo);
|
||||||
}
|
eina_ustringshare_del(last->str);
|
||||||
|
words = eina_inlist_remove(words, EINA_INLIST_GET(last));
|
||||||
|
free(last);
|
||||||
|
}
|
||||||
|
}
|
||||||
LKU(lock_words);
|
LKU(lock_words);
|
||||||
|
|
||||||
return save;
|
return save;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue