Evas font+textblock: Stopped using FcNameParse, parse ourselves.

FcNameParse is pretty bad, not only that it's pretty bad, it doesn't
work well in some cases. Also this makes our lives a lot easier since
we want to allow overriding style/weight/width and etc from markup.
We now parse the "font" markup ourselves, populating a font description
structure that we created, and then override values in it as needed.

SVN revision: 61936
This commit is contained in:
Tom Hacohen 2011-08-01 08:20:52 +00:00
parent 7239b6894f
commit 9ba3e192a5
4 changed files with 394 additions and 226 deletions

View File

@ -26,9 +26,9 @@ typedef struct _Fndat Fndat;
struct _Fndat
{
const char *name;
Evas_Font_Description *fdesc;
const char *source;
int size;
Evas_Font_Size size;
Evas_Font_Set *font;
int ref;
Font_Rend_Flags wanted_rend;
@ -136,7 +136,7 @@ evas_fonts_zero_free(Evas *evas)
EINA_LIST_FREE(fonts_zero, fd)
{
if (fd->name) eina_stringshare_del(fd->name);
if (fd->fdesc) evas_font_desc_unref(fd->fdesc);
if (fd->source) eina_stringshare_del(fd->source);
evas->engine.func->font_free(evas->engine.data.output, fd->font);
#ifdef HAVE_FONTCONFIG
@ -160,7 +160,7 @@ evas_fonts_zero_presure(Evas *evas)
if (fd->ref != 0) break;
fonts_zero = eina_list_remove_list(fonts_zero, fonts_zero);
if (fd->name) eina_stringshare_del(fd->name);
if (fd->fdesc) evas_font_desc_unref(fd->fdesc);
if (fd->source) eina_stringshare_del(fd->source);
evas->engine.func->font_free(evas->engine.data.output, fd->font);
#ifdef HAVE_FONTCONFIG
@ -200,7 +200,7 @@ evas_font_free(Evas *evas, void *font)
if (fd->ref != 0) break;
fonts_zero = eina_list_remove_list(fonts_zero, fonts_zero);
if (fd->name) eina_stringshare_del(fd->name);
if (fd->fdesc) evas_font_desc_unref(fd->fdesc);
if (fd->source) eina_stringshare_del(fd->source);
evas->engine.func->font_free(evas->engine.data.output, fd->font);
#ifdef HAVE_FONTCONFIG
@ -254,45 +254,6 @@ evas_load_fontconfig(Evas *evas, FcFontSet *set, int size,
}
#endif
static Eina_Bool
_font_style_name_match(const char *font_name, const char *style_name)
{
char *style_key = NULL;
style_key = strchr(font_name, ':');
if (!style_key) return EINA_FALSE;
if (strlen(style_key) > 2) style_key++;
if (strstr(style_key, "style="))
{
if (!strcmp(style_name, "Italic"))
{
if (strstr(style_key, "Italic")
|| strstr(style_key, "italic")
|| strstr(style_key, "Cursiva")
|| strstr(style_key, "cursiva")
|| strstr(style_key, "Oblique")
|| strstr(style_key, "oblique"))
return EINA_TRUE;
else
return EINA_FALSE;
}
else if (!strcmp(style_name, "Bold"))
{
if (strstr(style_key, "Bold")
|| strstr(style_key, "bold")
|| strstr(style_key, "Negreta")
|| strstr(style_key, "negreta"))
return EINA_TRUE;
else
return EINA_FALSE;
}
else
return EINA_FALSE;
}
else
return EINA_FALSE;
}
struct _FcPattern {
int num;
int size;
@ -300,8 +261,235 @@ struct _FcPattern {
int ref;
};
#ifdef HAVE_FONTCONFIG
/* In sync with Evas_Font_Style, Evas_Font_Weight and Evas_Font_Width */
static int _fc_slant_map[] =
{
FC_SLANT_ROMAN,
FC_SLANT_OBLIQUE,
FC_SLANT_ITALIC
};
static int _fc_weight_map[] =
{
FC_WEIGHT_NORMAL,
FC_WEIGHT_THIN,
FC_WEIGHT_ULTRALIGHT,
FC_WEIGHT_LIGHT,
FC_WEIGHT_BOOK,
FC_WEIGHT_MEDIUM,
FC_WEIGHT_SEMIBOLD,
FC_WEIGHT_BOLD,
FC_WEIGHT_ULTRABOLD,
FC_WEIGHT_BLACK,
FC_WEIGHT_EXTRABLACK
};
# ifdef FC_WIDTH
static int _fc_width_map[] =
{
FC_WIDTH_NORMAL,
FC_WIDTH_ULTRACONDENSED,
FC_WIDTH_EXTRACONDENSED,
FC_WIDTH_CONDENSED,
FC_WIDTH_SEMICONDENSED,
FC_WIDTH_SEMIEXPANDED,
FC_WIDTH_EXPANDED,
FC_WIDTH_EXTRAEXPANDED,
FC_WIDTH_ULTRAEXPANDED
};
# endif
#endif
struct _Style_Map
{
const char *name;
int type;
};
typedef struct _Style_Map Style_Map;
static Style_Map _style_width_map[] =
{
{"normal", EVAS_FONT_WIDTH_NORMAL},
{"ultracondensed", EVAS_FONT_WIDTH_ULTRACONDENSED},
{"extracondensed", EVAS_FONT_WIDTH_EXTRACONDENSED},
{"condensed", EVAS_FONT_WIDTH_CONDENSED},
{"semicondensed", EVAS_FONT_WIDTH_SEMICONDENSED},
{"semiexpanded", EVAS_FONT_WIDTH_SEMIEXPANDED},
{"expanded", EVAS_FONT_WIDTH_EXPANDED},
{"extraexpanded", EVAS_FONT_WIDTH_EXTRAEXPANDED},
{"ultraexpanded", EVAS_FONT_WIDTH_ULTRAEXPANDED},
};
static Style_Map _style_weight_map[] =
{
{"normal", EVAS_FONT_WEIGHT_NORMAL},
{"thin", EVAS_FONT_WEIGHT_THIN},
{"ultralight", EVAS_FONT_WEIGHT_ULTRALIGHT},
{"light", EVAS_FONT_WEIGHT_LIGHT},
{"book", EVAS_FONT_WEIGHT_BOOK},
{"medium", EVAS_FONT_WEIGHT_MEDIUM},
{"semibold", EVAS_FONT_WEIGHT_SEMIBOLD},
{"bold", EVAS_FONT_WEIGHT_BOLD},
{"ultrabold", EVAS_FONT_WEIGHT_ULTRABOLD},
{"black", EVAS_FONT_WEIGHT_BLACK},
{"extrablack", EVAS_FONT_WEIGHT_EXTRABLACK}
};
static Style_Map _style_slant_map[] =
{
{"normal", EVAS_FONT_SLANT_NORMAL},
{"oblique", EVAS_FONT_SLANT_OBLIQUE},
{"italic", EVAS_FONT_SLANT_ITALIC}
};
#define _STYLE_MAP_LEN(x) (sizeof(x) / sizeof(*(x)))
/**
* @internal
* Find a certain attribute from the map in the style.
* @return the index of the found one.
*/
static int
_evas_font_style_find_internal(const char *style, const char *style_end,
Style_Map _map[], size_t map_len)
{
size_t i;
while (style < style_end)
{
for (i = 0 ; i < map_len ; i++)
{
size_t len;
const char *cur = _map[i].name;
len = strlen(cur);
if (!strncasecmp(style, cur, len) &&
(!cur[len] || (cur[len] == ' ')))
{
return _map[i].type;
}
}
style = strchr(style, ' ');
if (!style)
break;
while (*style && (*style == ' '))
style++;
}
return 0;
}
int
evas_font_style_find(const char *start, const char *end,
Evas_Font_Style style)
{
#define _RET_STYLE(x) \
return _evas_font_style_find_internal(start, end, \
_style_##x##_map, _STYLE_MAP_LEN(_style_##x##_map));
switch (style)
{
case EVAS_FONT_STYLE_SLANT:
_RET_STYLE(slant);
case EVAS_FONT_STYLE_WEIGHT:
_RET_STYLE(weight);
case EVAS_FONT_STYLE_WIDTH:
_RET_STYLE(width);
default:
return 0;
}
#undef _RET_STYLE
}
void
evas_font_desc_unref(Evas_Font_Description *fdesc)
{
if (--(fdesc->ref) == 0)
{
eina_stringshare_del(fdesc->name);
free(fdesc);
}
}
Evas_Font_Description *
evas_font_desc_ref(Evas_Font_Description *fdesc)
{
fdesc->ref++;
return fdesc;
}
Evas_Font_Description *
evas_font_desc_new(void)
{
Evas_Font_Description *fdesc;
fdesc = calloc(1, sizeof(*fdesc));
fdesc->ref = 1;
fdesc->new = EINA_TRUE;
return fdesc;
}
Evas_Font_Description *
evas_font_desc_dup(const Evas_Font_Description *fdesc)
{
Evas_Font_Description *new;
new = evas_font_desc_new();
memcpy(new, fdesc, sizeof(*new));
new->ref = 1;
new->new = EINA_TRUE;
new->name = eina_stringshare_ref(new->name);
return new;
}
int
evas_font_desc_cmp(const Evas_Font_Description *a,
const Evas_Font_Description *b)
{
/* FIXME: Do actual comparison, i.e less than and bigger than. */
return !((a->name == b->name) && (a->weight == b->weight) &&
(a->slant == b->slant) && (a->width == b->width) &&
(a->lang == b->lang));
}
void
evas_font_name_parse(Evas_Font_Description *fdesc, const char *name)
{
const char *end;
end = strchr(name, ':');
if (!end)
fdesc->name = eina_stringshare_add(name);
else
fdesc->name = eina_stringshare_add_length(name, end - name);
while (end)
{
const char *tend;
name = end;
end = strchr(end + 1, ':');
if (!end)
tend = name + strlen(name);
else
tend = end;
if (!strncmp(name, ":style=", 7))
{
#define _SET_STYLE(x) \
fdesc->x = _evas_font_style_find_internal(name + 7, tend, \
_style_##x##_map, _STYLE_MAP_LEN(_style_##x##_map));
_SET_STYLE(slant);
_SET_STYLE(weight);
_SET_STYLE(width);
#undef _SET_STYLE
}
else if (!strncmp(name, ":lang=", 6))
{
/* FIXME: handle lang. */
}
}
}
void *
evas_font_load(Evas *evas, const char *name, const char *source, int size)
evas_font_load(Evas *evas, Evas_Font_Description *fdesc, const char *source, Evas_Font_Size size)
{
#ifdef HAVE_FONTCONFIG
FcPattern *p_nm = NULL;
@ -314,24 +502,25 @@ evas_font_load(Evas *evas, const char *name, const char *source, int size)
char *nm;
Font_Rend_Flags wanted_rend = 0;
if (!name) return NULL;
if (name[0] == 0) return NULL;
if (!fdesc) return NULL;
fdesc->new = EINA_FALSE;
if (_font_style_name_match(name, "Italic"))
if (fdesc->slant != EVAS_FONT_SLANT_NORMAL)
wanted_rend |= FONT_REND_ITALIC;
if (_font_style_name_match(name, "Bold"))
if (fdesc->weight == EVAS_FONT_WEIGHT_BOLD)
wanted_rend |= FONT_REND_BOLD;
evas_font_init();
EINA_LIST_FOREACH(fonts_cache, l, fd)
{
if (!strcmp(name, fd->name))
if (!evas_font_desc_cmp(fdesc, fd->fdesc))
{
if (((!source) && (!fd->source)) ||
((source) && (fd->source) && (!strcmp(source, fd->source))))
{
if ((size == fd->size) && (wanted_rend == fd->wanted_rend))
if ((size == fd->size) &&
(wanted_rend == fd->wanted_rend))
{
fonts_cache = eina_list_promote_list(fonts_cache, l);
fd->ref++;
@ -351,12 +540,13 @@ evas_font_load(Evas *evas, const char *name, const char *source, int size)
EINA_LIST_FOREACH(fonts_zero, l, fd)
{
if (!strcmp(name, fd->name))
if (!evas_font_desc_cmp(fdesc, fd->fdesc))
{
if (((!source) && (!fd->source)) ||
((source) && (fd->source) && (!strcmp(source, fd->source))))
{
if ((size == fd->size) && (wanted_rend == fd->wanted_rend))
if ((size == fd->size) &&
(wanted_rend == fd->wanted_rend))
{
fonts_zero = eina_list_remove_list(fonts_zero, l);
fonts_cache = eina_list_prepend(fonts_cache, fd);
@ -375,7 +565,7 @@ evas_font_load(Evas *evas, const char *name, const char *source, int size)
}
}
fonts = evas_font_set_get(name);
fonts = evas_font_set_get(fdesc->name);
EINA_LIST_FOREACH(fonts, l, nm) /* Load each font in append */
{
if (l == fonts || !font) /* First iteration OR no font */
@ -510,7 +700,16 @@ evas_font_load(Evas *evas, const char *name, const char *source, int size)
{
FcResult res;
p_nm = FcNameParse((FcChar8 *)name);
p_nm = FcPatternBuild (NULL,
FC_WEIGHT, FcTypeInteger, _fc_weight_map[fdesc->weight],
FC_SLANT, FcTypeInteger, _fc_slant_map[fdesc->slant],
#ifdef FC_WIDTH
FC_WIDTH, FcTypeInteger, _fc_width_map[fdesc->width],
#endif
NULL);
/* FIXME: Handle font fallbacks!!! */
FcPatternAddString (p_nm, FC_FAMILY, (FcChar8*) fdesc->name);
FcConfigSubstitute(NULL, p_nm, FcMatchPattern);
FcDefaultSubstitute(p_nm);
@ -518,17 +717,12 @@ evas_font_load(Evas *evas, const char *name, const char *source, int size)
set = FcFontSort(NULL, p_nm, FcTrue, NULL, &res);
if (!set)
{
ERR("No fontconfig font matches '%s'. It was the last resource, no font found!", name);
ERR("No fontconfig font matches '%s'. It was the last resource, no font found!", fdesc->name);
FcPatternDestroy(p_nm);
p_nm = NULL;
}
else
{
// FIXME: this i think is a bugfix for a rare bug... but i'm
// not sure 100%. it seems that way from fc. if trim is set
// to FcTrue...
// ok - not a bugfix... but there is something going on somewhere that's weird?
// FcPatternReference(p_nm); /* we have to reference count the pat */
font = evas_load_fontconfig(evas, set, size, wanted_rend);
}
}
@ -538,9 +732,8 @@ evas_font_load(Evas *evas, const char *name, const char *source, int size)
fd = calloc(1, sizeof(Fndat));
if (fd)
{
fd->name = eina_stringshare_add(name);
fd->fdesc = evas_font_desc_ref(fdesc);
if (source) fd->source = eina_stringshare_add(source);
fd->size = size;
fd->font = font;
fd->wanted_rend = wanted_rend;
fd->ref = 1;

View File

@ -19,6 +19,7 @@ struct _Evas_Object_Text
struct {
const char *utf8_text; /* The text exposed to the API */
const char *font;
Evas_Font_Description *fdesc;
const char *source;
Evas_Font_Size size;
struct {
@ -345,7 +346,7 @@ evas_object_text_font_set(Evas_Object *obj, const char *font, Evas_Font_Size siz
{
Evas_Object_Text *o;
int is, was = 0, pass = 0;
int same_font = 0;
Evas_Font_Description *fdesc;
if ((!font) || (size <= 0)) return;
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
@ -356,11 +357,22 @@ evas_object_text_font_set(Evas_Object *obj, const char *font, Evas_Font_Size siz
return;
MAGIC_CHECK_END();
if ((o->cur.font) && (font) && (!strcmp(o->cur.font, font)))
fdesc = evas_font_desc_new();
evas_font_name_parse(fdesc, font);
if (o->cur.fdesc && !evas_font_desc_cmp(fdesc, o->cur.fdesc) &&
(size == o->cur.size))
{
same_font = 1;
if (size == o->cur.size) return;
evas_font_desc_unref(fdesc);
return;
}
if (o->cur.fdesc) evas_font_desc_unref(o->cur.fdesc);
o->cur.fdesc = fdesc;
o->cur.size = size;
eina_stringshare_replace(&o->cur.font, font);
o->prev.font = NULL;
if (obj->layer->evas->events_frozen <= 0)
{
pass = evas_event_passes_through(obj);
@ -381,19 +393,9 @@ evas_object_text_font_set(Evas_Object *obj, const char *font, Evas_Font_Size siz
evas_font_free(obj->layer->evas, o->font);
o->font = NULL;
}
if (!same_font)
{
/*
if (o->cur.font) eina_stringshare_del(o->cur.font);
if (font) o->cur.font = eina_stringshare_add(font);
else o->cur.font = NULL;
*/
eina_stringshare_replace(&o->cur.font, font);
o->prev.font = NULL;
}
o->cur.size = size;
o->font = evas_font_load(obj->layer->evas, o->cur.font, o->cur.source,
(int)(((double)o->cur.size) * obj->cur.scale));
o->font = evas_font_load(obj->layer->evas, o->cur.fdesc, o->cur.source,
(int)(((double) o->cur.size) * obj->cur.scale));
if (o->font)
{
o->ascent = ENFN->font_ascent_get(ENDT, o->font);
@ -1441,6 +1443,7 @@ evas_object_text_free(Evas_Object *obj)
if (o->items) _evas_object_text_items_clear(o);
if (o->cur.utf8_text) eina_stringshare_del(o->cur.utf8_text);
if (o->cur.font) eina_stringshare_del(o->cur.font);
if (o->cur.fdesc) evas_font_desc_unref(o->cur.fdesc);
if (o->cur.source) eina_stringshare_del(o->cur.source);
if (o->font) evas_font_free(obj->layer->evas, o->font);
#ifdef BIDI_SUPPORT

View File

@ -348,11 +348,11 @@ struct _Evas_Object_Textblock_Format
double halign;
double valign;
struct {
const char *name;
Evas_Font_Description *fdesc;
const char *source;
const char *fallbacks;
Evas_Font_Set *font;
int size;
Evas_Font_Size size;
} font;
struct {
struct {
@ -620,7 +620,7 @@ _format_unref_free(const Evas_Object *obj, Evas_Object_Textblock_Format *fmt)
{
fmt->ref--;
if (fmt->ref > 0) return;
if (fmt->font.name) eina_stringshare_del(fmt->font.name);
if (fmt->font.fdesc) evas_font_desc_unref(fmt->font.fdesc);
if (fmt->font.fallbacks) eina_stringshare_del(fmt->font.fallbacks);
if (fmt->font.source) eina_stringshare_del(fmt->font.source);
evas_font_free(obj->layer->evas, fmt->font.font);
@ -1131,95 +1131,6 @@ _format_clean_param(char *dst, const char *src)
*ds = 0;
}
static const char *_style_weight_map[] = { "ultralight", "light", "bold",
"ultrabold", "black", "normal" };
#define _STYLE_WEIGHT_MAP_LEN (sizeof(_style_weight_map) / sizeof(_style_weight_map[0]))
static const char *_style_style_map[] = { "normal", "oblique", "italic" };
#define _STYLE_STYLE_MAP_LEN (sizeof(_style_style_map) / sizeof(_style_style_map[0]))
/**
* @internal
* Find a certain attribute from the map in the style.
* @return true if found, false otherwise.
*/
static Eina_Bool
_format_font_style_find(const char *style, const char *style_end,
const char **start, const char **end, const char *_map[], size_t map_len)
{
size_t i;
while (style < style_end)
{
for (i = 0 ; i < map_len ; i++)
{
size_t len;
const char *cur = _map[i];
len = strlen(cur);
if (!strncasecmp(style, cur, len) &&
(!cur[len] || (cur[len] == ' ')))
{
*start = style;
*end = *start + len;
return EINA_TRUE;
}
}
style = strchr(style, ' ');
if (!style)
break;
while (*style && _is_white(*style))
style++;
}
return EINA_FALSE;
}
static void
_format_command_parse_font_weight_style(Evas_Object_Textblock_Format *fmt,
const char *param, const char *_map[], size_t map_len)
{
size_t flen = eina_stringshare_strlen(fmt->font.name);
const char *style = strstr(fmt->font.name, ":style=");
if (style)
{
Eina_Strbuf *buf;
const char *found_start, *found_end;
const char *style_end = strchr(style + 7, ':');
/* Point to the end, either it be the next attribute,
* or the terminating 0 */
if (!style_end)
style_end = fmt->font.name + flen;
buf = eina_strbuf_new();
eina_strbuf_append_length(buf, fmt->font.name, flen);
if (_format_font_style_find(style + 7, style_end,
&found_start, &found_end, _map, map_len))
{
eina_strbuf_remove(buf, found_start - fmt->font.name,
found_end - fmt->font.name);
}
else
{
found_start = style + 7; /* + 7 for :style= */
eina_strbuf_insert_char(buf, ' ', found_start - fmt->font.name);
}
eina_strbuf_insert(buf, param, found_start - fmt->font.name);
if (fmt->font.name) eina_stringshare_del(fmt->font.name);
fmt->font.name = eina_stringshare_add(eina_strbuf_string_get(buf));
eina_strbuf_free(buf);
}
else
{
/* Make a buffer big enough to hold whatever we do.
* 7 == len(:style=). */
char *tmpres = alloca(flen + strlen(param) + 7 + 1);
/* Handle font.name == NULL */
memcpy(tmpres, fmt->font.name, flen);
sprintf(tmpres + flen, ":style=%s", param);
if (fmt->font.name) eina_stringshare_del(fmt->font.name);
fmt->font.name = eina_stringshare_add(tmpres);
}
}
/**
* @internal
* Parses the cmd and parameter and adds the parsed format to fmt.
@ -1232,7 +1143,6 @@ _format_command_parse_font_weight_style(Evas_Object_Textblock_Format *fmt,
static void
_format_command(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, const char *cmd, const char *param)
{
int new_font = 0;
int len;
char *tmp_param;
@ -1240,15 +1150,26 @@ _format_command(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, const char
tmp_param = alloca(len + 1);
_format_clean_param(tmp_param, param);
/* If we are changing the font, create the fdesc. */
if ((cmd == font_weightstr) || (cmd == font_stylestr) || (cmd == fontstr))
{
if (!fmt->font.fdesc)
{
fmt->font.fdesc = evas_font_desc_new();
}
else if (!fmt->font.fdesc->new)
{
Evas_Font_Description *old = fmt->font.fdesc;
fmt->font.fdesc = evas_font_desc_dup(fmt->font.fdesc);
if (old) evas_font_desc_unref(old);
}
}
if (cmd == fontstr)
{
if ((!fmt->font.name) ||
((fmt->font.name) && (strcmp(fmt->font.name, tmp_param))))
{
if (fmt->font.name) eina_stringshare_del(fmt->font.name);
fmt->font.name = eina_stringshare_add(tmp_param);
new_font = 1;
}
evas_font_name_parse(fmt->font.fdesc, tmp_param);
}
else if (cmd == font_fallbacksstr)
{
@ -1260,7 +1181,6 @@ _format_command(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, const char
*/
if (fmt->font.fallbacks) eina_stringshare_del(fmt->font.fallbacks);
fmt->font.fallbacks = eina_stringshare_add(tmp_param);
new_font = 1;
}
}
else if (cmd == font_sizestr)
@ -1271,7 +1191,6 @@ _format_command(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, const char
if (v != fmt->font.size)
{
fmt->font.size = v;
new_font = 1;
}
}
else if (cmd == font_sourcestr)
@ -1281,20 +1200,17 @@ _format_command(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, const char
{
if (fmt->font.source) eina_stringshare_del(fmt->font.source);
fmt->font.source = eina_stringshare_add(tmp_param);
new_font = 1;
}
}
if (cmd == font_weightstr)
{
_format_command_parse_font_weight_style(fmt, tmp_param,
_style_weight_map, _STYLE_WEIGHT_MAP_LEN);
new_font = 1;
fmt->font.fdesc->weight = evas_font_style_find(tmp_param,
tmp_param + strlen(tmp_param), EVAS_FONT_STYLE_WEIGHT);
}
if (cmd == font_stylestr)
{
_format_command_parse_font_weight_style(fmt, tmp_param,
_style_style_map, _STYLE_STYLE_MAP_LEN);
new_font = 1;
fmt->font.fdesc->slant = evas_font_style_find(tmp_param,
tmp_param + strlen(tmp_param), EVAS_FONT_STYLE_SLANT);
}
else if (cmd == colorstr)
_format_color_parse(tmp_param,
@ -1616,29 +1532,6 @@ _format_command(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, const char
else if (!strcmp(tmp_param, "on"))
fmt->password = 1;
}
if (new_font)
{
void *of;
char *buf = NULL;
of = fmt->font.font;
if ((fmt->font.name) && (fmt->font.fallbacks))
{
buf = malloc(strlen(fmt->font.name) + 1 + strlen(fmt->font.fallbacks) + 1);
strcpy(buf, fmt->font.name);
strcat(buf, ",");
strcat(buf, fmt->font.fallbacks);
}
else if (fmt->font.name)
buf = strdup(fmt->font.name);
fmt->font.font = evas_font_load(obj->layer->evas,
buf, fmt->font.source,
(int)(((double)fmt->font.size) * obj->cur.scale));
if (buf) free(buf);
if (of) evas_font_free(obj->layer->evas, of);
}
}
/**
@ -1796,22 +1689,14 @@ _format_dup(Evas_Object *obj, const Evas_Object_Textblock_Format *fmt)
fmt2 = calloc(1, sizeof(Evas_Object_Textblock_Format));
memcpy(fmt2, fmt, sizeof(Evas_Object_Textblock_Format));
fmt2->ref = 1;
if (fmt->font.name) fmt2->font.name = eina_stringshare_add(fmt->font.name);
fmt2->font.fdesc = evas_font_desc_ref(fmt->font.fdesc);
if (fmt->font.fallbacks) fmt2->font.fallbacks = eina_stringshare_add(fmt->font.fallbacks);
if (fmt->font.source) fmt2->font.source = eina_stringshare_add(fmt->font.source);
if ((fmt2->font.name) && (fmt2->font.fallbacks))
{
buf = malloc(strlen(fmt2->font.name) + 1 + strlen(fmt2->font.fallbacks) + 1);
strcpy(buf, fmt2->font.name);
strcat(buf, ",");
strcat(buf, fmt2->font.fallbacks);
}
else if (fmt2->font.name)
buf = strdup(fmt2->font.name);
fmt2->font.font = evas_font_load(obj->layer->evas,
buf, fmt2->font.source,
(int)(((double)fmt2->font.size) * obj->cur.scale));
/* FIXME: just ref the font here... */
fmt2->font.font = evas_font_load(obj->layer->evas, fmt2->font.fdesc,
fmt2->font.source, (int)(((double) fmt2->font.size) * obj->cur.scale));
if (buf) free(buf);
return fmt2;
}
@ -3065,6 +2950,23 @@ _layout_format_item_add(Ctxt *c, Evas_Object_Textblock_Node_Format *n, const cha
return fi;
}
/**
* @internal
* Should be call after we finish filling a format.
* FIXME: doc.
*/
static void
_format_finalize(Evas_Object *obj, Evas_Object_Textblock_Format *fmt)
{
void *of;
of = fmt->font.font;
fmt->font.font = evas_font_load(obj->layer->evas, fmt->font.fdesc,
fmt->font.source, (int)(((double) fmt->font.size) * obj->cur.scale));
if (of) evas_font_free(obj->layer->evas, of);
}
/**
* @internal
* Returns true if the item is a tab
@ -3253,6 +3155,7 @@ _layout_do_format(const Evas_Object *obj __UNUSED__, Ctxt *c,
}
}
}
_format_finalize(c->obj, fmt);
}
{
@ -4222,6 +4125,7 @@ _layout(const Evas_Object *obj, int w, int h, int *w_ret, int *h_ret)
{
c->fmt = _layout_format_push(c, NULL, NULL);
_format_fill(c->obj, c->fmt, c->o->style->default_tag);
_format_finalize(c->obj, c->fmt);
}
if (!c->fmt)
{

View File

@ -31,6 +31,7 @@ typedef struct _Evas_Size_Hints Evas_Size_Hints;
typedef struct _Evas_Font_Dir Evas_Font_Dir;
typedef struct _Evas_Font Evas_Font;
typedef struct _Evas_Font_Alias Evas_Font_Alias;
typedef struct _Evas_Font_Description Evas_Font_Description;
typedef struct _Evas_Data_Node Evas_Data_Node;
typedef struct _Evas_Func_Node Evas_Func_Node;
typedef RGBA_Image_Loadopts Evas_Image_Load_Opts;
@ -46,6 +47,11 @@ typedef struct _Evas_Map_Point Evas_Map_Point;
typedef struct _Evas_Smart_Cb_Description_Array Evas_Smart_Cb_Description_Array;
typedef struct _Evas_Post_Callback Evas_Post_Callback;
typedef enum _Evas_Font_Style Evas_Font_Style;
typedef enum _Evas_Font_Slant Evas_Font_Slant;
typedef enum _Evas_Font_Weight Evas_Font_Weight;
typedef enum _Evas_Font_Width Evas_Font_Width;
/* General types - used for script type chceking */
#define OPAQUE_TYPE(type) struct __##type { int a; }; \
typedef struct __##type type
@ -584,6 +590,61 @@ struct _Evas_Font_Alias
Evas_Font *fn;
};
enum _Evas_Font_Style
{
EVAS_FONT_STYLE_SLANT,
EVAS_FONT_STYLE_WEIGHT,
EVAS_FONT_STYLE_WIDTH
};
enum _Evas_Font_Slant
{
EVAS_FONT_SLANT_NORMAL,
EVAS_FONT_SLANT_OBLIQUE,
EVAS_FONT_SLANT_ITALIC
};
enum _Evas_Font_Weight
{
EVAS_FONT_WEIGHT_NORMAL,
EVAS_FONT_WEIGHT_THIN,
EVAS_FONT_WEIGHT_ULTRALIGHT,
EVAS_FONT_WEIGHT_LIGHT,
EVAS_FONT_WEIGHT_BOOK,
EVAS_FONT_WEIGHT_MEDIUM,
EVAS_FONT_WEIGHT_SEMIBOLD,
EVAS_FONT_WEIGHT_BOLD,
EVAS_FONT_WEIGHT_ULTRABOLD,
EVAS_FONT_WEIGHT_BLACK,
EVAS_FONT_WEIGHT_EXTRABLACK
};
enum _Evas_Font_Width
{
EVAS_FONT_WIDTH_NORMAL,
EVAS_FONT_WIDTH_ULTRACONDENSED,
EVAS_FONT_WIDTH_EXTRACONDENSED,
EVAS_FONT_WIDTH_CONDENSED,
EVAS_FONT_WIDTH_SEMICONDENSED,
EVAS_FONT_WIDTH_SEMIEXPANDED,
EVAS_FONT_WIDTH_EXPANDED,
EVAS_FONT_WIDTH_EXTRAEXPANDED,
EVAS_FONT_WIDTH_ULTRAEXPANDED
};
struct _Evas_Font_Description
{
int ref;
/* We assume everywhere this is stringshared */
const char *name;
Evas_Font_Slant slant;
Evas_Font_Weight weight;
Evas_Font_Width width;
Eina_Bool new : 1;
};
struct _Evas_Object_Func
{
void (*free) (Evas_Object *obj);
@ -871,7 +932,14 @@ void evas_font_dir_available_list_free(Eina_List *available);
void evas_font_free(Evas *evas, void *font);
void evas_fonts_zero_free(Evas *evas);
void evas_fonts_zero_presure(Evas *evas);
void *evas_font_load(Evas *evas, const char *name, const char *source, int size);
void evas_font_name_parse(Evas_Font_Description *fdesc, const char *name);
int evas_font_style_find(const char *start, const char *end, Evas_Font_Style style);
Evas_Font_Description *evas_font_desc_new(void);
Evas_Font_Description *evas_font_desc_dup(const Evas_Font_Description *fdesc);
void evas_font_desc_unref(Evas_Font_Description *fdesc);
int evas_font_desc_cmp(const Evas_Font_Description *a, const Evas_Font_Description *b);
Evas_Font_Description *evas_font_desc_ref(Evas_Font_Description *fdesc);
void * evas_font_load(Evas *evas, Evas_Font_Description *fdesc, const char *source, Evas_Font_Size size);
void evas_font_load_hinting_set(Evas *evas, void *font, int hinting);
void evas_object_smart_member_cache_invalidate(Evas_Object *obj);
void evas_text_style_pad_get(Evas_Text_Style_Type style, int *l, int *r, int *t, int *b);