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