2002-11-08 00:02:15 -08:00
|
|
|
#include "evas_common.h"
|
2009-09-21 09:08:51 -07:00
|
|
|
#include "evas_private.h"
|
2010-07-28 05:00:41 -07:00
|
|
|
|
2010-07-20 05:09:46 -07:00
|
|
|
#include "evas_font_private.h"
|
|
|
|
|
2012-06-22 13:31:31 -07:00
|
|
|
#ifdef EVAS_CSERVE2
|
|
|
|
# include "../../cserve2/evas_cs2_private.h"
|
|
|
|
#endif
|
|
|
|
|
2012-05-17 19:16:54 -07:00
|
|
|
#include <assert.h>
|
|
|
|
|
2011-05-04 01:27:19 -07:00
|
|
|
#include FT_OUTLINE_H
|
|
|
|
|
2004-01-15 06:58:03 -08:00
|
|
|
FT_Library evas_ft_lib = 0;
|
2004-01-12 10:12:41 -08:00
|
|
|
static int initialised = 0;
|
2002-11-08 00:02:15 -08:00
|
|
|
|
2010-05-30 20:31:49 -07:00
|
|
|
LK(lock_font_draw); // for freetype2 API calls
|
2010-09-01 06:15:04 -07:00
|
|
|
LK(lock_bidi); // for evas bidi internal usage.
|
2011-01-30 02:36:39 -08:00
|
|
|
LK(lock_ot); // for evas bidi internal usage.
|
2010-05-30 20:31:49 -07:00
|
|
|
|
2006-09-06 00:33:40 -07:00
|
|
|
EAPI void
|
2002-11-13 21:38:10 -08:00
|
|
|
evas_common_font_init(void)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
|
|
|
int error;
|
2011-11-08 21:58:19 -08:00
|
|
|
const char *s;
|
2002-11-08 00:02:15 -08:00
|
|
|
|
2004-01-12 15:48:10 -08:00
|
|
|
initialised++;
|
|
|
|
if (initialised != 1) return;
|
2004-01-15 06:58:03 -08:00
|
|
|
error = FT_Init_FreeType(&evas_ft_lib);
|
2010-05-17 21:22:33 -07:00
|
|
|
if (error) return;
|
2009-06-15 08:07:13 -07:00
|
|
|
evas_common_font_load_init();
|
2010-05-21 00:10:45 -07:00
|
|
|
evas_common_font_draw_init();
|
2011-11-08 21:58:19 -08:00
|
|
|
s = getenv("EVAS_FONT_DPI");
|
|
|
|
if (s)
|
|
|
|
{
|
|
|
|
int dpi = atoi(s);
|
2011-11-09 00:01:00 -08:00
|
|
|
|
2011-11-08 21:58:19 -08:00
|
|
|
if (dpi > 0) evas_common_font_dpi_set(dpi);
|
|
|
|
}
|
2010-05-30 20:31:49 -07:00
|
|
|
LKI(lock_font_draw);
|
2010-09-01 06:15:04 -07:00
|
|
|
LKI(lock_bidi);
|
2011-01-30 02:36:39 -08:00
|
|
|
LKI(lock_ot);
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
|
|
|
|
2006-09-06 00:33:40 -07:00
|
|
|
EAPI void
|
2004-01-12 10:12:41 -08:00
|
|
|
evas_common_font_shutdown(void)
|
|
|
|
{
|
2010-05-17 21:22:33 -07:00
|
|
|
if (initialised < 1) return;
|
2004-01-12 15:48:10 -08:00
|
|
|
initialised--;
|
|
|
|
if (initialised != 0) return;
|
2008-02-15 06:43:51 -08:00
|
|
|
|
2009-06-15 08:07:13 -07:00
|
|
|
evas_common_font_load_shutdown();
|
2008-02-15 06:43:51 -08:00
|
|
|
evas_common_font_cache_set(0);
|
|
|
|
evas_common_font_flush();
|
|
|
|
|
2012-01-18 15:33:33 -08:00
|
|
|
FT_Done_FreeType(evas_ft_lib);
|
2008-02-15 06:43:51 -08:00
|
|
|
evas_ft_lib = 0;
|
2012-06-17 18:05:30 -07:00
|
|
|
|
|
|
|
LKD(lock_font_draw);
|
|
|
|
LKD(lock_bidi);
|
|
|
|
LKD(lock_ot);
|
2004-01-12 10:12:41 -08:00
|
|
|
}
|
|
|
|
|
2010-04-12 01:23:53 -07:00
|
|
|
EAPI void
|
|
|
|
evas_common_font_font_all_unload(void)
|
|
|
|
{
|
|
|
|
evas_common_font_all_clear();
|
|
|
|
}
|
|
|
|
|
2006-09-06 00:33:40 -07:00
|
|
|
EAPI int
|
2002-11-13 21:38:10 -08:00
|
|
|
evas_common_font_ascent_get(RGBA_Font *fn)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2010-08-16 03:46:56 -07:00
|
|
|
int val;
|
2005-03-20 07:57:55 -08:00
|
|
|
RGBA_Font_Int *fi;
|
2005-05-21 19:49:48 -07:00
|
|
|
|
2010-02-03 03:18:00 -08:00
|
|
|
// evas_common_font_size_use(fn);
|
2010-04-25 04:35:41 -07:00
|
|
|
#if 0
|
|
|
|
{
|
|
|
|
Eina_List *l;
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(fn->fonts, l, fi)
|
|
|
|
{
|
|
|
|
if (!fi->src->ft.face) continue;
|
|
|
|
if (fi->src->current_size != fi->size)
|
|
|
|
{
|
2010-07-20 05:09:46 -07:00
|
|
|
FTLOCK();
|
2010-04-25 04:35:41 -07:00
|
|
|
FT_Activate_Size(fi->ft.size);
|
2010-07-20 05:09:46 -07:00
|
|
|
FTUNLOCK();
|
2010-04-25 04:35:41 -07:00
|
|
|
fi->src->current_size = fi->size;
|
|
|
|
}
|
|
|
|
val = (int)fi->src->ft.face->size->metrics.ascender;
|
|
|
|
if (fi->src->ft.face->units_per_EM == 0)
|
|
|
|
return val;
|
|
|
|
dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
|
|
|
|
ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
|
|
|
|
printf(" ==== %p: %i\n", fi, ret);
|
|
|
|
}
|
|
|
|
}
|
2010-05-01 07:08:14 -07:00
|
|
|
#endif
|
2005-03-20 07:57:55 -08:00
|
|
|
fi = fn->fonts->data;
|
2010-10-29 05:55:42 -07:00
|
|
|
evas_common_font_int_reload(fi);
|
2010-02-03 03:18:00 -08:00
|
|
|
if (fi->src->current_size != fi->size)
|
|
|
|
{
|
2011-08-11 07:14:48 -07:00
|
|
|
FTLOCK();
|
2010-02-03 03:18:00 -08:00
|
|
|
FT_Activate_Size(fi->ft.size);
|
2011-08-11 07:14:48 -07:00
|
|
|
FTUNLOCK();
|
2010-02-03 03:18:00 -08:00
|
|
|
fi->src->current_size = fi->size;
|
|
|
|
}
|
2010-05-01 07:08:14 -07:00
|
|
|
if (!FT_IS_SCALABLE(fi->src->ft.face))
|
|
|
|
{
|
2010-10-07 16:46:42 -07:00
|
|
|
WRN("NOT SCALABLE!");
|
2010-05-01 07:08:14 -07:00
|
|
|
}
|
2005-03-20 07:57:55 -08:00
|
|
|
val = (int)fi->src->ft.face->size->metrics.ascender;
|
2010-05-01 07:08:14 -07:00
|
|
|
return val >> 6;
|
|
|
|
// printf("%i | %i\n", val, val >> 6);
|
|
|
|
// if (fi->src->ft.face->units_per_EM == 0)
|
|
|
|
// return val;
|
|
|
|
// dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
|
|
|
|
// ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
|
|
|
|
// return ret;
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
|
|
|
|
2006-09-06 00:33:40 -07:00
|
|
|
EAPI int
|
2002-11-13 21:38:10 -08:00
|
|
|
evas_common_font_descent_get(RGBA_Font *fn)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2010-08-16 03:46:56 -07:00
|
|
|
int val;
|
2005-03-20 07:57:55 -08:00
|
|
|
RGBA_Font_Int *fi;
|
2005-05-21 19:49:48 -07:00
|
|
|
|
2010-02-03 03:18:00 -08:00
|
|
|
// evas_common_font_size_use(fn);
|
2005-03-20 07:57:55 -08:00
|
|
|
fi = fn->fonts->data;
|
2010-10-29 05:55:42 -07:00
|
|
|
evas_common_font_int_reload(fi);
|
2010-02-03 03:18:00 -08:00
|
|
|
if (fi->src->current_size != fi->size)
|
|
|
|
{
|
2011-08-11 07:14:48 -07:00
|
|
|
FTLOCK();
|
2010-02-03 03:18:00 -08:00
|
|
|
FT_Activate_Size(fi->ft.size);
|
2011-08-11 07:14:48 -07:00
|
|
|
FTUNLOCK();
|
2010-02-03 03:18:00 -08:00
|
|
|
fi->src->current_size = fi->size;
|
|
|
|
}
|
2005-03-20 07:57:55 -08:00
|
|
|
val = -(int)fi->src->ft.face->size->metrics.descender;
|
2010-05-01 07:08:14 -07:00
|
|
|
return val >> 6;
|
|
|
|
// if (fi->src->ft.face->units_per_EM == 0)
|
|
|
|
// return val;
|
|
|
|
// dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
|
|
|
|
// ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
|
|
|
|
// return ret;
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
|
|
|
|
2006-09-06 00:33:40 -07:00
|
|
|
EAPI int
|
2002-11-13 21:38:10 -08:00
|
|
|
evas_common_font_max_ascent_get(RGBA_Font *fn)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2004-01-26 00:21:00 -08:00
|
|
|
int val, dv;
|
2002-11-08 00:02:15 -08:00
|
|
|
int ret;
|
2005-03-20 07:57:55 -08:00
|
|
|
RGBA_Font_Int *fi;
|
2005-05-21 19:49:48 -07:00
|
|
|
|
2010-02-03 03:18:00 -08:00
|
|
|
// evas_common_font_size_use(fn);
|
2005-03-20 07:57:55 -08:00
|
|
|
fi = fn->fonts->data;
|
2011-08-11 07:14:48 -07:00
|
|
|
evas_common_font_int_reload(fi);
|
2010-10-29 05:55:42 -07:00
|
|
|
if (fi->src->current_size != fi->size)
|
2010-02-03 03:18:00 -08:00
|
|
|
{
|
2011-08-11 07:14:48 -07:00
|
|
|
FTLOCK();
|
2010-02-03 03:18:00 -08:00
|
|
|
FT_Activate_Size(fi->ft.size);
|
2011-08-11 07:14:48 -07:00
|
|
|
FTUNLOCK();
|
2010-02-03 03:18:00 -08:00
|
|
|
fi->src->current_size = fi->size;
|
|
|
|
}
|
2012-06-09 20:23:57 -07:00
|
|
|
if ((fi->src->ft.face->bbox.yMax == 0) &&
|
|
|
|
(fi->src->ft.face->bbox.yMin == 0) &&
|
|
|
|
(fi->src->ft.face->units_per_EM == 0))
|
|
|
|
val = (int)fi->src->ft.face->size->metrics.ascender / 64;
|
|
|
|
else
|
|
|
|
val = (int)fi->src->ft.face->bbox.yMax;
|
2006-03-19 02:50:33 -08:00
|
|
|
if (fi->src->ft.face->units_per_EM == 0)
|
2009-04-23 21:35:52 -07:00
|
|
|
return val;
|
2005-05-21 19:49:48 -07:00
|
|
|
dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
|
2005-03-20 07:57:55 -08:00
|
|
|
ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
|
2002-11-08 00:02:15 -08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2006-09-06 00:33:40 -07:00
|
|
|
EAPI int
|
2002-11-13 21:38:10 -08:00
|
|
|
evas_common_font_max_descent_get(RGBA_Font *fn)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2004-01-26 00:21:00 -08:00
|
|
|
int val, dv;
|
2002-11-08 00:02:15 -08:00
|
|
|
int ret;
|
2005-03-20 07:57:55 -08:00
|
|
|
RGBA_Font_Int *fi;
|
2005-05-21 19:49:48 -07:00
|
|
|
|
2010-02-03 03:18:00 -08:00
|
|
|
// evas_common_font_size_use(fn);
|
2005-03-20 07:57:55 -08:00
|
|
|
fi = fn->fonts->data;
|
2010-10-29 05:55:42 -07:00
|
|
|
evas_common_font_int_reload(fi);
|
2010-02-03 03:18:00 -08:00
|
|
|
if (fi->src->current_size != fi->size)
|
|
|
|
{
|
2011-08-11 07:14:48 -07:00
|
|
|
FTLOCK();
|
2010-02-03 03:18:00 -08:00
|
|
|
FT_Activate_Size(fi->ft.size);
|
2011-08-11 07:14:48 -07:00
|
|
|
FTUNLOCK();
|
2010-02-03 03:18:00 -08:00
|
|
|
fi->src->current_size = fi->size;
|
|
|
|
}
|
2012-06-09 20:23:57 -07:00
|
|
|
if ((fi->src->ft.face->bbox.yMax == 0) &&
|
|
|
|
(fi->src->ft.face->bbox.yMin == 0) &&
|
|
|
|
(fi->src->ft.face->units_per_EM == 0))
|
|
|
|
val = -(int)fi->src->ft.face->size->metrics.descender / 64;
|
|
|
|
else
|
|
|
|
val = -(int)fi->src->ft.face->bbox.yMin;
|
2006-03-19 02:50:33 -08:00
|
|
|
if (fi->src->ft.face->units_per_EM == 0)
|
2009-04-23 21:35:52 -07:00
|
|
|
return val;
|
2005-05-21 19:49:48 -07:00
|
|
|
dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
|
2005-03-20 07:57:55 -08:00
|
|
|
ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
|
2002-11-08 00:02:15 -08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2006-09-06 00:33:40 -07:00
|
|
|
EAPI int
|
2002-11-13 21:38:10 -08:00
|
|
|
evas_common_font_get_line_advance(RGBA_Font *fn)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2010-08-16 03:46:56 -07:00
|
|
|
int val;
|
2005-03-20 07:57:55 -08:00
|
|
|
RGBA_Font_Int *fi;
|
2005-05-21 19:49:48 -07:00
|
|
|
|
2010-02-03 03:18:00 -08:00
|
|
|
// evas_common_font_size_use(fn);
|
2005-03-20 07:57:55 -08:00
|
|
|
fi = fn->fonts->data;
|
2010-10-29 05:55:42 -07:00
|
|
|
evas_common_font_int_reload(fi);
|
2010-02-03 03:18:00 -08:00
|
|
|
if (fi->src->current_size != fi->size)
|
|
|
|
{
|
2011-08-11 07:14:48 -07:00
|
|
|
FTLOCK();
|
2010-02-03 03:18:00 -08:00
|
|
|
FT_Activate_Size(fi->ft.size);
|
2011-08-11 07:14:48 -07:00
|
|
|
FTUNLOCK();
|
2010-02-03 03:18:00 -08:00
|
|
|
fi->src->current_size = fi->size;
|
|
|
|
}
|
2005-03-20 07:57:55 -08:00
|
|
|
val = (int)fi->src->ft.face->size->metrics.height;
|
2012-06-19 21:53:21 -07:00
|
|
|
if ((fi->src->ft.face->bbox.yMax == 0) &&
|
|
|
|
(fi->src->ft.face->bbox.yMin == 0) &&
|
|
|
|
(fi->src->ft.face->units_per_EM == 0))
|
|
|
|
return val >> 6;
|
|
|
|
else if (fi->src->ft.face->units_per_EM == 0)
|
2009-04-23 21:35:52 -07:00
|
|
|
return val;
|
2010-05-01 07:08:14 -07:00
|
|
|
return val >> 6;
|
|
|
|
// dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
|
|
|
|
// ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
|
|
|
|
// return ret;
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
|
|
|
|
2011-05-04 01:27:19 -07:00
|
|
|
/* Set of common functions that are used in a couple of places. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
_fash_int2_free(Fash_Int_Map2 *fash)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < 256; i++) if (fash->bucket[i]) free(fash->bucket[i]);
|
|
|
|
free(fash);
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
int grp, maj, min;
|
|
|
|
|
|
|
|
// 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
|
|
|
|
grp = (item >> 16) & 0xff;
|
|
|
|
maj = (item >> 8) & 0xff;
|
|
|
|
min = item & 0xff;
|
|
|
|
if (!fash->bucket[grp]) return NULL;
|
|
|
|
if (!fash->bucket[grp]->bucket[maj]) return NULL;
|
|
|
|
return &(fash->bucket[grp]->bucket[maj]->item[min]);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-05-26 18:44:10 -07:00
|
|
|
_fash_int_add(Fash_Int *fash, int item, RGBA_Font_Int *fint, int idx)
|
2011-05-04 01:27:19 -07:00
|
|
|
{
|
|
|
|
int grp, maj, min;
|
|
|
|
|
|
|
|
// 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
|
|
|
|
grp = (item >> 16) & 0xff;
|
|
|
|
maj = (item >> 8) & 0xff;
|
|
|
|
min = item & 0xff;
|
|
|
|
if (!fash->bucket[grp])
|
|
|
|
fash->bucket[grp] = calloc(1, sizeof(Fash_Int_Map2));
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]);
|
|
|
|
if (!fash->bucket[grp]->bucket[maj])
|
|
|
|
fash->bucket[grp]->bucket[maj] = calloc(1, sizeof(Fash_Int_Map));
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]->bucket[maj]);
|
|
|
|
fash->bucket[grp]->bucket[maj]->item[min].fint = fint;
|
2011-05-26 18:44:10 -07:00
|
|
|
fash->bucket[grp]->bucket[maj]->item[min].index = idx;
|
2011-05-04 01:27:19 -07:00
|
|
|
}
|
|
|
|
|
2012-07-04 03:21:06 -07:00
|
|
|
static void
|
|
|
|
_fash_glyph_free(Fash_Glyph_Map *fmap)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i <= 0xff; i++)
|
|
|
|
{
|
|
|
|
RGBA_Font_Glyph *fg = fmap->item[i];
|
|
|
|
if ((fg) && (fg != (void *)(-1)))
|
|
|
|
{
|
|
|
|
FT_Done_Glyph(fg->glyph);
|
|
|
|
/* extension calls */
|
|
|
|
if (fg->ext_dat_free) fg->ext_dat_free(fg->ext_dat);
|
|
|
|
if (fg->glyph_out_free) fg->glyph_out_free(fg->glyph_out);
|
|
|
|
free(fg);
|
|
|
|
fmap->item[i] = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(fmap);
|
|
|
|
}
|
|
|
|
|
2011-05-04 01:27:19 -07:00
|
|
|
static void
|
|
|
|
_fash_gl2_free(Fash_Glyph_Map2 *fash)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2012-07-04 03:21:06 -07:00
|
|
|
// 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
|
|
|
|
for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_glyph_free(fash->bucket[i]);
|
2011-05-04 01:27:19 -07:00
|
|
|
free(fash);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_fash_gl_free(Fash_Glyph *fash)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2012-07-04 03:21:06 -07:00
|
|
|
// 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
|
2011-05-04 01:27:19 -07:00
|
|
|
for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_gl2_free(fash->bucket[i]);
|
|
|
|
free(fash);
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
int grp, maj, min;
|
|
|
|
|
|
|
|
// 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
|
|
|
|
grp = (item >> 16) & 0xff;
|
|
|
|
maj = (item >> 8) & 0xff;
|
|
|
|
min = item & 0xff;
|
|
|
|
if (!fash->bucket[grp]) return NULL;
|
|
|
|
if (!fash->bucket[grp]->bucket[maj]) return NULL;
|
|
|
|
return fash->bucket[grp]->bucket[maj]->item[min];
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_fash_gl_add(Fash_Glyph *fash, int item, RGBA_Font_Glyph *glyph)
|
|
|
|
{
|
|
|
|
int grp, maj, min;
|
|
|
|
|
|
|
|
// 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
|
|
|
|
grp = (item >> 16) & 0xff;
|
|
|
|
maj = (item >> 8) & 0xff;
|
|
|
|
min = item & 0xff;
|
|
|
|
if (!fash->bucket[grp])
|
|
|
|
fash->bucket[grp] = calloc(1, sizeof(Fash_Glyph_Map2));
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]);
|
|
|
|
if (!fash->bucket[grp]->bucket[maj])
|
|
|
|
fash->bucket[grp]->bucket[maj] = calloc(1, sizeof(Fash_Glyph_Map));
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]->bucket[maj]);
|
|
|
|
fash->bucket[grp]->bucket[maj]->item[min] = glyph;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI RGBA_Font_Glyph *
|
2011-05-26 18:44:10 -07:00
|
|
|
evas_common_font_int_cache_glyph_get(RGBA_Font_Int *fi, FT_UInt idx)
|
2011-05-04 01:27:19 -07:00
|
|
|
{
|
|
|
|
RGBA_Font_Glyph *fg;
|
|
|
|
FT_Error error;
|
|
|
|
const FT_Int32 hintflags[3] =
|
|
|
|
{ FT_LOAD_NO_HINTING, FT_LOAD_FORCE_AUTOHINT, FT_LOAD_NO_AUTOHINT };
|
2012-05-29 07:43:17 -07:00
|
|
|
static FT_Matrix transform = {0x10000, _EVAS_FONT_SLANT_TAN * 0x10000,
|
|
|
|
0x00000, 0x10000};
|
2011-05-04 01:27:19 -07:00
|
|
|
|
|
|
|
evas_common_font_int_promote(fi);
|
|
|
|
if (fi->fash)
|
|
|
|
{
|
2011-05-26 18:44:10 -07:00
|
|
|
fg = _fash_gl_find(fi->fash, idx);
|
2011-05-04 01:27:19 -07:00
|
|
|
if (fg == (void *)(-1)) return NULL;
|
2012-06-22 13:31:31 -07:00
|
|
|
else if (fg)
|
|
|
|
{
|
|
|
|
#ifdef EVAS_CSERVE2
|
|
|
|
if (fi->cs2_handler)
|
|
|
|
evas_cserve2_font_glyph_used(fi->cs2_handler, idx,
|
|
|
|
fi->hinting);
|
|
|
|
#endif
|
|
|
|
return fg;
|
|
|
|
}
|
2011-05-04 01:27:19 -07:00
|
|
|
}
|
|
|
|
// fg = eina_hash_find(fi->glyphs, &hindex);
|
|
|
|
// if (fg) return fg;
|
|
|
|
|
|
|
|
evas_common_font_int_reload(fi);
|
|
|
|
FTLOCK();
|
2011-05-26 18:44:10 -07:00
|
|
|
error = FT_Load_Glyph(fi->src->ft.face, idx,
|
2011-05-04 01:27:19 -07:00
|
|
|
FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP |
|
|
|
|
hintflags[fi->hinting]);
|
|
|
|
FTUNLOCK();
|
|
|
|
if (error)
|
|
|
|
{
|
|
|
|
if (!fi->fash) fi->fash = _fash_gl_new();
|
2011-05-26 18:44:10 -07:00
|
|
|
if (fi->fash) _fash_gl_add(fi->fash, idx, (void *)(-1));
|
2011-05-04 01:27:19 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Transform the outline of Glyph according to runtime_rend. */
|
2011-08-01 02:11:42 -07:00
|
|
|
if (fi->runtime_rend & FONT_REND_SLANT)
|
2011-05-04 01:27:19 -07:00
|
|
|
FT_Outline_Transform(&fi->src->ft.face->glyph->outline, &transform);
|
|
|
|
/* Embolden the outline of Glyph according to rundtime_rend. */
|
2011-08-01 02:11:42 -07:00
|
|
|
if (fi->runtime_rend & FONT_REND_WEIGHT)
|
2011-05-04 01:27:19 -07:00
|
|
|
FT_Outline_Embolden(&fi->src->ft.face->glyph->outline,
|
|
|
|
(fi->src->ft.face->size->metrics.x_ppem * 5 * 64) / 100);
|
|
|
|
|
|
|
|
fg = malloc(sizeof(struct _RGBA_Font_Glyph));
|
|
|
|
if (!fg) return NULL;
|
|
|
|
memset(fg, 0, (sizeof(struct _RGBA_Font_Glyph)));
|
|
|
|
|
|
|
|
FTLOCK();
|
|
|
|
error = FT_Get_Glyph(fi->src->ft.face->glyph, &(fg->glyph));
|
|
|
|
FTUNLOCK();
|
|
|
|
if (error)
|
|
|
|
{
|
2011-08-11 07:14:48 -07:00
|
|
|
free(fg);
|
2011-05-04 01:27:19 -07:00
|
|
|
if (!fi->fash) fi->fash = _fash_gl_new();
|
2011-05-26 18:44:10 -07:00
|
|
|
if (fi->fash) _fash_gl_add(fi->fash, idx, (void *)(-1));
|
2011-08-11 07:14:48 -07:00
|
|
|
return NULL;
|
2011-05-04 01:27:19 -07:00
|
|
|
}
|
2012-05-29 07:43:10 -07:00
|
|
|
|
|
|
|
{
|
|
|
|
FT_BBox outbox;
|
2012-06-18 08:43:49 -07:00
|
|
|
FT_Glyph_Get_CBox(fg->glyph,
|
|
|
|
((fi->hinting == 0) ? FT_GLYPH_BBOX_UNSCALED :
|
|
|
|
FT_GLYPH_BBOX_GRIDFIT),
|
2012-06-17 00:18:50 -07:00
|
|
|
&outbox);
|
2012-05-29 07:43:10 -07:00
|
|
|
fg->width = EVAS_FONT_ROUND_26_6_TO_INT(outbox.xMax - outbox.xMin);
|
|
|
|
fg->x_bear = EVAS_FONT_ROUND_26_6_TO_INT(outbox.xMin);
|
2012-06-22 13:31:31 -07:00
|
|
|
fg->y_bear = EVAS_FONT_ROUND_26_6_TO_INT(outbox.yMax);
|
2012-05-29 07:43:10 -07:00
|
|
|
}
|
2011-05-18 06:47:37 -07:00
|
|
|
|
2012-05-15 14:15:08 -07:00
|
|
|
fg->index = idx;
|
|
|
|
fg->fi = fi;
|
|
|
|
|
|
|
|
if (!fi->fash) fi->fash = _fash_gl_new();
|
|
|
|
if (fi->fash) _fash_gl_add(fi->fash, idx, fg);
|
|
|
|
|
2012-06-22 13:31:31 -07:00
|
|
|
#ifdef EVAS_CSERVE2
|
|
|
|
if (fi->cs2_handler)
|
|
|
|
evas_cserve2_font_glyph_request(fi->cs2_handler, idx, fi->hinting);
|
|
|
|
#endif
|
|
|
|
|
2012-05-15 14:15:08 -07:00
|
|
|
// eina_hash_direct_add(fi->glyphs, &fg->index, fg);
|
|
|
|
return fg;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Eina_Bool
|
|
|
|
evas_common_font_int_cache_glyph_render(RGBA_Font_Glyph *fg)
|
|
|
|
{
|
|
|
|
int size;
|
|
|
|
FT_Error error;
|
|
|
|
RGBA_Font_Int *fi = fg->fi;
|
2012-06-22 13:31:31 -07:00
|
|
|
FT_BitmapGlyph fbg;
|
|
|
|
|
|
|
|
#ifdef EVAS_CSERVE2
|
|
|
|
if (fi->cs2_handler)
|
|
|
|
{
|
|
|
|
fg->glyph_out = evas_cserve2_font_glyph_bitmap_get(fi->cs2_handler,
|
|
|
|
fg->index,
|
|
|
|
fg->fi->hinting);
|
|
|
|
if (fg->glyph_out)
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* no cserve2 case */
|
2011-05-18 06:47:37 -07:00
|
|
|
FTLOCK();
|
|
|
|
error = FT_Glyph_To_Bitmap(&(fg->glyph), FT_RENDER_MODE_NORMAL, 0, 1);
|
|
|
|
if (error)
|
2011-05-04 01:27:19 -07:00
|
|
|
{
|
2011-05-18 06:47:37 -07:00
|
|
|
FT_Done_Glyph(fg->glyph);
|
2011-05-04 01:27:19 -07:00
|
|
|
FTUNLOCK();
|
2011-05-18 06:47:37 -07:00
|
|
|
free(fg);
|
|
|
|
if (!fi->fash) fi->fash = _fash_gl_new();
|
2012-05-15 14:15:08 -07:00
|
|
|
if (fi->fash) _fash_gl_add(fi->fash, fg->index, (void *)(-1));
|
|
|
|
return EINA_FALSE;
|
2011-05-04 01:27:19 -07:00
|
|
|
}
|
2011-05-18 06:47:37 -07:00
|
|
|
FTUNLOCK();
|
|
|
|
|
2012-06-22 13:31:31 -07:00
|
|
|
fbg = (FT_BitmapGlyph)fg->glyph;
|
|
|
|
|
|
|
|
fg->glyph_out = malloc(sizeof(RGBA_Font_Glyph_Out));
|
|
|
|
fg->glyph_out->bitmap.rows = fbg->bitmap.rows;
|
|
|
|
fg->glyph_out->bitmap.width = fbg->bitmap.width;
|
|
|
|
fg->glyph_out->bitmap.pitch = fbg->bitmap.pitch;
|
|
|
|
fg->glyph_out->bitmap.buffer = fbg->bitmap.buffer;
|
|
|
|
fg->glyph_out->bitmap.num_grays = fbg->bitmap.num_grays;
|
|
|
|
fg->glyph_out->bitmap.pixel_mode = fbg->bitmap.pixel_mode;
|
|
|
|
|
|
|
|
fg->glyph_out_free = free;
|
2011-05-04 01:27:19 -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. */
|
|
|
|
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);
|
|
|
|
|
2012-05-15 14:15:08 -07:00
|
|
|
return EINA_TRUE;
|
2011-05-04 01:27:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct _Font_Char_Index Font_Char_Index;
|
|
|
|
struct _Font_Char_Index
|
|
|
|
{
|
|
|
|
FT_UInt index;
|
|
|
|
Eina_Unicode gl;
|
|
|
|
};
|
|
|
|
|
|
|
|
EAPI FT_UInt
|
|
|
|
evas_common_get_char_index(RGBA_Font_Int* fi, Eina_Unicode gl)
|
|
|
|
{
|
2012-06-22 19:32:30 -07:00
|
|
|
static const unsigned short mapfix[] =
|
2012-06-21 06:48:59 -07:00
|
|
|
{
|
|
|
|
0x00b0, 0x7,
|
|
|
|
0x00b1, 0x8,
|
2012-06-22 19:32:30 -07:00
|
|
|
0x00b7, 0x1f,
|
|
|
|
0x03c0, 0x1c,
|
|
|
|
0x20a4, 0xa3,
|
|
|
|
0x2260, 0x1d,
|
|
|
|
0x2264, 0x1a,
|
|
|
|
0x2265, 0x1b,
|
2012-06-21 06:48:59 -07:00
|
|
|
0x23ba, 0x10,
|
|
|
|
0x23bb, 0x11,
|
|
|
|
0x23bc, 0x13,
|
|
|
|
0x23bd, 0x14,
|
2012-06-22 19:32:30 -07:00
|
|
|
0x2409, 0x3,
|
|
|
|
0x240a, 0x6,
|
|
|
|
0x240b, 0xa,
|
|
|
|
0x240c, 0x4,
|
|
|
|
0x240d, 0x5,
|
|
|
|
0x2424, 0x9,
|
|
|
|
0x2500, 0x12,
|
|
|
|
0x2502, 0x19,
|
|
|
|
0x250c, 0xd,
|
|
|
|
0x2510, 0xc,
|
|
|
|
0x2514, 0xe,
|
|
|
|
0x2518, 0xb,
|
2012-06-21 06:48:59 -07:00
|
|
|
0x251c, 0x15,
|
|
|
|
0x2524, 0x16,
|
|
|
|
0x252c, 0x18,
|
2012-06-22 19:32:30 -07:00
|
|
|
0x2534, 0x17,
|
|
|
|
0x253c, 0xf,
|
|
|
|
0x2592, 0x2,
|
|
|
|
0x25c6, 0x1,
|
2012-06-21 06:48:59 -07:00
|
|
|
};
|
2011-05-04 01:27:19 -07:00
|
|
|
Font_Char_Index result;
|
|
|
|
//FT_UInt ret;
|
|
|
|
|
|
|
|
#ifdef HAVE_PTHREAD
|
|
|
|
/// pthread_mutex_lock(&fi->ft_mutex);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
// }
|
|
|
|
|
|
|
|
evas_common_font_int_reload(fi);
|
2012-07-04 02:39:23 -07:00
|
|
|
/*
|
|
|
|
* There is no point in locking FreeType at this point as all caller
|
|
|
|
* are running in the main loop at a time where there is zero chance
|
|
|
|
* that something else try to use it.
|
|
|
|
*/
|
|
|
|
/* FTLOCK(); */
|
2011-05-04 01:27:19 -07:00
|
|
|
result.index = FT_Get_Char_Index(fi->src->ft.face, gl);
|
2012-07-04 02:39:23 -07:00
|
|
|
/* FTUNLOCK(); */
|
2011-05-04 01:27:19 -07:00
|
|
|
result.gl = gl;
|
|
|
|
|
|
|
|
// eina_hash_direct_add(fi->indexes, &result->gl, result);
|
|
|
|
//
|
|
|
|
// on_correct:
|
|
|
|
#ifdef HAVE_PTHREAD
|
|
|
|
// pthread_mutex_unlock(&fi->ft_mutex);
|
|
|
|
#endif
|
2012-06-22 19:32:30 -07:00
|
|
|
// this is a workaround freetype bugs where for a bitmap old style font
|
|
|
|
// even if it has unicode information and mappings, they are not used
|
|
|
|
// to find terminal line/drawing chars, so do this by hand with a table
|
|
|
|
if ((result.index <= 0) && (fi->src->ft.face->num_fixed_sizes == 1) &&
|
|
|
|
(fi->src->ft.face->num_glyphs < 512))
|
2012-06-21 06:48:59 -07:00
|
|
|
{
|
2012-06-22 19:32:30 -07:00
|
|
|
int i, min = 0, max;
|
|
|
|
|
|
|
|
// binary search through sorted table of codepoints to new
|
|
|
|
// codepoints with a guess that bitmap font is playing the old
|
|
|
|
// game of putting line drawing chars in specific ranges
|
|
|
|
max = sizeof(mapfix) / (sizeof(mapfix[0]) * 2);
|
|
|
|
i = (min + max) / 2;
|
|
|
|
for (;;)
|
2012-06-21 06:48:59 -07:00
|
|
|
{
|
2012-06-22 19:32:30 -07:00
|
|
|
unsigned short v;
|
|
|
|
|
|
|
|
v = mapfix[i << 1];
|
|
|
|
if (gl == v)
|
2012-06-21 06:48:59 -07:00
|
|
|
{
|
2012-06-22 19:32:30 -07:00
|
|
|
gl = mapfix[(i << 1) + 1];
|
2012-06-21 06:48:59 -07:00
|
|
|
FTLOCK();
|
|
|
|
result.index = FT_Get_Char_Index(fi->src->ft.face, gl);
|
|
|
|
FTUNLOCK();
|
|
|
|
break;
|
|
|
|
}
|
2012-06-22 19:32:30 -07:00
|
|
|
// failure to find at all
|
|
|
|
if ((max - min) <= 2) break;
|
|
|
|
// if glyph above out position...
|
|
|
|
if (gl > v)
|
|
|
|
{
|
|
|
|
min = i;
|
2012-07-06 02:53:58 -07:00
|
|
|
if ((max - min) == 1) i = max;
|
2012-06-22 19:32:30 -07:00
|
|
|
else i = (min + max) / 2;
|
|
|
|
}
|
|
|
|
// if glyph below out position
|
|
|
|
else if (gl < v)
|
|
|
|
{
|
|
|
|
max = i;
|
2012-07-06 02:53:58 -07:00
|
|
|
if ((max - min) == 1) i = min;
|
2012-06-22 19:32:30 -07:00
|
|
|
else i = (min + max) / 2;
|
|
|
|
}
|
2012-06-21 06:48:59 -07:00
|
|
|
}
|
|
|
|
}
|
2011-05-04 01:27:19 -07:00
|
|
|
return result.index;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI int
|
|
|
|
evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, Eina_Unicode gl)
|
|
|
|
{
|
|
|
|
Eina_List *l;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (l = fn->fonts; l; l = l->next)
|
|
|
|
{
|
2011-08-11 07:14:48 -07:00
|
|
|
RGBA_Font_Int *fi;
|
|
|
|
int idx;
|
2011-05-04 01:27:19 -07:00
|
|
|
|
2011-08-11 07:14:48 -07:00
|
|
|
fi = l->data;
|
2011-05-04 01:27:19 -07:00
|
|
|
|
|
|
|
#if 0 /* FIXME: charmap user is disabled and use a deprecated data type. */
|
|
|
|
/*
|
|
|
|
if (fi->src->charmap) // Charmap loaded, FI/FS blank
|
|
|
|
{
|
2011-05-26 18:44:10 -07:00
|
|
|
idx = evas_array_hash_search(fi->src->charmap, gl);
|
|
|
|
if (idx != 0)
|
2011-05-04 01:27:19 -07:00
|
|
|
{
|
|
|
|
evas_common_font_source_load_complete(fi->src);
|
|
|
|
evas_common_font_int_load_complete(fi);
|
|
|
|
|
|
|
|
evas_array_hash_free(fi->src->charmap);
|
|
|
|
fi->src->charmap = NULL;
|
|
|
|
|
|
|
|
*fi_ret = fi;
|
2011-05-26 18:44:10 -07:00
|
|
|
return idx;
|
2011-05-04 01:27:19 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*/
|
|
|
|
#endif
|
|
|
|
if (!fi->src->ft.face) /* Charmap not loaded, FI/FS blank */
|
2011-08-11 07:14:48 -07:00
|
|
|
{
|
2011-05-04 01:27:19 -07:00
|
|
|
evas_common_font_int_reload(fi);
|
2011-08-11 07:14:48 -07:00
|
|
|
}
|
2011-05-04 01:27:19 -07:00
|
|
|
if (fi->src->ft.face)
|
2011-08-11 07:14:48 -07:00
|
|
|
{
|
|
|
|
idx = evas_common_get_char_index(fi, gl);
|
|
|
|
if (idx != 0)
|
|
|
|
{
|
|
|
|
if (!fi->ft.size)
|
|
|
|
evas_common_font_int_load_complete(fi);
|
2011-05-04 01:27:19 -07:00
|
|
|
if (!fn->fash) fn->fash = _fash_int_new();
|
2011-05-26 18:44:10 -07:00
|
|
|
if (fn->fash) _fash_int_add(fn->fash, gl, fi, idx);
|
2011-08-11 07:14:48 -07:00
|
|
|
*fi_ret = fi;
|
|
|
|
return idx;
|
|
|
|
}
|
2011-05-04 01:27:19 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!fn->fash) fn->fash = _fash_int_new();
|
|
|
|
if (fn->fash) _fash_int_add(fn->fash, gl, NULL, -1);
|
|
|
|
}
|
2011-08-11 07:14:48 -07:00
|
|
|
}
|
2011-05-04 01:27:19 -07:00
|
|
|
}
|
2011-05-29 02:20:13 -07:00
|
|
|
*fi_ret = NULL;
|
2011-05-04 01:27:19 -07:00
|
|
|
return 0;
|
|
|
|
}
|