2002-11-08 00:02:15 -08:00
|
|
|
#include "evas_common.h"
|
2009-09-21 09:08:51 -07:00
|
|
|
#include "evas_private.h"
|
2008-07-21 09:10:48 -07:00
|
|
|
#include "evas_blend_private.h"
|
2002-11-08 00:02:15 -08:00
|
|
|
|
2011-01-30 02:35:37 -08:00
|
|
|
#include "language/evas_bidi_utils.h" /*defines BIDI_SUPPORT if possible */
|
2010-05-21 00:10:45 -07:00
|
|
|
#include "evas_font_private.h" /* for Frame-Queuing support */
|
2009-04-11 06:11:10 -07:00
|
|
|
|
2011-01-30 02:36:39 -08:00
|
|
|
#include "evas_font_ot.h"
|
|
|
|
|
2011-04-12 02:05:47 -07:00
|
|
|
#include FT_OUTLINE_H
|
|
|
|
|
2011-01-30 02:33:14 -08:00
|
|
|
#define WORD_CACHE_MAXLEN 50
|
2010-06-13 22:59:23 -07:00
|
|
|
/* How many to cache */
|
2010-10-07 14:07:53 -07:00
|
|
|
#define WORD_CACHE_NWORDS 40
|
2011-04-12 02:05:47 -07:00
|
|
|
|
2010-07-04 23:40:20 -07:00
|
|
|
static int max_cached_words = WORD_CACHE_NWORDS;
|
2010-06-13 22:59:23 -07:00
|
|
|
|
2010-10-07 14:07:53 -07:00
|
|
|
struct prword
|
|
|
|
{
|
|
|
|
EINA_INLIST;
|
|
|
|
/* FIXME: Need to save font/size et al */
|
|
|
|
int size;
|
|
|
|
struct cinfo *cinfo;
|
|
|
|
RGBA_Font *font;
|
|
|
|
const Eina_Unicode *str;
|
|
|
|
int len;
|
|
|
|
DATA8 *im;
|
|
|
|
int roww;
|
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
int baseline;
|
2010-06-13 22:59:23 -07:00
|
|
|
};
|
|
|
|
|
2010-10-07 14:07:53 -07:00
|
|
|
struct cinfo
|
|
|
|
{
|
|
|
|
FT_UInt index;
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
} pos;
|
|
|
|
int posx;
|
|
|
|
RGBA_Font_Glyph *fg;
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
int w,h;
|
|
|
|
int rows;
|
|
|
|
unsigned char *data;
|
|
|
|
} bm;
|
2010-06-13 22:59:23 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2010-08-16 03:46:56 -07:00
|
|
|
#if defined(METRIC_CACHE) || defined(WORD_CACHE)
|
2010-07-20 05:11:49 -07:00
|
|
|
LK(lock_words); // for word cache call
|
2010-06-13 22:59:23 -07:00
|
|
|
static Eina_Inlist *words = NULL;
|
2011-03-30 08:55:10 -07:00
|
|
|
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);
|
2010-08-16 03:46:56 -07:00
|
|
|
#endif
|
2010-06-13 22:59:23 -07:00
|
|
|
|
2010-05-21 00:10:45 -07:00
|
|
|
EAPI void
|
|
|
|
evas_common_font_draw_init(void)
|
|
|
|
{
|
2010-07-04 23:40:20 -07:00
|
|
|
char *p;
|
|
|
|
int tmp;
|
2010-10-07 14:07:53 -07:00
|
|
|
|
2010-07-04 23:40:20 -07:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2010-05-21 00:10:45 -07:00
|
|
|
}
|
|
|
|
|
2010-07-04 23:40:20 -07:00
|
|
|
#ifdef EVAS_FRAME_QUEUING
|
2010-05-21 00:10:45 -07:00
|
|
|
EAPI void
|
|
|
|
evas_common_font_draw_finish(void)
|
2010-08-29 20:21:15 -07:00
|
|
|
{
|
2010-05-21 00:10:45 -07:00
|
|
|
}
|
|
|
|
#endif
|
2009-04-11 06:11:10 -07:00
|
|
|
|
2010-02-03 03:18:00 -08:00
|
|
|
static void
|
2010-10-29 05:55:42 -07:00
|
|
|
_fash_int2_free(Fash_Int_Map2 *fash)
|
2010-02-03 03:18:00 -08:00
|
|
|
{
|
|
|
|
int i;
|
2010-10-07 14:07:53 -07:00
|
|
|
|
2010-02-03 03:18:00 -08:00
|
|
|
for (i = 0; i < 256; i++) if (fash->bucket[i]) free(fash->bucket[i]);
|
|
|
|
free(fash);
|
|
|
|
}
|
|
|
|
|
2010-10-29 05:55:42 -07:00
|
|
|
static void
|
|
|
|
_fash_int_free(Fash_Int *fash)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_int2_free(fash->bucket[i]);
|
|
|
|
free(fash);
|
|
|
|
}
|
|
|
|
|
2010-02-03 03:18:00 -08:00
|
|
|
static Fash_Int *
|
|
|
|
_fash_int_new(void)
|
|
|
|
{
|
|
|
|
Fash_Int *fash = calloc(1, sizeof(Fash_Int));
|
|
|
|
fash->freeme = _fash_int_free;
|
|
|
|
return fash;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Fash_Item_Index_Map *
|
|
|
|
_fash_int_find(Fash_Int *fash, int item)
|
|
|
|
{
|
2010-10-29 05:55:42 -07:00
|
|
|
int grp, maj, min;
|
2010-02-03 03:18:00 -08:00
|
|
|
|
2010-11-01 21:56:57 -07:00
|
|
|
// 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
|
2010-10-29 05:55:42 -07:00
|
|
|
grp = (item >> 16) & 0xff;
|
2010-02-03 03:18:00 -08:00
|
|
|
maj = (item >> 8) & 0xff;
|
|
|
|
min = item & 0xff;
|
2010-10-29 05:55:42 -07:00
|
|
|
if (!fash->bucket[grp]) return NULL;
|
|
|
|
if (!fash->bucket[grp]->bucket[maj]) return NULL;
|
|
|
|
return &(fash->bucket[grp]->bucket[maj]->item[min]);
|
2010-02-03 03:18:00 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_fash_int_add(Fash_Int *fash, int item, RGBA_Font_Int *fint, int index)
|
|
|
|
{
|
2010-10-29 05:55:42 -07:00
|
|
|
int grp, maj, min;
|
2010-10-07 14:07:53 -07:00
|
|
|
|
2010-11-01 21:56:57 -07:00
|
|
|
// 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
|
2010-10-29 05:55:42 -07:00
|
|
|
grp = (item >> 16) & 0xff;
|
2010-02-03 03:18:00 -08:00
|
|
|
maj = (item >> 8) & 0xff;
|
|
|
|
min = item & 0xff;
|
2010-10-29 05:55:42 -07:00
|
|
|
if (!fash->bucket[grp])
|
|
|
|
fash->bucket[grp] = calloc(1, sizeof(Fash_Int_Map2));
|
2011-01-13 22:35:41 -08:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]);
|
2010-10-29 05:55:42 -07:00
|
|
|
if (!fash->bucket[grp]->bucket[maj])
|
|
|
|
fash->bucket[grp]->bucket[maj] = calloc(1, sizeof(Fash_Int_Map));
|
2011-01-13 22:35:41 -08:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]->bucket[maj]);
|
2010-10-29 05:55:42 -07:00
|
|
|
fash->bucket[grp]->bucket[maj]->item[min].fint = fint;
|
|
|
|
fash->bucket[grp]->bucket[maj]->item[min].index = index;
|
2010-02-03 03:18:00 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2010-10-29 05:55:42 -07:00
|
|
|
_fash_gl2_free(Fash_Glyph_Map2 *fash)
|
2010-02-03 03:18:00 -08:00
|
|
|
{
|
|
|
|
int i;
|
2010-10-07 14:07:53 -07:00
|
|
|
|
2010-02-03 03:18:00 -08:00
|
|
|
for (i = 0; i < 256; i++) if (fash->bucket[i]) free(fash->bucket[i]);
|
|
|
|
free(fash);
|
|
|
|
}
|
|
|
|
|
2010-10-29 05:55:42 -07:00
|
|
|
static void
|
|
|
|
_fash_gl_free(Fash_Glyph *fash)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_gl2_free(fash->bucket[i]);
|
|
|
|
free(fash);
|
|
|
|
}
|
|
|
|
|
2010-02-03 03:18:00 -08:00
|
|
|
static Fash_Glyph *
|
|
|
|
_fash_gl_new(void)
|
|
|
|
{
|
|
|
|
Fash_Glyph *fash = calloc(1, sizeof(Fash_Glyph));
|
|
|
|
fash->freeme = _fash_gl_free;
|
|
|
|
return fash;
|
|
|
|
}
|
|
|
|
|
|
|
|
static RGBA_Font_Glyph *
|
|
|
|
_fash_gl_find(Fash_Glyph *fash, int item)
|
|
|
|
{
|
2010-10-29 05:55:42 -07:00
|
|
|
int grp, maj, min;
|
2010-02-03 03:18:00 -08:00
|
|
|
|
2010-11-01 21:56:57 -07:00
|
|
|
// 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
|
2010-10-29 05:55:42 -07:00
|
|
|
grp = (item >> 16) & 0xff;
|
2010-02-03 03:18:00 -08:00
|
|
|
maj = (item >> 8) & 0xff;
|
|
|
|
min = item & 0xff;
|
2010-10-29 05:55:42 -07:00
|
|
|
if (!fash->bucket[grp]) return NULL;
|
|
|
|
if (!fash->bucket[grp]->bucket[maj]) return NULL;
|
|
|
|
return fash->bucket[grp]->bucket[maj]->item[min];
|
2010-02-03 03:18:00 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_fash_gl_add(Fash_Glyph *fash, int item, RGBA_Font_Glyph *glyph)
|
|
|
|
{
|
2010-10-29 05:55:42 -07:00
|
|
|
int grp, maj, min;
|
2010-10-07 14:07:53 -07:00
|
|
|
|
2010-11-01 21:56:57 -07:00
|
|
|
// 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
|
2010-10-29 05:55:42 -07:00
|
|
|
grp = (item >> 16) & 0xff;
|
2010-02-03 03:18:00 -08:00
|
|
|
maj = (item >> 8) & 0xff;
|
|
|
|
min = item & 0xff;
|
2010-10-29 05:55:42 -07:00
|
|
|
if (!fash->bucket[grp])
|
|
|
|
fash->bucket[grp] = calloc(1, sizeof(Fash_Glyph_Map2));
|
2011-01-13 22:35:41 -08:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]);
|
2010-10-29 05:55:42 -07:00
|
|
|
if (!fash->bucket[grp]->bucket[maj])
|
|
|
|
fash->bucket[grp]->bucket[maj] = calloc(1, sizeof(Fash_Glyph_Map));
|
2011-01-13 22:28:40 -08:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]->bucket[maj]);
|
2010-10-29 05:55:42 -07:00
|
|
|
fash->bucket[grp]->bucket[maj]->item[min] = glyph;
|
2010-02-03 03:18:00 -08:00
|
|
|
}
|
|
|
|
|
2006-09-06 00:33:40 -07:00
|
|
|
EAPI RGBA_Font_Glyph *
|
2005-03-20 07:57:55 -08:00
|
|
|
evas_common_font_int_cache_glyph_get(RGBA_Font_Int *fi, FT_UInt index)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
|
|
|
RGBA_Font_Glyph *fg;
|
2006-02-28 19:48:03 -08:00
|
|
|
FT_UInt hindex;
|
2002-11-08 00:02:15 -08:00
|
|
|
FT_Error error;
|
2010-10-29 05:55:42 -07:00
|
|
|
int size;
|
2006-02-28 19:48:03 -08:00
|
|
|
const FT_Int32 hintflags[3] =
|
|
|
|
{ FT_LOAD_NO_HINTING, FT_LOAD_FORCE_AUTOHINT, FT_LOAD_NO_AUTOHINT };
|
2011-04-12 02:05:47 -07:00
|
|
|
static FT_Matrix transform = {0x10000, 0x05000, 0x0000, 0x10000}; // about 12 degree.
|
2008-07-10 11:08:18 -07:00
|
|
|
|
2010-10-29 05:55:42 -07:00
|
|
|
evas_common_font_int_promote(fi);
|
2010-02-03 03:18:00 -08:00
|
|
|
if (fi->fash)
|
|
|
|
{
|
|
|
|
fg = _fash_gl_find(fi->fash, index);
|
|
|
|
if (fg == (void *)(-1)) return NULL;
|
|
|
|
else if (fg) return fg;
|
|
|
|
}
|
2010-10-07 14:07:53 -07:00
|
|
|
|
2006-02-28 19:48:03 -08:00
|
|
|
hindex = index + (fi->hinting * 500000000);
|
2010-10-07 14:07:53 -07:00
|
|
|
|
2010-02-03 03:18:00 -08:00
|
|
|
// fg = eina_hash_find(fi->glyphs, &hindex);
|
|
|
|
// if (fg) return fg;
|
2008-07-10 11:08:18 -07:00
|
|
|
|
2010-10-29 05:55:42 -07:00
|
|
|
evas_common_font_int_reload(fi);
|
2010-05-21 00:10:45 -07:00
|
|
|
FTLOCK();
|
2006-02-28 19:48:03 -08:00
|
|
|
error = FT_Load_Glyph(fi->src->ft.face, index,
|
2011-04-12 02:05:47 -07:00
|
|
|
FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP |
|
|
|
|
hintflags[fi->hinting]);
|
2010-05-21 00:10:45 -07:00
|
|
|
FTUNLOCK();
|
2010-02-03 03:18:00 -08:00
|
|
|
if (error)
|
|
|
|
{
|
|
|
|
if (!fi->fash) fi->fash = _fash_gl_new();
|
|
|
|
if (fi->fash) _fash_gl_add(fi->fash, index, (void *)(-1));
|
|
|
|
return NULL;
|
|
|
|
}
|
2005-05-21 19:49:50 -07:00
|
|
|
|
2011-04-12 02:05:47 -07:00
|
|
|
/* Transform the outline of Glyph according to runtime_rend. */
|
|
|
|
if (fi->runtime_rend & FONT_REND_ITALIC)
|
|
|
|
FT_Outline_Transform(&fi->src->ft.face->glyph->outline, &transform);
|
|
|
|
/* Embolden the outline of Glyph according to rundtime_rend. */
|
|
|
|
if (fi->runtime_rend & FONT_REND_BOLD)
|
|
|
|
FT_Outline_Embolden(&fi->src->ft.face->glyph->outline,
|
|
|
|
(fi->src->ft.face->size->metrics.x_ppem * 5 * 64) / 100);
|
|
|
|
|
2002-11-08 00:02:15 -08:00
|
|
|
fg = malloc(sizeof(struct _RGBA_Font_Glyph));
|
|
|
|
if (!fg) return NULL;
|
|
|
|
memset(fg, 0, (sizeof(struct _RGBA_Font_Glyph)));
|
2005-05-21 19:49:50 -07:00
|
|
|
|
2010-05-21 00:10:45 -07:00
|
|
|
FTLOCK();
|
2005-03-20 07:57:55 -08:00
|
|
|
error = FT_Get_Glyph(fi->src->ft.face->glyph, &(fg->glyph));
|
2010-05-21 00:10:45 -07:00
|
|
|
FTUNLOCK();
|
2005-05-21 19:49:50 -07:00
|
|
|
if (error)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
|
|
|
free(fg);
|
2010-02-03 03:18:00 -08:00
|
|
|
if (!fi->fash) fi->fash = _fash_gl_new();
|
|
|
|
if (fi->fash) _fash_gl_add(fi->fash, index, (void *)(-1));
|
2002-11-08 00:02:15 -08:00
|
|
|
return NULL;
|
|
|
|
}
|
2007-08-25 04:54:17 -07:00
|
|
|
if (fg->glyph->format != FT_GLYPH_FORMAT_BITMAP)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2010-05-21 00:10:45 -07:00
|
|
|
FTLOCK();
|
2007-08-26 01:21:57 -07:00
|
|
|
error = FT_Glyph_To_Bitmap(&(fg->glyph), FT_RENDER_MODE_NORMAL, 0, 1);
|
2005-05-21 19:49:50 -07:00
|
|
|
if (error)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
|
|
|
FT_Done_Glyph(fg->glyph);
|
2010-10-07 14:07:53 -07:00
|
|
|
FTUNLOCK();
|
2002-11-08 00:02:15 -08:00
|
|
|
free(fg);
|
2010-02-03 03:18:00 -08:00
|
|
|
if (!fi->fash) fi->fash = _fash_gl_new();
|
|
|
|
if (fi->fash) _fash_gl_add(fi->fash, index, (void *)(-1));
|
2002-11-08 00:02:15 -08:00
|
|
|
return NULL;
|
|
|
|
}
|
2010-10-07 14:07:53 -07:00
|
|
|
FTUNLOCK();
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
|
|
|
fg->glyph_out = (FT_BitmapGlyph)fg->glyph;
|
2009-06-18 05:14:29 -07:00
|
|
|
fg->index = hindex;
|
2009-10-09 05:10:27 -07:00
|
|
|
fg->fi = fi;
|
2010-10-07 14:07:53 -07:00
|
|
|
|
2010-02-03 03:18:00 -08:00
|
|
|
if (!fi->fash) fi->fash = _fash_gl_new();
|
|
|
|
if (fi->fash) _fash_gl_add(fi->fash, index, fg);
|
2011-03-20 01:51:41 -07:00
|
|
|
/* This '+ 200' is just an estimation of how much memory freetype will use
|
|
|
|
* on it's size. This value is not really used anywhere in code - it's
|
|
|
|
* only for statistics. */
|
2010-10-29 05:55:42 -07:00
|
|
|
size = sizeof(RGBA_Font_Glyph) + sizeof(Eina_List) +
|
|
|
|
(fg->glyph_out->bitmap.width * fg->glyph_out->bitmap.rows) + 200;
|
|
|
|
fi->usage += size;
|
|
|
|
if (fi->inuse) evas_common_font_int_use_increase(size);
|
2010-10-07 14:07:53 -07:00
|
|
|
|
2010-02-03 03:18:00 -08:00
|
|
|
// eina_hash_direct_add(fi->glyphs, &fg->index, fg);
|
2002-11-08 00:02:15 -08:00
|
|
|
return fg;
|
|
|
|
}
|
|
|
|
|
2009-02-10 07:53:17 -08:00
|
|
|
typedef struct _Font_Char_Index Font_Char_Index;
|
|
|
|
struct _Font_Char_Index
|
|
|
|
{
|
|
|
|
FT_UInt index;
|
|
|
|
int gl;
|
|
|
|
};
|
|
|
|
|
|
|
|
static FT_UInt
|
|
|
|
_evas_common_get_char_index(RGBA_Font_Int* fi, int gl)
|
|
|
|
{
|
2010-02-03 03:18:00 -08:00
|
|
|
Font_Char_Index result;
|
2010-06-13 22:59:23 -07:00
|
|
|
//FT_UInt ret;
|
2009-02-10 07:53:17 -08:00
|
|
|
|
|
|
|
#ifdef HAVE_PTHREAD
|
2010-02-03 03:18:00 -08:00
|
|
|
/// pthread_mutex_lock(&fi->ft_mutex);
|
2009-02-10 07:53:17 -08:00
|
|
|
#endif
|
|
|
|
|
2010-02-03 03:18:00 -08:00
|
|
|
// result = eina_hash_find(fi->indexes, &gl);
|
|
|
|
// if (result) goto on_correct;
|
|
|
|
//
|
|
|
|
// result = malloc(sizeof (Font_Char_Index));
|
|
|
|
// if (!result)
|
|
|
|
// {
|
|
|
|
//#ifdef HAVE_PTHREAD
|
|
|
|
// pthread_mutex_unlock(&fi->ft_mutex);
|
|
|
|
//#endif
|
|
|
|
// return FT_Get_Char_Index(fi->src->ft.face, gl);
|
|
|
|
// }
|
|
|
|
|
2010-10-29 05:55:42 -07:00
|
|
|
evas_common_font_int_reload(fi);
|
2010-05-21 00:10:45 -07:00
|
|
|
FTLOCK();
|
2010-02-03 03:18:00 -08:00
|
|
|
result.index = FT_Get_Char_Index(fi->src->ft.face, gl);
|
2010-05-21 00:10:45 -07:00
|
|
|
FTUNLOCK();
|
2010-02-03 03:18:00 -08:00
|
|
|
result.gl = gl;
|
|
|
|
|
|
|
|
// eina_hash_direct_add(fi->indexes, &result->gl, result);
|
|
|
|
//
|
|
|
|
// on_correct:
|
2009-02-10 07:53:17 -08:00
|
|
|
#ifdef HAVE_PTHREAD
|
2010-02-03 03:18:00 -08:00
|
|
|
// pthread_mutex_unlock(&fi->ft_mutex);
|
2009-02-10 07:53:17 -08:00
|
|
|
#endif
|
2010-02-03 03:18:00 -08:00
|
|
|
return result.index;
|
2009-02-10 07:53:17 -08:00
|
|
|
}
|
|
|
|
|
2006-09-06 00:33:40 -07:00
|
|
|
EAPI int
|
2005-03-20 07:57:55 -08:00
|
|
|
evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, int gl)
|
|
|
|
{
|
2008-10-21 09:31:05 -07:00
|
|
|
Eina_List *l;
|
2005-05-21 19:49:50 -07:00
|
|
|
|
2010-02-03 03:18:00 -08:00
|
|
|
if (fn->fash)
|
|
|
|
{
|
|
|
|
Fash_Item_Index_Map *fm = _fash_int_find(fn->fash, gl);
|
|
|
|
if (fm)
|
|
|
|
{
|
|
|
|
if (fm->fint)
|
|
|
|
{
|
|
|
|
*fi_ret = fm->fint;
|
|
|
|
return fm->index;
|
|
|
|
}
|
|
|
|
else if (fm->index == -1) return 0;
|
|
|
|
}
|
|
|
|
}
|
2010-10-07 14:07:53 -07:00
|
|
|
|
2005-03-20 07:57:55 -08:00
|
|
|
for (l = fn->fonts; l; l = l->next)
|
|
|
|
{
|
|
|
|
RGBA_Font_Int *fi;
|
|
|
|
int index;
|
2008-07-10 11:08:18 -07:00
|
|
|
|
2005-03-20 07:57:55 -08:00
|
|
|
fi = l->data;
|
2006-04-22 04:08:01 -07:00
|
|
|
|
2009-06-17 03:01:52 -07:00
|
|
|
#if 0 /* FIXME: charmap user is disabled and use a deprecated data type. */
|
2010-02-03 03:18:00 -08:00
|
|
|
/*
|
|
|
|
if (fi->src->charmap) // Charmap loaded, FI/FS blank
|
2006-04-08 17:02:47 -07:00
|
|
|
{
|
2008-07-10 11:08:18 -07:00
|
|
|
index = evas_array_hash_search(fi->src->charmap, gl);
|
2006-04-22 04:08:01 -07:00
|
|
|
if (index != 0)
|
|
|
|
{
|
|
|
|
evas_common_font_source_load_complete(fi->src);
|
|
|
|
evas_common_font_int_load_complete(fi);
|
|
|
|
|
2008-07-10 11:12:45 -07:00
|
|
|
evas_array_hash_free(fi->src->charmap);
|
2006-04-22 04:08:01 -07:00
|
|
|
fi->src->charmap = NULL;
|
|
|
|
|
|
|
|
*fi_ret = fi;
|
2008-07-10 11:08:18 -07:00
|
|
|
return index;
|
2010-10-07 14:07:53 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2010-02-03 03:18:00 -08:00
|
|
|
*/
|
2009-06-17 03:01:52 -07:00
|
|
|
#endif
|
2010-02-03 03:18:00 -08:00
|
|
|
if (!fi->src->ft.face) /* Charmap not loaded, FI/FS blank */
|
2006-04-22 04:08:01 -07:00
|
|
|
{
|
2010-10-29 05:55:42 -07:00
|
|
|
evas_common_font_int_reload(fi);
|
2006-04-08 17:02:47 -07:00
|
|
|
}
|
2010-11-11 05:07:04 -08:00
|
|
|
if (fi->src->ft.face)
|
2005-03-20 07:57:55 -08:00
|
|
|
{
|
2009-02-10 07:53:17 -08:00
|
|
|
index = _evas_common_get_char_index(fi, gl);
|
2006-04-22 04:08:01 -07:00
|
|
|
if (index != 0)
|
|
|
|
{
|
2008-07-10 11:08:18 -07:00
|
|
|
if (!fi->ft.size)
|
2010-10-29 05:55:42 -07:00
|
|
|
evas_common_font_int_load_complete(fi);
|
2010-02-03 03:18:00 -08:00
|
|
|
if (!fn->fash) fn->fash = _fash_int_new();
|
|
|
|
if (fn->fash) _fash_int_add(fn->fash, gl, fi, index);
|
2006-04-22 04:08:01 -07:00
|
|
|
*fi_ret = fi;
|
|
|
|
return index;
|
|
|
|
}
|
2010-02-03 03:18:00 -08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!fn->fash) fn->fash = _fash_int_new();
|
|
|
|
if (fn->fash) _fash_int_add(fn->fash, gl, NULL, -1);
|
|
|
|
}
|
2005-03-20 07:57:55 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-07-28 05:00:41 -07:00
|
|
|
/*
|
2011-02-01 04:17:52 -08:00
|
|
|
* BiDi handling: We receive the shaped string + other props from text_props,
|
2010-07-28 05:00:41 -07:00
|
|
|
* we need to reorder it so we'll have the visual string (the way we draw)
|
|
|
|
* and then for kerning we have to switch the order of the kerning query (as the prev
|
|
|
|
* is on the right, and not on the left).
|
|
|
|
*/
|
2009-02-20 19:13:49 -08:00
|
|
|
static void
|
2010-07-28 05:00:41 -07:00
|
|
|
evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const Eina_Unicode *in_text,
|
2011-02-01 04:17:52 -08:00
|
|
|
const Evas_Text_Props *text_props, RGBA_Gfx_Func func, int ext_x, int ext_y, int ext_w,
|
2011-03-30 08:55:10 -07:00
|
|
|
int ext_h, RGBA_Font_Int *fi, int im_w, int im_h __UNUSED__)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2010-07-28 05:00:41 -07:00
|
|
|
const Eina_Unicode *text = in_text;
|
2002-11-08 00:02:15 -08:00
|
|
|
DATA32 *im;
|
2011-02-01 04:17:52 -08:00
|
|
|
FT_Face pface = NULL;
|
2011-01-30 02:33:24 -08:00
|
|
|
EVAS_FONT_WALK_TEXT_INIT();
|
2009-04-23 21:35:52 -07:00
|
|
|
|
2010-06-25 01:52:37 -07:00
|
|
|
#if defined(METRIC_CACHE) || defined(WORD_CACHE)
|
2010-08-16 05:28:17 -07:00
|
|
|
unsigned int len;
|
|
|
|
|
2011-04-13 01:36:51 -07:00
|
|
|
len = text_props->text_len;
|
2010-06-13 22:59:23 -07:00
|
|
|
|
2011-01-30 02:43:09 -08:00
|
|
|
if (len > 2 && (len < WORD_CACHE_MAXLEN))
|
2010-10-07 14:07:53 -07:00
|
|
|
{
|
|
|
|
struct prword *word;
|
2010-06-13 22:59:23 -07:00
|
|
|
|
2011-01-30 02:43:09 -08:00
|
|
|
word =
|
2011-02-01 04:17:52 -08:00
|
|
|
evas_font_word_prerender(dc, text, text_props,
|
2011-03-30 08:55:10 -07:00
|
|
|
len, fn, fi);
|
2010-10-07 14:07:53 -07:00
|
|
|
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;
|
2010-08-16 03:46:56 -07:00
|
|
|
# ifdef WORD_CACHE
|
2010-10-07 14:07:53 -07:00
|
|
|
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;
|
|
|
|
}
|
2010-08-16 03:46:56 -07:00
|
|
|
# elif defined(METRIC_CACHE)
|
2010-10-07 14:07:53 -07:00
|
|
|
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;
|
2010-08-16 03:46:56 -07:00
|
|
|
# endif
|
2010-10-07 14:07:53 -07:00
|
|
|
}
|
2010-06-13 22:59:23 -07:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-02-20 19:13:49 -08:00
|
|
|
im = dst->image.data;
|
2011-02-01 04:17:52 -08:00
|
|
|
/* Load the glyph according to the first letter of the script, preety
|
|
|
|
* bad, but will have to do */
|
|
|
|
{
|
|
|
|
/* Skip common chars */
|
|
|
|
const Eina_Unicode *tmp;
|
|
|
|
for (tmp = text ;
|
2011-04-13 01:36:51 -07:00
|
|
|
((size_t) (tmp - text) < text_props->text_len) &&
|
2011-02-01 04:17:52 -08:00
|
|
|
evas_common_language_char_script_get(*tmp) ==
|
|
|
|
EVAS_SCRIPT_COMMON ;
|
|
|
|
tmp++)
|
|
|
|
;
|
2011-04-13 01:36:51 -07:00
|
|
|
if (((size_t) (tmp - text) == text_props->text_len) && (tmp > text))
|
|
|
|
tmp--;
|
2011-02-01 04:17:52 -08:00
|
|
|
evas_common_font_glyph_search(fn, &fi, *tmp);
|
|
|
|
}
|
2011-03-27 05:22:13 -07:00
|
|
|
|
|
|
|
if (fi->src->current_size != fi->size)
|
|
|
|
{
|
|
|
|
FTLOCK();
|
|
|
|
FT_Activate_Size(fi->ft.size);
|
|
|
|
FTUNLOCK();
|
|
|
|
fi->src->current_size = fi->size;
|
|
|
|
}
|
|
|
|
|
2011-02-01 04:17:52 -08:00
|
|
|
EVAS_FONT_WALK_TEXT_VISUAL_START()
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
FT_UInt index;
|
|
|
|
RGBA_Font_Glyph *fg;
|
|
|
|
int chr_x, chr_y, chr_w;
|
|
|
|
if (!EVAS_FONT_WALK_IS_VISIBLE) continue;
|
|
|
|
|
|
|
|
#ifdef OT_SUPPORT
|
2011-02-22 05:00:02 -08:00
|
|
|
index = EVAS_FONT_WALK_INDEX;
|
2011-02-01 04:17:52 -08:00
|
|
|
#else
|
|
|
|
/* FIXME: Should be removed once we split according to script without
|
|
|
|
* the use of harfbuzz */
|
|
|
|
index =
|
|
|
|
evas_common_font_glyph_search(fn, &fi, text[EVAS_FONT_WALK_POS]);
|
2011-03-27 05:22:13 -07:00
|
|
|
|
|
|
|
if (fi->src->current_size != fi->size)
|
|
|
|
{
|
|
|
|
FTLOCK();
|
|
|
|
FT_Activate_Size(fi->ft.size);
|
|
|
|
FTUNLOCK();
|
|
|
|
fi->src->current_size = fi->size;
|
|
|
|
}
|
2011-02-01 04:17:52 -08:00
|
|
|
#endif
|
|
|
|
LKL(fi->ft_mutex);
|
|
|
|
fg = evas_common_font_int_cache_glyph_get(fi, index);
|
|
|
|
if (!fg)
|
2011-01-30 02:36:39 -08:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
LKU(fi->ft_mutex);
|
|
|
|
continue;
|
|
|
|
}
|
2005-05-21 19:49:50 -07:00
|
|
|
|
2011-02-01 04:17:52 -08:00
|
|
|
pface = fi->src->ft.face;
|
|
|
|
LKU(fi->ft_mutex);
|
2010-10-07 14:07:53 -07:00
|
|
|
|
2011-02-01 04:17:52 -08:00
|
|
|
if (dc->font_ext.func.gl_new)
|
|
|
|
{
|
|
|
|
/* extension calls */
|
|
|
|
fg->ext_dat = dc->font_ext.func.gl_new(dc->font_ext.data, fg);
|
|
|
|
fg->ext_dat_free = dc->font_ext.func.gl_free;
|
|
|
|
}
|
2011-01-30 02:33:24 -08:00
|
|
|
|
2011-02-01 04:17:52 -08:00
|
|
|
chr_x = x + EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_X_OFF + EVAS_FONT_WALK_X_BEAR;
|
|
|
|
chr_y = y + EVAS_FONT_WALK_PEN_Y + EVAS_FONT_WALK_Y_OFF + EVAS_FONT_WALK_Y_BEAR;
|
|
|
|
chr_w = EVAS_FONT_WALK_WIDTH;
|
2010-10-07 14:07:53 -07:00
|
|
|
|
2011-02-01 04:17:52 -08:00
|
|
|
if (chr_x < (ext_x + ext_w))
|
|
|
|
{
|
|
|
|
DATA8 *data;
|
|
|
|
int i, j, w, h;
|
|
|
|
|
|
|
|
data = fg->glyph_out->bitmap.buffer;
|
|
|
|
j = fg->glyph_out->bitmap.pitch;
|
|
|
|
w = fg->glyph_out->bitmap.width;
|
|
|
|
if (j < w) j = w;
|
|
|
|
h = fg->glyph_out->bitmap.rows;
|
|
|
|
/*
|
|
|
|
if ((fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays)
|
|
|
|
&& (fg->glyph_out->bitmap.num_grays == 256)
|
|
|
|
)
|
|
|
|
*/
|
2010-10-07 14:07:53 -07:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
if ((j > 0) && (chr_x + w > ext_x))
|
2010-10-07 14:07:53 -07:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
if ((fg->ext_dat) && (dc->font_ext.func.gl_draw))
|
2011-01-30 05:55:04 -08:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
/* ext glyph draw */
|
|
|
|
dc->font_ext.func.gl_draw(dc->font_ext.data,
|
|
|
|
(void *)dst,
|
|
|
|
dc, fg, chr_x,
|
|
|
|
y - (chr_y - y));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((fg->glyph_out->bitmap.num_grays == 256) &&
|
|
|
|
(fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays))
|
2011-01-30 02:36:39 -08:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
for (i = 0; i < h; i++)
|
2010-10-07 14:07:53 -07:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
int dx, dy;
|
|
|
|
int in_x, in_w;
|
2010-10-07 14:07:53 -07:00
|
|
|
|
2011-02-01 04:17:52 -08:00
|
|
|
in_x = 0;
|
|
|
|
in_w = 0;
|
|
|
|
dx = chr_x;
|
|
|
|
dy = y - (chr_y - i - y);
|
2006-11-15 08:44:34 -08:00
|
|
|
#ifdef EVAS_SLI
|
2011-02-01 04:17:52 -08:00
|
|
|
if (((dy) % dc->sli.h) == dc->sli.y)
|
2006-11-15 08:44:34 -08:00
|
|
|
#endif
|
2010-10-07 14:07:53 -07:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
if ((dx < (ext_x + ext_w)) &&
|
|
|
|
(dy >= (ext_y)) &&
|
|
|
|
(dy < (ext_y + ext_h)))
|
2010-10-07 14:07:53 -07:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
if (dx + w > (ext_x + ext_w))
|
|
|
|
in_w += (dx + w) - (ext_x + ext_w);
|
|
|
|
if (dx < ext_x)
|
2010-10-07 14:07:53 -07:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
in_w += ext_x - dx;
|
|
|
|
in_x = ext_x - dx;
|
|
|
|
dx = ext_x;
|
2010-10-07 14:07:53 -07:00
|
|
|
}
|
2011-02-01 04:17:52 -08:00
|
|
|
if (in_w < w)
|
2010-10-07 14:07:53 -07:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
func(NULL, data + (i * j) + in_x, dc->col.col,
|
|
|
|
im + (dy * im_w) + dx, w - in_w);
|
2010-10-07 14:07:53 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
DATA8 *tmpbuf = NULL, *dp, *tp, bits;
|
|
|
|
int bi, bj;
|
|
|
|
const DATA8 bitrepl[2] = {0x0, 0xff};
|
|
|
|
|
|
|
|
tmpbuf = alloca(w);
|
|
|
|
for (i = 0; i < h; i++)
|
2010-10-07 14:07:53 -07:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
int dx, dy;
|
|
|
|
int in_x, in_w, end;
|
2010-10-07 14:07:53 -07:00
|
|
|
|
2011-02-01 04:17:52 -08:00
|
|
|
in_x = 0;
|
|
|
|
in_w = 0;
|
|
|
|
dx = chr_x;
|
|
|
|
dy = y - (chr_y - i - y);
|
2006-11-15 08:44:34 -08:00
|
|
|
#ifdef EVAS_SLI
|
2011-02-01 04:17:52 -08:00
|
|
|
if (((dy) % dc->sli.h) == dc->sli.y)
|
2006-11-15 08:44:34 -08:00
|
|
|
#endif
|
2011-02-01 04:17:52 -08:00
|
|
|
{
|
|
|
|
tp = tmpbuf;
|
|
|
|
dp = data + (i * fg->glyph_out->bitmap.pitch);
|
|
|
|
for (bi = 0; bi < w; bi += 8)
|
2010-10-07 14:07:53 -07:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
bits = *dp;
|
|
|
|
if ((w - bi) < 8) end = w - bi;
|
|
|
|
else end = 8;
|
|
|
|
for (bj = 0; bj < end; bj++)
|
2010-10-07 14:07:53 -07:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
*tp = bitrepl[(bits >> (7 - bj)) & 0x1];
|
|
|
|
tp++;
|
2010-10-07 14:07:53 -07:00
|
|
|
}
|
2011-02-01 04:17:52 -08:00
|
|
|
dp++;
|
2010-10-07 14:07:53 -07:00
|
|
|
}
|
2011-02-01 04:17:52 -08:00
|
|
|
if ((dx < (ext_x + ext_w)) &&
|
|
|
|
(dy >= (ext_y)) &&
|
|
|
|
(dy < (ext_y + ext_h)))
|
2010-10-07 14:07:53 -07:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
if (dx + w > (ext_x + ext_w))
|
|
|
|
in_w += (dx + w) - (ext_x + ext_w);
|
|
|
|
if (dx < ext_x)
|
2010-10-07 14:07:53 -07:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
in_w += ext_x - dx;
|
|
|
|
in_x = ext_x - dx;
|
|
|
|
dx = ext_x;
|
2010-10-07 14:07:53 -07:00
|
|
|
}
|
2011-02-01 04:17:52 -08:00
|
|
|
if (in_w < w)
|
2010-10-07 14:07:53 -07:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
func(NULL, tmpbuf + in_x, dc->col.col,
|
|
|
|
im + (dy * im_w) + dx, w - in_w);
|
2010-10-07 14:07:53 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-02-01 04:17:52 -08:00
|
|
|
else
|
|
|
|
break;
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
2011-02-01 04:17:52 -08:00
|
|
|
EVAS_FONT_WALK_TEXT_END();
|
2010-10-29 05:55:42 -07:00
|
|
|
evas_common_font_int_use_trim();
|
2009-02-20 19:13:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2010-07-28 05:00:41 -07:00
|
|
|
evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const Eina_Unicode *text,
|
2011-02-01 04:17:52 -08:00
|
|
|
const Evas_Text_Props *text_props)
|
2009-02-20 19:13:49 -08:00
|
|
|
{
|
|
|
|
int ext_x, ext_y, ext_w, ext_h;
|
|
|
|
int im_w, im_h;
|
2009-04-23 21:35:52 -07:00
|
|
|
RGBA_Gfx_Func func;
|
2009-02-20 19:13:49 -08:00
|
|
|
RGBA_Font_Int *fi;
|
|
|
|
Cutout_Rects *rects;
|
|
|
|
Cutout_Rect *r;
|
2010-10-07 14:07:53 -07:00
|
|
|
int c, cx, cy, cw, ch;
|
|
|
|
int i;
|
2009-04-23 21:35:52 -07:00
|
|
|
|
2009-02-20 19:13:49 -08:00
|
|
|
fi = fn->fonts->data;
|
|
|
|
|
|
|
|
im_w = dst->cache_entry.w;
|
|
|
|
im_h = dst->cache_entry.h;
|
|
|
|
|
|
|
|
ext_x = 0; ext_y = 0; ext_w = im_w; ext_h = im_h;
|
|
|
|
if (dc->clip.use)
|
|
|
|
{
|
|
|
|
ext_x = dc->clip.x;
|
|
|
|
ext_y = dc->clip.y;
|
|
|
|
ext_w = dc->clip.w;
|
|
|
|
ext_h = dc->clip.h;
|
|
|
|
if (ext_x < 0)
|
|
|
|
{
|
|
|
|
ext_w += ext_x;
|
|
|
|
ext_x = 0;
|
|
|
|
}
|
|
|
|
if (ext_y < 0)
|
|
|
|
{
|
|
|
|
ext_h += ext_y;
|
|
|
|
ext_y = 0;
|
|
|
|
}
|
|
|
|
if ((ext_x + ext_w) > im_w)
|
|
|
|
ext_w = im_w - ext_x;
|
|
|
|
if ((ext_y + ext_h) > im_h)
|
|
|
|
ext_h = im_h - ext_y;
|
|
|
|
}
|
|
|
|
if (ext_w <= 0) return;
|
|
|
|
if (ext_h <= 0) return;
|
|
|
|
|
2010-08-29 20:21:15 -07:00
|
|
|
#ifdef EVAS_FRAME_QUEUING
|
2009-02-20 19:13:49 -08:00
|
|
|
LKL(fn->lock);
|
2010-05-21 00:10:45 -07:00
|
|
|
#endif
|
2010-10-29 05:55:42 -07:00
|
|
|
evas_common_font_int_reload(fi);
|
2010-02-03 03:18:00 -08:00
|
|
|
// evas_common_font_size_use(fn);
|
2009-02-20 19:13:49 -08:00
|
|
|
func = evas_common_gfx_func_composite_mask_color_span_get(dc->col.col, dst, 1, dc->render_op);
|
|
|
|
|
|
|
|
if (!dc->cutout.rects)
|
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
evas_common_font_draw_internal(dst, dc, fn, x, y, text, text_props,
|
2009-02-20 19:13:49 -08:00
|
|
|
func, ext_x, ext_y, ext_w, ext_h, fi,
|
2011-03-30 08:55:10 -07:00
|
|
|
im_w, im_h);
|
2009-02-20 19:13:49 -08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-02-22 23:20:21 -08:00
|
|
|
c = dc->clip.use; cx = dc->clip.x; cy = dc->clip.y; cw = dc->clip.w; ch = dc->clip.h;
|
2009-02-20 19:13:49 -08:00
|
|
|
evas_common_draw_context_clip_clip(dc, 0, 0, dst->cache_entry.w, dst->cache_entry.h);
|
|
|
|
/* our clip is 0 size.. abort */
|
|
|
|
if ((dc->clip.w > 0) && (dc->clip.h > 0))
|
|
|
|
{
|
|
|
|
rects = evas_common_draw_context_apply_cutouts(dc);
|
|
|
|
for (i = 0; i < rects->active; ++i)
|
|
|
|
{
|
|
|
|
r = rects->rects + i;
|
|
|
|
evas_common_draw_context_set_clip(dc, r->x, r->y, r->w, r->h);
|
2011-02-01 04:17:52 -08:00
|
|
|
evas_common_font_draw_internal(dst, dc, fn, x, y, text, text_props,
|
2009-02-20 19:13:49 -08:00
|
|
|
func, r->x, r->y, r->w, r->h, fi,
|
2011-03-30 08:55:10 -07:00
|
|
|
im_w, im_h);
|
2009-02-20 19:13:49 -08:00
|
|
|
}
|
|
|
|
evas_common_draw_context_apply_clear_cutouts(rects);
|
|
|
|
}
|
2009-02-22 23:20:21 -08:00
|
|
|
dc->clip.use = c; dc->clip.x = cx; dc->clip.y = cy; dc->clip.w = cw; dc->clip.h = ch;
|
2009-02-20 19:13:49 -08:00
|
|
|
}
|
2010-08-29 20:21:15 -07:00
|
|
|
#ifdef EVAS_FRAME_QUEUING
|
2006-11-13 15:23:44 -08:00
|
|
|
LKU(fn->lock);
|
2010-05-21 00:10:45 -07:00
|
|
|
#endif
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
2010-06-13 22:59:23 -07:00
|
|
|
|
2010-07-28 05:00:41 -07:00
|
|
|
/* FIXME: Where is it freed at? */
|
2010-08-16 03:46:56 -07:00
|
|
|
/* Only used if cache is on */
|
|
|
|
#if defined(METRIC_CACHE) || defined(WORD_CACHE)
|
2010-06-13 22:59:23 -07:00
|
|
|
struct prword *
|
2011-03-30 08:55:10 -07:00
|
|
|
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)
|
2010-10-07 14:07:53 -07:00
|
|
|
{
|
2010-06-13 22:59:23 -07:00
|
|
|
struct cinfo *metrics;
|
2010-07-28 05:00:41 -07:00
|
|
|
const Eina_Unicode *text = in_text;
|
2010-06-13 22:59:23 -07:00
|
|
|
unsigned char *im;
|
|
|
|
int width;
|
|
|
|
int height, above, below, baseline, descent;
|
|
|
|
int i,j;
|
|
|
|
struct prword *w;
|
2011-01-30 02:43:09 -08:00
|
|
|
int last_delta = 0;
|
2010-06-13 22:59:23 -07:00
|
|
|
int gl;
|
2011-02-22 05:00:02 -08:00
|
|
|
struct cinfo *ci;
|
2011-01-30 02:43:09 -08:00
|
|
|
EVAS_FONT_WALK_TEXT_INIT();
|
2010-06-13 22:59:23 -07:00
|
|
|
|
2010-08-16 03:46:56 -07:00
|
|
|
# ifndef METRIC_CACHE
|
2010-07-29 21:53:30 -07:00
|
|
|
gl = dc->font_ext.func.gl_new ? 1: 0;
|
|
|
|
if (gl) return NULL;
|
2010-08-16 03:46:56 -07:00
|
|
|
# endif
|
2010-07-29 21:53:30 -07:00
|
|
|
|
2010-07-20 05:11:49 -07:00
|
|
|
LKL(lock_words);
|
2010-10-07 14:07:53 -07:00
|
|
|
EINA_INLIST_FOREACH(words,w)
|
|
|
|
{
|
2010-06-13 22:59:23 -07:00
|
|
|
if (w->len == len && w->font == fn && fi->size == w->size &&
|
2010-10-07 14:07:53 -07:00
|
|
|
(w->str == in_text || memcmp(w->str, in_text, len * sizeof(Eina_Unicode)) == 0)){
|
|
|
|
words = eina_inlist_promote(words, EINA_INLIST_GET(w));
|
|
|
|
LKU(lock_words);
|
|
|
|
return w;
|
2010-06-13 22:59:23 -07:00
|
|
|
}
|
2010-10-07 14:07:53 -07:00
|
|
|
}
|
2010-07-20 05:11:49 -07:00
|
|
|
LKU(lock_words);
|
2010-06-13 22:59:23 -07:00
|
|
|
|
|
|
|
gl = dc->font_ext.func.gl_new ? 1: 0;
|
|
|
|
|
|
|
|
above = 0; below = 0; baseline = 0; height = 0; descent = 0;
|
2011-02-01 04:18:01 -08:00
|
|
|
/* Load the glyph according to the first letter of the script, preety
|
|
|
|
* bad, but will have to do */
|
|
|
|
{
|
|
|
|
/* Skip common chars */
|
|
|
|
const Eina_Unicode *tmp;
|
|
|
|
for (tmp = text ;
|
2011-04-13 01:36:51 -07:00
|
|
|
((tmp - text) < len) &&
|
2011-02-01 04:18:01 -08:00
|
|
|
evas_common_language_char_script_get(*tmp) ==
|
|
|
|
EVAS_SCRIPT_COMMON ;
|
|
|
|
tmp++)
|
|
|
|
;
|
2011-04-13 01:36:51 -07:00
|
|
|
if (((tmp - text) == len) && (tmp > text)) tmp--;
|
2011-02-01 04:18:01 -08:00
|
|
|
evas_common_font_glyph_search(fn, &fi, *tmp);
|
|
|
|
}
|
2010-10-07 14:07:53 -07:00
|
|
|
|
2011-03-27 05:22:13 -07:00
|
|
|
if (fi->src->current_size != fi->size)
|
|
|
|
{
|
|
|
|
FTLOCK();
|
|
|
|
FT_Activate_Size(fi->ft.size);
|
|
|
|
FTUNLOCK();
|
|
|
|
fi->src->current_size = fi->size;
|
|
|
|
}
|
|
|
|
|
2011-01-30 02:43:09 -08:00
|
|
|
/* 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 */
|
2011-02-01 04:17:52 -08:00
|
|
|
len = text_props->len;
|
|
|
|
metrics = malloc(sizeof(struct cinfo) * len);
|
2011-02-22 05:00:02 -08:00
|
|
|
ci = metrics;
|
2011-02-01 04:17:52 -08:00
|
|
|
EVAS_FONT_WALK_TEXT_VISUAL_START()
|
2010-10-07 14:07:53 -07:00
|
|
|
{
|
2011-02-01 04:18:01 -08:00
|
|
|
FT_UInt index;
|
|
|
|
RGBA_Font_Glyph *fg;
|
|
|
|
#ifdef OT_SUPPORT
|
2011-02-22 05:00:02 -08:00
|
|
|
index = EVAS_FONT_WALK_INDEX;
|
2011-02-01 04:18:01 -08:00
|
|
|
#else
|
|
|
|
/* FIXME: Should be removed once we split according to script without
|
|
|
|
* the use of harfbuzz */
|
|
|
|
index =
|
|
|
|
evas_common_font_glyph_search(fn, &fi, text[EVAS_FONT_WALK_POS]);
|
2011-03-27 05:22:13 -07:00
|
|
|
|
|
|
|
if (fi->src->current_size != fi->size)
|
|
|
|
{
|
|
|
|
FTLOCK();
|
|
|
|
FT_Activate_Size(fi->ft.size);
|
|
|
|
FTUNLOCK();
|
|
|
|
fi->src->current_size = fi->size;
|
|
|
|
}
|
2011-02-01 04:18:01 -08:00
|
|
|
#endif
|
|
|
|
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();
|
2011-02-01 04:17:52 -08:00
|
|
|
/* Currently broken with invisible chars if (!EVAS_FONT_WALK_IS_VISIBLE) continue; */
|
|
|
|
ci->index = index;
|
|
|
|
ci->fg = fg;
|
2011-01-30 02:43:09 -08:00
|
|
|
|
2011-02-01 04:17:52 -08:00
|
|
|
if (gl)
|
2010-10-07 14:07:53 -07:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
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;
|
2010-10-07 14:07:53 -07:00
|
|
|
}
|
2011-02-01 04:17:52 -08:00
|
|
|
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;
|
2011-02-01 04:18:01 -08:00
|
|
|
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;
|
2011-02-01 04:17:52 -08:00
|
|
|
last_delta = EVAS_FONT_WALK_X_ADV -
|
|
|
|
(ci->bm.w + ci->fg->glyph_out->left);
|
2011-02-22 05:00:02 -08:00
|
|
|
ci++;
|
2010-06-13 22:59:23 -07:00
|
|
|
}
|
2011-02-01 04:17:52 -08:00
|
|
|
EVAS_FONT_WALK_TEXT_END();
|
2010-10-07 14:07:53 -07:00
|
|
|
|
|
|
|
/* First loop done */
|
2011-01-30 02:43:09 -08:00
|
|
|
width = EVAS_FONT_WALK_PEN_X;
|
|
|
|
if (last_delta < 0)
|
|
|
|
width -= last_delta;
|
2010-10-07 14:07:53 -07:00
|
|
|
width = (width & 0x7) ? width + (8 - (width & 0x7)) : width;
|
|
|
|
|
|
|
|
height = baseline + descent;
|
|
|
|
if (!gl)
|
|
|
|
{
|
|
|
|
im = calloc(height, width);
|
2011-01-30 02:43:09 -08:00
|
|
|
for (i = 0 ; i < len ; i ++)
|
2010-10-07 14:07:53 -07:00
|
|
|
{
|
|
|
|
struct cinfo *ci = metrics + i;
|
|
|
|
|
|
|
|
for (j = 0 ; j < ci->bm.rows ; j ++)
|
2011-01-30 02:43:09 -08:00
|
|
|
{
|
|
|
|
int correction; /* Used to remove negative inset and such */
|
|
|
|
if (ci->pos.x < 0)
|
|
|
|
correction = -ci->pos.x;
|
|
|
|
else
|
|
|
|
correction = 0;
|
|
|
|
|
|
|
|
memcpy(im + ci->pos.x + (j + baseline - ci->bm.h) * width +
|
|
|
|
correction,
|
|
|
|
ci->bm.data + j * ci->bm.w + correction,
|
|
|
|
ci->bm.w - correction);
|
|
|
|
}
|
2010-10-07 14:07:53 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
im = NULL;
|
|
|
|
}
|
|
|
|
|
2010-06-13 22:59:23 -07:00
|
|
|
/* Save it */
|
|
|
|
struct prword *save;
|
|
|
|
|
|
|
|
save = malloc(sizeof(struct prword));
|
|
|
|
save->cinfo = metrics;
|
2010-07-29 21:53:30 -07:00
|
|
|
save->str = eina_ustringshare_add(in_text);
|
2010-06-13 22:59:23 -07:00
|
|
|
save->font = fn;
|
|
|
|
save->size = fi->size;
|
|
|
|
save->len = len;
|
|
|
|
save->im = im;
|
2011-01-30 02:43:09 -08:00
|
|
|
save->width = EVAS_FONT_WALK_PEN_X;
|
|
|
|
if (last_delta < 0)
|
|
|
|
save->width += last_delta;
|
2010-06-13 22:59:23 -07:00
|
|
|
save->roww = width;
|
|
|
|
save->height = height;
|
|
|
|
save->baseline = baseline;
|
2010-07-20 05:11:49 -07:00
|
|
|
LKL(lock_words);
|
2010-06-13 22:59:23 -07:00
|
|
|
words = eina_inlist_prepend(words, EINA_INLIST_GET(save));
|
|
|
|
|
|
|
|
/* Clean up if too long */
|
2010-10-07 14:07:53 -07:00
|
|
|
if (eina_inlist_count(words) > max_cached_words)
|
|
|
|
{
|
2010-06-13 22:59:23 -07:00
|
|
|
struct prword *last = (struct prword *)(words->last);
|
2010-10-07 14:07:53 -07:00
|
|
|
|
|
|
|
if (last)
|
|
|
|
{
|
|
|
|
if (last->im) free(last->im);
|
|
|
|
if (last->cinfo) free(last->cinfo);
|
|
|
|
eina_ustringshare_del(last->str);
|
|
|
|
words = eina_inlist_remove(words, EINA_INLIST_GET(last));
|
|
|
|
free(last);
|
|
|
|
}
|
|
|
|
}
|
2010-07-20 05:11:49 -07:00
|
|
|
LKU(lock_words);
|
2010-06-13 22:59:23 -07:00
|
|
|
|
2010-07-04 23:40:20 -07:00
|
|
|
return save;
|
2010-06-13 22:59:23 -07:00
|
|
|
}
|
2010-08-16 03:46:56 -07:00
|
|
|
#endif
|