#include "e.h" #define E_TOK_STYLE ":style=" static Eina_Bool _font_hash_free_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata EINA_UNUSED); static Eina_Hash *_e_font_available_hash_add(Eina_Hash *font_hash, const char *full_name); static E_Font_Properties *_e_font_fontconfig_name_parse(Eina_Hash **font_hash, E_Font_Properties *efp, const char *font); static char _fn_buf[1024]; EINTERN int e_font_init(void) { /* all init stuff is in e_config */ return 1; } EINTERN int e_font_shutdown(void) { /* e_config will do this */ return 1; } E_API void e_font_apply(void) { char buf[1024]; const Eina_List *l; E_Client *ec; E_Font_Default *efd; E_Font_Fallback *eff; int blen, len; /* setup edje fallback list */ blen = sizeof(buf) - 1; buf[0] = 0; buf[blen] = 0; l = e_config->font_fallbacks; if (l) { eff = eina_list_data_get(l); len = strlen(eff->name); if (len < blen) { strcpy(buf, eff->name); blen -= len; } EINA_LIST_FOREACH(eina_list_next(l), l, eff) { len = 1; if (len < blen) { strcat(buf, ","); blen -= len; } len = strlen(eff->name); if (len < blen) { strcat(buf, eff->name); blen -= len; } } edje_fontset_append_set(buf); } else edje_fontset_append_set(NULL); /* setup edje text classes */ EINA_LIST_FOREACH(e_config->font_defaults, l, efd) { edje_text_class_set(efd->text_class, efd->font, efd->size); } /* Update clients */ if (!e_comp) return; EINA_LIST_FOREACH(e_comp->clients, l, ec) e_client_frame_recalc(ec); } E_API Eina_List * e_font_available_list(void) { Eina_List *evas_fonts; Eina_List *e_fonts; Eina_List *l; const char *evas_font; evas_fonts = evas_font_available_list(e_comp->evas); e_fonts = NULL; EINA_LIST_FOREACH(evas_fonts, l, evas_font) { E_Font_Available *efa; efa = E_NEW(E_Font_Available, 1); efa->name = eina_stringshare_add(evas_font); e_fonts = eina_list_append(e_fonts, efa); } evas_font_available_list_free(e_comp->evas, evas_fonts); return e_fonts; } E_API void e_font_available_list_free(Eina_List *available) { E_Font_Available *efa; EINA_LIST_FREE(available, efa) { if (efa->name) eina_stringshare_del(efa->name); E_FREE(efa); } } E_API void e_font_properties_free(E_Font_Properties *efp) { const char *str; EINA_LIST_FREE(efp->styles, str) { if (str) eina_stringshare_del(str); } if (efp->name) eina_stringshare_del(efp->name); free(efp); } static Eina_Bool _font_hash_free_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata EINA_UNUSED) { E_Font_Properties *efp; efp = data; e_font_properties_free(efp); return 1; } E_API void e_font_available_hash_free(Eina_Hash *hash) { eina_hash_foreach(hash, _font_hash_free_cb, NULL); eina_hash_free(hash); } E_API E_Font_Properties * e_font_fontconfig_name_parse(const char *font) { if (!font) return NULL; return _e_font_fontconfig_name_parse(NULL, NULL, font); } static E_Font_Properties * _e_font_fontconfig_name_parse(Eina_Hash **font_hash, E_Font_Properties *efp, const char *font) { char *s1; s1 = strchr(font, ':'); if (s1) { char *s2, *name, *style, *temp; int len; len = s1 - font; name = calloc(sizeof(char), len + 1); strncpy(name, font, len); /* Get subname (should be english) */ s2 = strchr(name, ','); if (s2) { len = s2 - name; temp = name; name = realloc(name, sizeof(char) * len + 1); if (!name) { free(temp); return NULL; } memset(name, 0, sizeof(char) * len + 1); strncpy(name, font, len); } if (strncmp(s1, E_TOK_STYLE, strlen(E_TOK_STYLE)) == 0) { style = s1 + strlen(E_TOK_STYLE); if (font_hash) efp = eina_hash_find(*font_hash, name); if (!efp) { efp = calloc(1, sizeof(E_Font_Properties)); efp->name = eina_stringshare_add(name); if (font_hash) { if (!*font_hash) *font_hash = eina_hash_string_superfast_new(NULL); eina_hash_add(*font_hash, name, efp); } } s2 = strchr(style, ','); if (s2) { char *style_old; len = s2 - style; style_old = style; style = calloc(sizeof(char), len + 1); strncpy(style, style_old, len); efp->styles = eina_list_append(efp->styles, eina_stringshare_add(style)); free(style); } else efp->styles = eina_list_append(efp->styles, eina_stringshare_add(style)); } free(name); } else { if (font_hash) efp = eina_hash_find(*font_hash, font); if (!efp) { efp = calloc(1, sizeof(E_Font_Properties)); efp->name = eina_stringshare_add(font); if (font_hash) { if (!*font_hash) *font_hash = eina_hash_string_superfast_new(NULL); eina_hash_add(*font_hash, font, efp); } } } return efp; } static Eina_Hash * _e_font_available_hash_add(Eina_Hash *font_hash, const char *full_name) { _e_font_fontconfig_name_parse(&font_hash, NULL, full_name); return font_hash; } E_API Eina_Hash * e_font_available_list_parse(Eina_List *list) { Eina_Hash *font_hash; Eina_List *next; void *key; font_hash = NULL; /* Populate Default Font Families */ font_hash = _e_font_available_hash_add(font_hash, "Sans:style=Regular"); font_hash = _e_font_available_hash_add(font_hash, "Sans:style=Bold"); font_hash = _e_font_available_hash_add(font_hash, "Sans:style=Oblique"); font_hash = _e_font_available_hash_add(font_hash, "Sans:style=Bold Oblique"); font_hash = _e_font_available_hash_add(font_hash, "Serif:style=Regular"); font_hash = _e_font_available_hash_add(font_hash, "Serif:style=Bold"); font_hash = _e_font_available_hash_add(font_hash, "Serif:style=Oblique"); font_hash = _e_font_available_hash_add(font_hash, "Serif:style=Bold Oblique"); font_hash = _e_font_available_hash_add(font_hash, "Monospace:style=Regular"); font_hash = _e_font_available_hash_add(font_hash, "Monospace:style=Bold"); font_hash = _e_font_available_hash_add(font_hash, "Monospace:style=Oblique"); font_hash = _e_font_available_hash_add(font_hash, "Monospace:style=Bold Oblique"); EINA_LIST_FOREACH(list, next, key) font_hash = _e_font_available_hash_add(font_hash, key); return font_hash; } E_API const char * e_font_fontconfig_name_get(const char *name, const char *style) { char buf[256]; if (!name) return NULL; if (!style || style[0] == 0) return eina_stringshare_add(name); snprintf(buf, 256, "%s"E_TOK_STYLE "%s", name, style); return eina_stringshare_add(buf); } E_API void e_font_fallback_clear(void) { E_Font_Fallback *eff; EINA_LIST_FREE(e_config->font_fallbacks, eff) { if (eff->name) eina_stringshare_del(eff->name); E_FREE(eff); } } E_API void e_font_fallback_append(const char *font) { E_Font_Fallback *eff; e_font_fallback_remove(font); eff = E_NEW(E_Font_Fallback, 1); eff->name = eina_stringshare_add(font); e_config->font_fallbacks = eina_list_append(e_config->font_fallbacks, eff); } E_API void e_font_fallback_prepend(const char *font) { E_Font_Fallback *eff; e_font_fallback_remove(font); eff = E_NEW(E_Font_Fallback, 1); eff->name = eina_stringshare_add(font); e_config->font_fallbacks = eina_list_prepend(e_config->font_fallbacks, eff); } E_API void e_font_fallback_remove(const char *font) { Eina_List *next; E_Font_Fallback *eff; EINA_LIST_FOREACH(e_config->font_fallbacks, next, eff) { if (!e_util_strcmp(eff->name, font)) { e_config->font_fallbacks = eina_list_remove_list(e_config->font_fallbacks, next); if (eff->name) eina_stringshare_del(eff->name); E_FREE(eff); break; } } } E_API Eina_List * e_font_fallback_list(void) { return e_config->font_fallbacks; } E_API void e_font_default_set(const char *text_class, const char *font, Evas_Font_Size size) { E_Font_Default *efd; Eina_List *next; /* search for the text class */ EINA_LIST_FOREACH(e_config->font_defaults, next, efd) { if (!strcmp(efd->text_class, text_class)) { if (efd->font) eina_stringshare_del(efd->font); efd->font = eina_stringshare_add(font); efd->size = size; /* move to the front of the list */ e_config->font_defaults = eina_list_remove_list(e_config->font_defaults, next); e_config->font_defaults = eina_list_prepend(e_config->font_defaults, efd); return; } } /* the text class doesn't exist */ efd = E_NEW(E_Font_Default, 1); efd->text_class = eina_stringshare_add(text_class); efd->font = eina_stringshare_add(font); efd->size = size; e_config->font_defaults = eina_list_prepend(e_config->font_defaults, efd); } /* * returns a pointer to the data, return null if nothing if found. */ E_API E_Font_Default * e_font_default_get(const char *text_class) { E_Font_Default *efd = NULL, *defd = NULL; Eina_List *next; /* search for the text class */ EINA_LIST_FOREACH(e_config->font_defaults, next, efd) { if (!strcmp(efd->text_class, text_class)) { /* move to the front of the list */ e_config->font_defaults = eina_list_remove_list(e_config->font_defaults, next); e_config->font_defaults = eina_list_prepend(e_config->font_defaults, efd); return efd; } if (!strcmp(efd->text_class, "default")) defd = efd; } if (!defd) defd = efd; return defd; } E_API void e_font_default_remove(const char *text_class) { E_Font_Default *efd; Eina_List *next; /* search for the text class */ EINA_LIST_FOREACH(e_config->font_defaults, next, efd) { if (!e_util_strcmp(efd->text_class, text_class)) { e_config->font_defaults = eina_list_remove_list(e_config->font_defaults, next); if (efd->text_class) eina_stringshare_del(efd->text_class); if (efd->font) eina_stringshare_del(efd->font); E_FREE(efd); edje_text_class_del(text_class); return; } } } E_API Eina_List * e_font_default_list(void) { return e_config->font_defaults; } /* return the default font name with fallbacks, font size is returned * in size_ret. This function is needed when all hell breaks loose and * we need a font name and size. */ E_API const char * e_font_default_string_get(const char *text_class, Evas_Font_Size *size_ret) { E_Font_Default *efd; Eina_List *next; E_Font_Fallback *eff; int blen, len; _fn_buf[0] = 0; efd = e_font_default_get(text_class); if (!efd) { if (size_ret) *size_ret = 0; return ""; } blen = sizeof(_fn_buf) - 1; len = strlen(efd->font); if (len < blen) { strcpy(_fn_buf, efd->font); blen -= len; } EINA_LIST_FOREACH(e_config->font_fallbacks, next, eff) { len = 1; if (len < blen) { strcat(_fn_buf, ","); blen -= len; } len = strlen(eff->name); if (len < blen) { strcat(_fn_buf, eff->name); blen -= len; } } if (size_ret) *size_ret = efd->size; return _fn_buf; }