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:
parent
7239b6894f
commit
9ba3e192a5
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue