1 #include "e.h"
2 
3 #define E_TOK_STYLE ":style="
4 
5 static Eina_Bool          _font_hash_free_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata EINA_UNUSED);
6 static Eina_Hash         *_e_font_available_hash_add(Eina_Hash *font_hash, const char *full_name);
7 static E_Font_Properties *_e_font_fontconfig_name_parse(Eina_Hash **font_hash, E_Font_Properties *efp, const char *font);
8 static char _fn_buf[1024];
9 
10 EINTERN int
e_font_init(void)11 e_font_init(void)
12 {
13    /* all init stuff is in e_config */
14    return 1;
15 }
16 
17 EINTERN int
e_font_shutdown(void)18 e_font_shutdown(void)
19 {
20    /* e_config will do this */
21    return 1;
22 }
23 
24 E_API void
e_font_apply(void)25 e_font_apply(void)
26 {
27    char buf[1024];
28    const Eina_List *l;
29    E_Client *ec;
30    E_Font_Default *efd;
31    E_Font_Fallback *eff;
32    int blen, len;
33 
34    /* setup edje fallback list */
35    blen = sizeof(buf) - 1;
36    buf[0] = 0;
37    buf[blen] = 0;
38    l = e_config->font_fallbacks;
39    if (l)
40      {
41         eff = eina_list_data_get(l);
42         len = strlen(eff->name);
43         if (len < blen)
44           {
45              strcpy(buf, eff->name);
46              blen -= len;
47           }
48         EINA_LIST_FOREACH(eina_list_next(l), l, eff)
49           {
50              len = 1;
51              if (len < blen)
52                {
53                   strcat(buf, ",");
54                   blen -= len;
55                }
56              len = strlen(eff->name);
57              if (len < blen)
58                {
59                   strcat(buf, eff->name);
60                   blen -= len;
61                }
62           }
63         edje_fontset_append_set(buf);
64      }
65    else
66      edje_fontset_append_set(NULL);
67 
68    /* setup edje text classes */
69    EINA_LIST_FOREACH(e_config->font_defaults, l, efd)
70      {
71         edje_text_class_set(efd->text_class, efd->font, efd->size);
72      }
73 
74    /* Update clients */
75    if (!e_comp) return;
76    EINA_LIST_FOREACH(e_comp->clients, l, ec)
77      e_client_frame_recalc(ec);
78 }
79 
80 E_API Eina_List *
e_font_available_list(void)81 e_font_available_list(void)
82 {
83    Eina_List *evas_fonts;
84    Eina_List *e_fonts;
85    Eina_List *l;
86    const char *evas_font;
87 
88    evas_fonts = evas_font_available_list(e_comp->evas);
89 
90    e_fonts = NULL;
91    EINA_LIST_FOREACH(evas_fonts, l, evas_font)
92      {
93         E_Font_Available *efa;
94 
95         efa = E_NEW(E_Font_Available, 1);
96         efa->name = eina_stringshare_add(evas_font);
97         e_fonts = eina_list_append(e_fonts, efa);
98      }
99 
100    evas_font_available_list_free(e_comp->evas, evas_fonts);
101 
102    return e_fonts;
103 }
104 
105 E_API void
e_font_available_list_free(Eina_List * available)106 e_font_available_list_free(Eina_List *available)
107 {
108    E_Font_Available *efa;
109 
110    EINA_LIST_FREE(available, efa)
111      {
112         if (efa->name) eina_stringshare_del(efa->name);
113         E_FREE(efa);
114      }
115 }
116 
117 E_API void
e_font_properties_free(E_Font_Properties * efp)118 e_font_properties_free(E_Font_Properties *efp)
119 {
120    const char *str;
121 
122    EINA_LIST_FREE(efp->styles, str)
123      {
124         if (str) eina_stringshare_del(str);
125      }
126    if (efp->name) eina_stringshare_del(efp->name);
127    free(efp);
128 }
129 
130 static Eina_Bool
_font_hash_free_cb(const Eina_Hash * hash EINA_UNUSED,const void * key EINA_UNUSED,void * data,void * fdata EINA_UNUSED)131 _font_hash_free_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata EINA_UNUSED)
132 {
133    E_Font_Properties *efp;
134 
135    efp = data;
136    e_font_properties_free(efp);
137    return 1;
138 }
139 
140 E_API void
e_font_available_hash_free(Eina_Hash * hash)141 e_font_available_hash_free(Eina_Hash *hash)
142 {
143    eina_hash_foreach(hash, _font_hash_free_cb, NULL);
144    eina_hash_free(hash);
145 }
146 
147 E_API E_Font_Properties *
e_font_fontconfig_name_parse(const char * font)148 e_font_fontconfig_name_parse(const char *font)
149 {
150    if (!font) return NULL;
151    return _e_font_fontconfig_name_parse(NULL, NULL, font);
152 }
153 
154 static E_Font_Properties *
_e_font_fontconfig_name_parse(Eina_Hash ** font_hash,E_Font_Properties * efp,const char * font)155 _e_font_fontconfig_name_parse(Eina_Hash **font_hash, E_Font_Properties *efp, const char *font)
156 {
157    char *s1;
158 
159    s1 = strchr(font, ':');
160    if (s1)
161      {
162         char *s2, *name, *style, *temp;
163         int len;
164 
165         len = s1 - font;
166         name = calloc(sizeof(char), len + 1);
167         strncpy(name, font, len);
168 
169         /* Get subname (should be english)  */
170         s2 = strchr(name, ',');
171         if (s2)
172           {
173              len = s2 - name;
174              temp = name;
175              name = realloc(name, sizeof(char) * len + 1);
176              if (!name)
177                {
178                   free(temp);
179                   return NULL;
180                }
181              memset(name, 0, sizeof(char) * len + 1);
182              strncpy(name, font, len);
183           }
184 
185         if (strncmp(s1, E_TOK_STYLE, strlen(E_TOK_STYLE)) == 0)
186           {
187              style = s1 + strlen(E_TOK_STYLE);
188 
189              if (font_hash) efp = eina_hash_find(*font_hash, name);
190              if (!efp)
191                {
192                   efp = calloc(1, sizeof(E_Font_Properties));
193                   efp->name = eina_stringshare_add(name);
194                   if (font_hash)
195                     {
196                        if (!*font_hash) *font_hash = eina_hash_string_superfast_new(NULL);
197                        eina_hash_add(*font_hash, name, efp);
198                     }
199                }
200              s2 = strchr(style, ',');
201              if (s2)
202                {
203                   char *style_old;
204 
205                   len = s2 - style;
206                   style_old = style;
207                   style = calloc(sizeof(char), len + 1);
208                   strncpy(style, style_old, len);
209                   efp->styles = eina_list_append(efp->styles, eina_stringshare_add(style));
210                   free(style);
211                }
212              else
213                efp->styles = eina_list_append(efp->styles, eina_stringshare_add(style));
214           }
215         free(name);
216      }
217    else
218      {
219         if (font_hash) efp = eina_hash_find(*font_hash, font);
220         if (!efp)
221           {
222              efp = calloc(1, sizeof(E_Font_Properties));
223              efp->name = eina_stringshare_add(font);
224              if (font_hash)
225                {
226                   if (!*font_hash) *font_hash = eina_hash_string_superfast_new(NULL);
227                   eina_hash_add(*font_hash, font, efp);
228                }
229           }
230      }
231    return efp;
232 }
233 
234 static Eina_Hash *
_e_font_available_hash_add(Eina_Hash * font_hash,const char * full_name)235 _e_font_available_hash_add(Eina_Hash *font_hash, const char *full_name)
236 {
237    _e_font_fontconfig_name_parse(&font_hash, NULL, full_name);
238    return font_hash;
239 }
240 
241 E_API Eina_Hash *
e_font_available_list_parse(Eina_List * list)242 e_font_available_list_parse(Eina_List *list)
243 {
244    Eina_Hash *font_hash;
245    Eina_List *next;
246    void *key;
247 
248    font_hash = NULL;
249 
250    /* Populate Default Font Families */
251    font_hash = _e_font_available_hash_add(font_hash, "Sans:style=Regular");
252    font_hash = _e_font_available_hash_add(font_hash, "Sans:style=Bold");
253    font_hash = _e_font_available_hash_add(font_hash, "Sans:style=Oblique");
254    font_hash = _e_font_available_hash_add(font_hash, "Sans:style=Bold Oblique");
255 
256    font_hash = _e_font_available_hash_add(font_hash, "Serif:style=Regular");
257    font_hash = _e_font_available_hash_add(font_hash, "Serif:style=Bold");
258    font_hash = _e_font_available_hash_add(font_hash, "Serif:style=Oblique");
259    font_hash = _e_font_available_hash_add(font_hash, "Serif:style=Bold Oblique");
260 
261    font_hash = _e_font_available_hash_add(font_hash, "Monospace:style=Regular");
262    font_hash = _e_font_available_hash_add(font_hash, "Monospace:style=Bold");
263    font_hash = _e_font_available_hash_add(font_hash, "Monospace:style=Oblique");
264    font_hash = _e_font_available_hash_add(font_hash, "Monospace:style=Bold Oblique");
265 
266    EINA_LIST_FOREACH(list, next, key)
267      font_hash = _e_font_available_hash_add(font_hash, key);
268 
269    return font_hash;
270 }
271 
272 E_API const char *
e_font_fontconfig_name_get(const char * name,const char * style)273 e_font_fontconfig_name_get(const char *name, const char *style)
274 {
275    char buf[256];
276 
277    if (!name) return NULL;
278    if (!style || style[0] == 0) return eina_stringshare_add(name);
279    snprintf(buf, 256, "%s"E_TOK_STYLE "%s", name, style);
280    return eina_stringshare_add(buf);
281 }
282 
283 E_API void
e_font_fallback_clear(void)284 e_font_fallback_clear(void)
285 {
286    E_Font_Fallback *eff;
287 
288    EINA_LIST_FREE(e_config->font_fallbacks, eff)
289      {
290         if (eff->name) eina_stringshare_del(eff->name);
291         E_FREE(eff);
292      }
293 }
294 
295 E_API void
e_font_fallback_append(const char * font)296 e_font_fallback_append(const char *font)
297 {
298    E_Font_Fallback *eff;
299 
300    e_font_fallback_remove(font);
301 
302    eff = E_NEW(E_Font_Fallback, 1);
303    eff->name = eina_stringshare_add(font);
304    e_config->font_fallbacks = eina_list_append(e_config->font_fallbacks, eff);
305 }
306 
307 E_API void
e_font_fallback_prepend(const char * font)308 e_font_fallback_prepend(const char *font)
309 {
310    E_Font_Fallback *eff;
311 
312    e_font_fallback_remove(font);
313 
314    eff = E_NEW(E_Font_Fallback, 1);
315    eff->name = eina_stringshare_add(font);
316    e_config->font_fallbacks = eina_list_prepend(e_config->font_fallbacks, eff);
317 }
318 
319 E_API void
e_font_fallback_remove(const char * font)320 e_font_fallback_remove(const char *font)
321 {
322    Eina_List *next;
323    E_Font_Fallback *eff;
324 
325    EINA_LIST_FOREACH(e_config->font_fallbacks, next, eff)
326      {
327         if (!e_util_strcmp(eff->name, font))
328           {
329              e_config->font_fallbacks =
330                eina_list_remove_list(e_config->font_fallbacks, next);
331              if (eff->name) eina_stringshare_del(eff->name);
332              E_FREE(eff);
333              break;
334           }
335      }
336 }
337 
338 E_API Eina_List *
e_font_fallback_list(void)339 e_font_fallback_list(void)
340 {
341    return e_config->font_fallbacks;
342 }
343 
344 E_API void
e_font_default_set(const char * text_class,const char * font,Evas_Font_Size size)345 e_font_default_set(const char *text_class, const char *font, Evas_Font_Size size)
346 {
347    E_Font_Default *efd;
348    Eina_List *next;
349 
350    /* search for the text class */
351    EINA_LIST_FOREACH(e_config->font_defaults, next, efd)
352      {
353         if (!strcmp(efd->text_class, text_class))
354           {
355              if (efd->font) eina_stringshare_del(efd->font);
356              efd->font = eina_stringshare_add(font);
357              efd->size = size;
358              /* move to the front of the list */
359              e_config->font_defaults =
360                eina_list_remove_list(e_config->font_defaults, next);
361              e_config->font_defaults =
362                eina_list_prepend(e_config->font_defaults, efd);
363              return;
364           }
365      }
366 
367    /* the text class doesn't exist */
368    efd = E_NEW(E_Font_Default, 1);
369    efd->text_class = eina_stringshare_add(text_class);
370    efd->font = eina_stringshare_add(font);
371    efd->size = size;
372 
373    e_config->font_defaults = eina_list_prepend(e_config->font_defaults, efd);
374 }
375 
376 /*
377  * returns a pointer to the data, return null if nothing if found.
378  */
379 E_API E_Font_Default *
e_font_default_get(const char * text_class)380 e_font_default_get(const char *text_class)
381 {
382    E_Font_Default *efd = NULL, *defd = NULL;
383    Eina_List *next;
384 
385    /* search for the text class */
386    EINA_LIST_FOREACH(e_config->font_defaults, next, efd)
387      {
388         if (!strcmp(efd->text_class, text_class))
389           {
390              /* move to the front of the list */
391              e_config->font_defaults =
392                eina_list_remove_list(e_config->font_defaults, next);
393              e_config->font_defaults =
394                eina_list_prepend(e_config->font_defaults, efd);
395              return efd;
396           }
397         if (!strcmp(efd->text_class, "default")) defd = efd;
398      }
399    if (!defd) defd = efd;
400    return defd;
401 }
402 
403 E_API void
e_font_default_remove(const char * text_class)404 e_font_default_remove(const char *text_class)
405 {
406    E_Font_Default *efd;
407    Eina_List *next;
408 
409    /* search for the text class */
410    EINA_LIST_FOREACH(e_config->font_defaults, next, efd)
411      {
412         if (!e_util_strcmp(efd->text_class, text_class))
413           {
414              e_config->font_defaults =
415                eina_list_remove_list(e_config->font_defaults, next);
416              if (efd->text_class) eina_stringshare_del(efd->text_class);
417              if (efd->font) eina_stringshare_del(efd->font);
418              E_FREE(efd);
419              edje_text_class_del(text_class);
420              return;
421           }
422      }
423 }
424 
425 E_API Eina_List *
e_font_default_list(void)426 e_font_default_list(void)
427 {
428    return e_config->font_defaults;
429 }
430 
431 /* return the default font name with fallbacks, font size is returned
432  * in size_ret. This function is needed when all hell breaks loose and
433  * we need a font name and size.
434  */
435 E_API const char *
e_font_default_string_get(const char * text_class,Evas_Font_Size * size_ret)436 e_font_default_string_get(const char *text_class, Evas_Font_Size *size_ret)
437 {
438    E_Font_Default *efd;
439    Eina_List *next;
440    E_Font_Fallback *eff;
441    int blen, len;
442 
443    _fn_buf[0] = 0;
444    efd = e_font_default_get(text_class);
445    if (!efd)
446      {
447         if (size_ret) *size_ret = 0;
448         return "";
449      }
450    blen = sizeof(_fn_buf) - 1;
451 
452    len = strlen(efd->font);
453    if (len < blen)
454      {
455         strcpy(_fn_buf, efd->font);
456         blen -= len;
457      }
458 
459    EINA_LIST_FOREACH(e_config->font_fallbacks, next, eff)
460      {
461         len = 1;
462         if (len < blen)
463           {
464              strcat(_fn_buf, ",");
465              blen -= len;
466           }
467         len = strlen(eff->name);
468         if (len < blen)
469           {
470              strcat(_fn_buf, eff->name);
471              blen -= len;
472           }
473      }
474 
475    if (size_ret) *size_ret = efd->size;
476    return _fn_buf;
477 }
478 
479