* evas_font_dir: reduce use of FcFontSort by using cache as much as possible.

This reduce in EWeather the time spend in FcFontSort from 25% of the startup time
	to 1% with a small memory footprint increase.


SVN revision: 44444
This commit is contained in:
Cedric BAIL 2009-12-14 17:27:51 +00:00
parent 576d5f7091
commit 0ccf619ba0
1 changed files with 62 additions and 25 deletions

View File

@ -31,6 +31,11 @@ struct _Fndat
int size; int size;
void *font; void *font;
int ref; int ref;
#ifdef HAVE_FONTCONFIG
FcFontSet *set;
FcPattern *p_nm;
#endif
}; };
/* private methods for font dir cache */ /* private methods for font dir cache */
@ -51,15 +56,16 @@ static int fc_init = 0;
void void
evas_font_dir_cache_free(void) evas_font_dir_cache_free(void)
{ {
#ifdef HAVE_FONTCONFIG
fc_init--;
if (fc_init == 0) FcFini();
#endif
if (!font_dirs) return; if (!font_dirs) return;
eina_hash_foreach(font_dirs, font_cache_dir_free, NULL); eina_hash_foreach(font_dirs, font_cache_dir_free, NULL);
eina_hash_free(font_dirs); eina_hash_free(font_dirs);
font_dirs = NULL; font_dirs = NULL;
#ifdef HAVE_FONTCONFIG
fc_init--;
if (fc_init == 0) FcFini();
#endif
} }
const char * const char *
@ -124,6 +130,8 @@ evas_fonts_zero_free(Evas *evas)
if (fd->name) eina_stringshare_del(fd->name); if (fd->name) eina_stringshare_del(fd->name);
if (fd->source) eina_stringshare_del(fd->source); if (fd->source) eina_stringshare_del(fd->source);
evas->engine.func->font_free(evas->engine.data.output, fd->font); evas->engine.func->font_free(evas->engine.data.output, fd->font);
if (fd->set) FcFontSetDestroy(fd->set);
if (fd->p_nm) FcPatternDestroy(fd->p_nm);
free(fd); free(fd);
} }
} }
@ -144,6 +152,8 @@ evas_fonts_zero_presure(Evas *evas)
if (fd->name) eina_stringshare_del(fd->name); if (fd->name) eina_stringshare_del(fd->name);
if (fd->source) eina_stringshare_del(fd->source); if (fd->source) eina_stringshare_del(fd->source);
evas->engine.func->font_free(evas->engine.data.output, fd->font); evas->engine.func->font_free(evas->engine.data.output, fd->font);
if (fd->set) FcFontSetDestroy(fd->set);
if (fd->p_nm) FcPatternDestroy(fd->p_nm);
free(fd); free(fd);
if (eina_list_count(fonts_zero) < 5) break; if (eina_list_count(fonts_zero) < 5) break;
@ -180,6 +190,8 @@ evas_font_free(Evas *evas, void *font)
if (fd->name) eina_stringshare_del(fd->name); if (fd->name) eina_stringshare_del(fd->name);
if (fd->source) eina_stringshare_del(fd->source); if (fd->source) eina_stringshare_del(fd->source);
evas->engine.func->font_free(evas->engine.data.output, fd->font); evas->engine.func->font_free(evas->engine.data.output, fd->font);
if (fd->set) FcFontSetDestroy(fd->set);
if (fd->p_nm) FcPatternDestroy(fd->p_nm);
free(fd); free(fd);
if (eina_list_count(fonts_zero) < 43) break; if (eina_list_count(fonts_zero) < 43) break;
@ -202,9 +214,36 @@ evas_font_init(void)
#endif #endif
} }
static void *
evas_load_fontconfig(Evas *evas, FcFontSet *set, int size)
{
void *font = NULL;
int i;
/* Do loading for all in family */
for (i = 0; i < set->nfont; i++)
{
FcValue filename;
FcPatternGet(set->fonts[i], FC_FILE, 0, &filename);
if (font)
evas->engine.func->font_add(evas->engine.data.output, font, (char *)filename.u.s, size);
else
font = evas->engine.func->font_load(evas->engine.data.output, (char *)filename.u.s, size);
}
return font;
}
void * void *
evas_font_load(Evas *evas, const char *name, const char *source, int size) evas_font_load(Evas *evas, const char *name, const char *source, int size)
{ {
#ifdef HAVE_FONTCONFIG
FcPattern *p_nm = NULL;
FcFontSet *set = NULL;
#endif
void *font = NULL; void *font = NULL;
Eina_List *fonts, *l; Eina_List *fonts, *l;
Fndat *fd; Fndat *fd;
@ -228,6 +267,11 @@ evas_font_load(Evas *evas, const char *name, const char *source, int size)
fd->ref++; fd->ref++;
return fd->font; return fd->font;
} }
else if (fd->set && fd->p_nm)
{
font = evas_load_fontconfig(evas, fd->set, size);
goto on_find;
}
} }
} }
} }
@ -246,6 +290,11 @@ evas_font_load(Evas *evas, const char *name, const char *source, int size)
fd->ref++; fd->ref++;
return fd->font; return fd->font;
} }
else if (fd->set && fd->p_nm)
{
font = evas_load_fontconfig(evas, fd->set, size);
goto on_find;
}
} }
} }
} }
@ -381,10 +430,7 @@ evas_font_load(Evas *evas, const char *name, const char *source, int size)
#ifdef HAVE_FONTCONFIG #ifdef HAVE_FONTCONFIG
if (!font) /* Search using fontconfig */ if (!font) /* Search using fontconfig */
{ {
FcPattern *p_nm = NULL;
FcFontSet *set;
FcResult res; FcResult res;
int i;
p_nm = FcNameParse((FcChar8 *)name); p_nm = FcNameParse((FcChar8 *)name);
FcConfigSubstitute(NULL, p_nm, FcMatchPattern); FcConfigSubstitute(NULL, p_nm, FcMatchPattern);
@ -395,28 +441,15 @@ evas_font_load(Evas *evas, const char *name, const char *source, int size)
if (!set) 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!", name);
goto fc_end; FcPatternDestroy(p_nm);
p_nm = NULL;
} }
else
/* Do loading for all in family */ font = evas_load_fontconfig(evas, set, size);
for (i = 0; i < set->nfont; i++)
{
FcValue filename;
FcPatternGet(set->fonts[i], FC_FILE, 0, &filename);
if (font)
evas->engine.func->font_add(evas->engine.data.output, font, (char *)filename.u.s, size);
else
font = evas->engine.func->font_load(evas->engine.data.output, (char *)filename.u.s, size);
}
FcFontSetDestroy(set);
fc_end:
FcPatternDestroy(p_nm);
} }
#endif #endif
on_find:
fd = calloc(1, sizeof(Fndat)); fd = calloc(1, sizeof(Fndat));
if (fd) if (fd)
{ {
@ -426,6 +459,10 @@ evas_font_load(Evas *evas, const char *name, const char *source, int size)
fd->font = font; fd->font = font;
fd->ref = 1; fd->ref = 1;
fonts_cache = eina_list_prepend(fonts_cache, fd); fonts_cache = eina_list_prepend(fonts_cache, fd);
#ifdef HAVE_FONTCONFIG
fd->set = set;
fd->p_nm = p_nm;
#endif
} }
if (font) if (font)