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