1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #ifdef _WIN32
6 # include <evil_private.h> /* evil_path_is_absolute */
7 #endif
8
9 #include <Eet.h>
10
11 #ifdef HAVE_FONTCONFIG
12 #include <fontconfig/fontconfig.h>
13 #include <fontconfig/fcfreetype.h>
14 #endif
15
16 #include "evas_font.h"
17
18 /* General types - used for script type chceking */
19 #define OPAQUE_TYPE(type) struct __##type { int a; }; \
20 typedef struct __##type type
21
22 OPAQUE_TYPE(Evas_Font_Set); /* General type for RGBA_Font */
23 OPAQUE_TYPE(Evas_Font_Instance); /* General type for RGBA_Font_Int */
24
25 /* font dir cache */
26 static Eina_Hash *font_dirs = NULL;
27 static Eina_List *fonts_cache = NULL;
28 static Eina_List *fonts_zero = NULL;
29 static Eina_List *global_font_path = NULL;
30
31 typedef struct _Fndat Fndat;
32
33 struct _Fndat
34 {
35 Evas_Font_Description *fdesc;
36 const char *source;
37 Evas_Font_Size size;
38 Evas_Font_Set *font;
39 int ref;
40 Font_Rend_Flags wanted_rend;
41 Efl_Text_Font_Bitmap_Scalable bitmap_scalable;
42
43 #ifdef HAVE_FONTCONFIG
44 FcFontSet *set;
45 FcPattern *p_nm;
46
47 Eina_Bool file_font : 1; /* Indicates this is a font that uses a file rather than fontconfig. */
48 #endif
49 };
50
51 /* private methods for font dir cache */
52 static Eina_Bool font_cache_dir_free(const Eina_Hash *hash, const void *key, void *data, void *fdata);
53 static Evas_Font_Dir *object_text_font_cache_dir_update(char *dir, Evas_Font_Dir *fd);
54 static Evas_Font *object_text_font_cache_font_find_x(Evas_Font_Dir *fd, char *font);
55 static Evas_Font *object_text_font_cache_font_find_file(Evas_Font_Dir *fd, char *font);
56 static Evas_Font *object_text_font_cache_font_find_alias(Evas_Font_Dir *fd, char *font);
57 static Evas_Font *object_text_font_cache_font_find(Evas_Font_Dir *fd, char *font);
58 static Evas_Font_Dir *object_text_font_cache_dir_add(char *dir);
59 static void object_text_font_cache_dir_del(char *dir, Evas_Font_Dir *fd);
60 static int evas_object_text_font_string_parse(char *buffer, char dest[14][256]);
61
62 #ifdef HAVE_FONTCONFIG
63 static FcConfig *fc_config = NULL;
64 #endif
65
66 /* FIXME move these helper function to eina_file or eina_path */
67 /* get the casefold feature! */
68 #include <fnmatch.h>
69 #include <unistd.h>
70 #include <sys/param.h>
71 int
_file_path_is_full_path(const char * path)72 _file_path_is_full_path(const char *path)
73 {
74 if (!path) return 0;
75 #ifdef _WIN32
76 if (evil_path_is_absolute(path)) return 1;
77 #else
78 if (path[0] == '/') return 1;
79 #endif
80 return 0;
81 }
82
83 static DATA64
_file_modified_time(const char * file)84 _file_modified_time(const char *file)
85 {
86 struct stat st;
87
88 if (stat(file, &st) < 0) return 0;
89 if (st.st_ctime > st.st_mtime) return (DATA64)st.st_ctime;
90 else return (DATA64)st.st_mtime;
91 return 0;
92 }
93
94 Eina_List *
_file_path_list(char * path,const char * match,int match_case)95 _file_path_list(char *path, const char *match, int match_case)
96 {
97 Eina_File_Direct_Info *info;
98 Eina_Iterator *it;
99 Eina_List *files = NULL;
100 int flags;
101
102 flags = FNM_PATHNAME;
103 #ifdef FNM_CASEFOLD
104 if (!match_case)
105 flags |= FNM_CASEFOLD;
106 #elif defined FNM_IGNORECASE
107 if (!match_case)
108 flags |= FNM_IGNORECASE;
109 #else
110 /*#warning "Your libc does not provide case-insensitive matching!"*/
111 #endif
112
113 it = eina_file_direct_ls(path);
114 EINA_ITERATOR_FOREACH(it, info)
115 {
116 if (match)
117 {
118 if (fnmatch(match, info->path + info->name_start, flags) == 0)
119 files = eina_list_append(files, strdup(info->path + info->name_start));
120 }
121 else
122 files = eina_list_append(files, strdup(info->path + info->name_start));
123 }
124 if (it) eina_iterator_free(it);
125 return files;
126 }
127
128 static void
evas_font_init(void)129 evas_font_init(void)
130 {
131 #ifdef HAVE_FONTCONFIG
132 if (!fc_config)
133 {
134 Eina_List *l;
135 char *path;
136
137 fc_config = FcInitLoadConfigAndFonts();
138
139 EINA_LIST_FOREACH(global_font_path, l, path)
140 FcConfigAppFontAddDir(fc_config, (const FcChar8 *) path);
141 }
142 #endif
143 }
144
145 void
evas_font_dir_cache_free(void)146 evas_font_dir_cache_free(void)
147 {
148 if (font_dirs)
149 {
150 eina_hash_foreach(font_dirs, font_cache_dir_free, NULL);
151 eina_hash_free(font_dirs);
152 font_dirs = NULL;
153 }
154 #ifdef HAVE_FONTCONFIG
155 if (fc_config)
156 {
157 FcConfigDestroy(fc_config);
158 fc_config = NULL;
159 }
160 #endif
161 }
162
163 const char *
evas_font_dir_cache_find(char * dir,char * font)164 evas_font_dir_cache_find(char *dir, char *font)
165 {
166 Evas_Font_Dir *fd = NULL;
167
168 if (!font_dirs) font_dirs = eina_hash_string_superfast_new(NULL);
169 else fd = eina_hash_find(font_dirs, dir);
170 fd = object_text_font_cache_dir_update(dir, fd);
171 if (fd)
172 {
173 Evas_Font *fn;
174
175 fn = object_text_font_cache_font_find(fd, font);
176 if (fn)
177 {
178 return fn->path;
179 }
180 }
181 return NULL;
182 }
183
184 static Eina_List *
evas_font_set_get(const char * name)185 evas_font_set_get(const char *name)
186 {
187 Eina_List *fonts = NULL;
188 char *p;
189
190 EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
191 if (!*name) return NULL;
192
193 p = strchr(name, ',');
194 if (!p)
195 {
196 fonts = eina_list_append(fonts, eina_stringshare_add(name));
197 }
198 else
199 {
200 const char *pp;
201 char *nm;
202
203 pp = name;
204 while (p)
205 {
206 nm = alloca(p - pp + 1);
207 strncpy(nm, pp, p - pp);
208 nm[p - pp] = 0;
209 fonts = eina_list_append(fonts, eina_stringshare_add(nm));
210 pp = p + 1;
211 p = strchr(pp, ',');
212 if (!p) fonts = eina_list_append(fonts, eina_stringshare_add(pp));
213 }
214 }
215 return fonts;
216 }
217
218 void
evas_fonts_zero_free()219 evas_fonts_zero_free()
220 {
221 Fndat *fd;
222
223 EINA_LIST_FREE(fonts_zero, fd)
224 {
225 if (fd->fdesc) evas_font_desc_unref(fd->fdesc);
226 if (fd->source) eina_stringshare_del(fd->source);
227 evas_common_font_free((RGBA_Font *)fd->font);
228 #ifdef HAVE_FONTCONFIG
229 if (fd->set) FcFontSetDestroy(fd->set);
230 if (fd->p_nm) FcPatternDestroy(fd->p_nm);
231 #endif
232 free(fd);
233 }
234 }
235
236 void
evas_fonts_zero_pressure()237 evas_fonts_zero_pressure()
238 {
239 Fndat *fd;
240
241 while (fonts_zero
242 && eina_list_count(fonts_zero) > 4) /* 4 is arbitrary */
243 {
244 fd = eina_list_data_get(fonts_zero);
245
246 if (fd->ref != 0) break;
247 fonts_zero = eina_list_remove_list(fonts_zero, fonts_zero);
248
249 if (fd->fdesc) evas_font_desc_unref(fd->fdesc);
250 if (fd->source) eina_stringshare_del(fd->source);
251 evas_common_font_free((RGBA_Font *)fd->font);
252 #ifdef HAVE_FONTCONFIG
253 if (fd->set) FcFontSetDestroy(fd->set);
254 if (fd->p_nm) FcPatternDestroy(fd->p_nm);
255 #endif
256 free(fd);
257
258 if (eina_list_count(fonts_zero) < 5) break;
259 }
260 }
261
262 void
evas_font_free(void * font)263 evas_font_free(void *font)
264 {
265 Eina_List *l;
266 Fndat *fd;
267
268 EINA_LIST_FOREACH(fonts_cache, l, fd)
269 {
270 if (fd->font == font)
271 {
272 fd->ref--;
273 if (fd->ref == 0)
274 {
275 fonts_cache = eina_list_remove_list(fonts_cache, l);
276 fonts_zero = eina_list_append(fonts_zero, fd);
277 }
278 break;
279 }
280 }
281 while (fonts_zero
282 && eina_list_count(fonts_zero) > 42) /* 42 is arbitrary */
283 {
284 fd = eina_list_data_get(fonts_zero);
285
286 if (fd->ref != 0) break;
287 fonts_zero = eina_list_remove_list(fonts_zero, fonts_zero);
288
289 if (fd->fdesc) evas_font_desc_unref(fd->fdesc);
290 if (fd->source) eina_stringshare_del(fd->source);
291 evas_common_font_free((RGBA_Font *)fd->font);
292 #ifdef HAVE_FONTCONFIG
293 if (fd->set) FcFontSetDestroy(fd->set);
294 if (fd->p_nm) FcPatternDestroy(fd->p_nm);
295 #endif
296 free(fd);
297
298 if (eina_list_count(fonts_zero) < 43) break;
299 }
300 }
301
302 #ifdef HAVE_FONTCONFIG
303 static Evas_Font_Set *
_evas_load_fontconfig(Evas_Font_Set * font,FcFontSet * set,int size,Font_Rend_Flags wanted_rend,Efl_Text_Font_Bitmap_Scalable bitmap_scalable)304 _evas_load_fontconfig(Evas_Font_Set *font, FcFontSet *set, int size,
305 Font_Rend_Flags wanted_rend, Efl_Text_Font_Bitmap_Scalable bitmap_scalable)
306 {
307 int i;
308
309 /* Do loading for all in family */
310 for (i = 0; i < set->nfont; i++)
311 {
312 FcValue filename;
313
314 if (FcPatternGet(set->fonts[i], FC_FILE, 0, &filename) == FcResultMatch)
315 {
316 if (font)
317 evas_common_font_add((RGBA_Font *)font, (char *)filename.u.s, size, wanted_rend, bitmap_scalable);
318 else
319 font = (Evas_Font_Set *)evas_common_font_load((char *)filename.u.s, size, wanted_rend, bitmap_scalable);
320 }
321 }
322
323 return font;
324 }
325 #endif
326
327 #ifdef HAVE_FONTCONFIG
328 /* In sync with Evas_Font_Style, Evas_Font_Weight and Evas_Font_Width */
329 static int _fc_slant_map[] =
330 {
331 FC_SLANT_ROMAN,
332 FC_SLANT_OBLIQUE,
333 FC_SLANT_ITALIC
334 };
335
336 /* Apparently EXTRABLACK is not always available, hardcode. */
337 # ifndef FC_WEIGHT_EXTRABLACK
338 # define FC_WEIGHT_EXTRABLACK 215
339 # endif
340 static int _fc_weight_map[] =
341 {
342 FC_WEIGHT_NORMAL,
343 FC_WEIGHT_THIN,
344 FC_WEIGHT_ULTRALIGHT,
345 FC_WEIGHT_EXTRALIGHT,
346 FC_WEIGHT_LIGHT,
347 FC_WEIGHT_BOOK,
348 FC_WEIGHT_MEDIUM,
349 FC_WEIGHT_SEMIBOLD,
350 FC_WEIGHT_BOLD,
351 FC_WEIGHT_ULTRABOLD,
352 FC_WEIGHT_EXTRABOLD,
353 FC_WEIGHT_BLACK,
354 FC_WEIGHT_EXTRABLACK
355 };
356
357 # ifdef FC_WIDTH
358 static int _fc_width_map[] =
359 {
360 FC_WIDTH_NORMAL,
361 FC_WIDTH_ULTRACONDENSED,
362 FC_WIDTH_EXTRACONDENSED,
363 FC_WIDTH_CONDENSED,
364 FC_WIDTH_SEMICONDENSED,
365 FC_WIDTH_SEMIEXPANDED,
366 FC_WIDTH_EXPANDED,
367 FC_WIDTH_EXTRAEXPANDED,
368 FC_WIDTH_ULTRAEXPANDED
369 };
370 # endif
371
372 static int _fc_spacing_map[] =
373 {
374 FC_PROPORTIONAL,
375 FC_DUAL,
376 FC_MONO,
377 FC_CHARCELL
378 };
379
380 #endif
381
382 struct _Style_Map
383 {
384 const char *name;
385 int type;
386 };
387 typedef struct _Style_Map Style_Map;
388
389 static Style_Map _style_width_map[] =
390 {
391 {"normal", EVAS_FONT_WIDTH_NORMAL},
392 {"ultracondensed", EVAS_FONT_WIDTH_ULTRACONDENSED},
393 {"extracondensed", EVAS_FONT_WIDTH_EXTRACONDENSED},
394 {"condensed", EVAS_FONT_WIDTH_CONDENSED},
395 {"semicondensed", EVAS_FONT_WIDTH_SEMICONDENSED},
396 {"semiexpanded", EVAS_FONT_WIDTH_SEMIEXPANDED},
397 {"expanded", EVAS_FONT_WIDTH_EXPANDED},
398 {"extraexpanded", EVAS_FONT_WIDTH_EXTRAEXPANDED},
399 {"ultraexpanded", EVAS_FONT_WIDTH_ULTRAEXPANDED},
400 };
401
402 static Style_Map _style_weight_map[] =
403 {
404 {"normal", EVAS_FONT_WEIGHT_NORMAL},
405 {"thin", EVAS_FONT_WEIGHT_THIN},
406 {"ultralight", EVAS_FONT_WEIGHT_ULTRALIGHT},
407 {"extralight", EVAS_FONT_WEIGHT_EXTRALIGHT},
408 {"light", EVAS_FONT_WEIGHT_LIGHT},
409 {"book", EVAS_FONT_WEIGHT_BOOK},
410 {"medium", EVAS_FONT_WEIGHT_MEDIUM},
411 {"semibold", EVAS_FONT_WEIGHT_SEMIBOLD},
412 {"bold", EVAS_FONT_WEIGHT_BOLD},
413 {"ultrabold", EVAS_FONT_WEIGHT_ULTRABOLD},
414 {"extrabold", EVAS_FONT_WEIGHT_EXTRABOLD},
415 {"black", EVAS_FONT_WEIGHT_BLACK},
416 {"extrablack", EVAS_FONT_WEIGHT_EXTRABLACK}
417 };
418
419 static Style_Map _style_slant_map[] =
420 {
421 {"normal", EVAS_FONT_SLANT_NORMAL},
422 {"oblique", EVAS_FONT_SLANT_OBLIQUE},
423 {"italic", EVAS_FONT_SLANT_ITALIC}
424 };
425
426 static Style_Map _style_spacing_map[] =
427 {
428 {"proportional", EVAS_FONT_SPACING_PROPORTIONAL},
429 {"dualwidth", EVAS_FONT_SPACING_DUAL},
430 {"monospace", EVAS_FONT_SPACING_MONO},
431 {"charcell", EVAS_FONT_SPACING_CHARCELL}
432 };
433
434 #define _STYLE_MAP_LEN(x) (sizeof(x) / sizeof(*(x)))
435
436 /**
437 * @internal
438 * Find the string from the map at a style
439 * @return the string at a style type
440 */
441 static const char*
_evas_font_style_find_str_internal(int type,Style_Map _map[],size_t map_len)442 _evas_font_style_find_str_internal(int type, Style_Map _map[], size_t map_len)
443 {
444 size_t i;
445 for ( i = 0; i < map_len; i++ )
446 {
447 if (_map[i].type == type)
448 return _map[i].name;
449 }
450 return NULL;
451 }
452
453 const char*
evas_font_style_find_str(int type,Evas_Font_Style style)454 evas_font_style_find_str(int type, Evas_Font_Style style)
455 {
456 #define _RET_STYLE(x) \
457 return _evas_font_style_find_str_internal(type, \
458 _style_##x##_map, _STYLE_MAP_LEN(_style_##x##_map));
459 switch (style)
460 {
461 case EVAS_FONT_STYLE_SLANT:
462 _RET_STYLE(slant);
463 case EVAS_FONT_STYLE_WEIGHT:
464 _RET_STYLE(weight);
465 case EVAS_FONT_STYLE_WIDTH:
466 _RET_STYLE(width);
467 default:
468 return NULL;
469 }
470 #undef _RET_STYLE
471 }
472
473 /**
474 * @internal
475 * Find a certain attribute from the map in the style.
476 * @return the index of the found one.
477 */
478 static unsigned int
_evas_font_style_find_internal(const char * style,const char * style_end,Style_Map _map[],size_t map_len)479 _evas_font_style_find_internal(const char *style, const char *style_end,
480 Style_Map _map[], size_t map_len)
481 {
482 size_t i;
483 while (style < style_end)
484 {
485 for (i = 0 ; i < map_len ; i++)
486 {
487 size_t len;
488 const char *cur = _map[i].name;
489 len = strlen(cur);
490 if (!strncasecmp(style, cur, len) &&
491 (!cur[len] || (cur[len] == ' ')))
492 {
493 return _map[i].type;
494 }
495 }
496 style = strchr(style, ' ');
497 if (!style)
498 break;
499
500 while (*style && (*style == ' '))
501 style++;
502 }
503 return 0;
504 }
505
506 unsigned int
evas_font_style_find(const char * start,const char * end,Evas_Font_Style style)507 evas_font_style_find(const char *start, const char *end,
508 Evas_Font_Style style)
509 {
510 #define _RET_STYLE(x) \
511 return _evas_font_style_find_internal(start, end, \
512 _style_##x##_map, _STYLE_MAP_LEN(_style_##x##_map));
513 switch (style)
514 {
515 case EVAS_FONT_STYLE_SLANT:
516 _RET_STYLE(slant);
517 case EVAS_FONT_STYLE_WEIGHT:
518 _RET_STYLE(weight);
519 case EVAS_FONT_STYLE_WIDTH:
520 _RET_STYLE(width);
521 default:
522 return 0;
523 }
524 #undef _RET_STYLE
525 }
526
527 void
evas_font_desc_unref(Evas_Font_Description * fdesc)528 evas_font_desc_unref(Evas_Font_Description *fdesc)
529 {
530 if (--(fdesc->ref) == 0)
531 {
532 eina_stringshare_del(fdesc->name);
533 eina_stringshare_del(fdesc->style);
534 eina_stringshare_del(fdesc->fallbacks);
535 eina_stringshare_del(fdesc->lang);
536 free(fdesc);
537 }
538 }
539
540 Evas_Font_Description *
evas_font_desc_ref(Evas_Font_Description * fdesc)541 evas_font_desc_ref(Evas_Font_Description *fdesc)
542 {
543 fdesc->ref++;
544 return fdesc;
545 }
546
547 Evas_Font_Description *
evas_font_desc_new(void)548 evas_font_desc_new(void)
549 {
550 Evas_Font_Description *fdesc;
551 fdesc = calloc(1, sizeof(*fdesc));
552 fdesc->ref = 1;
553 fdesc->is_new = EINA_TRUE;
554
555 return fdesc;
556 }
557
558 Evas_Font_Description *
evas_font_desc_dup(const Evas_Font_Description * fdesc)559 evas_font_desc_dup(const Evas_Font_Description *fdesc)
560 {
561 Evas_Font_Description *new;
562 new = evas_font_desc_new();
563 memcpy(new, fdesc, sizeof(*new));
564 new->ref = 1;
565 new->is_new = EINA_TRUE;
566 new->name = eina_stringshare_ref(new->name);
567 new->fallbacks = eina_stringshare_ref(new->fallbacks);
568 new->lang = eina_stringshare_ref(new->lang);
569 new->style = eina_stringshare_ref(new->style);
570
571 return new;
572 }
573
574 int
evas_font_desc_cmp(const Evas_Font_Description * a,const Evas_Font_Description * b)575 evas_font_desc_cmp(const Evas_Font_Description *a,
576 const Evas_Font_Description *b)
577 {
578 /* FIXME: Do actual comparison, i.e less than and bigger than. */
579 return !((a->name == b->name) && (a->weight == b->weight) &&
580 (a->slant == b->slant) && (a->width == b->width) &&
581 (a->spacing == b->spacing) && (a->lang == b->lang) &&
582 (a->fallbacks == b->fallbacks));
583 }
584
585 const char *
evas_font_lang_normalize(const char * lang)586 evas_font_lang_normalize(const char *lang)
587 {
588 if (!lang || !strcmp(lang, "none")) return NULL;
589
590 if (!strcmp(lang, "auto"))
591 return evas_common_language_from_locale_full_get();
592
593 return lang;
594 }
595
596 void
evas_font_name_parse(Evas_Font_Description * fdesc,const char * name)597 evas_font_name_parse(Evas_Font_Description *fdesc, const char *name)
598 {
599 const char *end;
600
601 end = strchr(name, ':');
602 if (!end)
603 eina_stringshare_replace(&(fdesc->name), name);
604 else
605 eina_stringshare_replace_length(&(fdesc->name), name, end - name);
606
607 while (end)
608 {
609 const char *tend;
610 name = end;
611 end = strchr(end + 1, ':');
612 if (!end)
613 tend = name + strlen(name);
614 else
615 tend = end;
616
617 if (!strncmp(name, ":style=", 7))
618 {
619 #define _SET_STYLE(x, len) \
620 fdesc->x = _evas_font_style_find_internal(name + len, tend, \
621 _style_##x##_map, _STYLE_MAP_LEN(_style_##x##_map));
622 eina_stringshare_replace_length(&(fdesc->style), name + 7, tend - (name + 7));
623 _SET_STYLE(slant, 7);
624 _SET_STYLE(weight, 7);
625 _SET_STYLE(width, 7);
626 }
627 else if (!strncmp(name, ":slant=", 7))
628 {
629 _SET_STYLE(slant, 7);
630 }
631 else if (!strncmp(name, ":weight=", 8))
632 {
633 _SET_STYLE(weight, 8);
634 }
635 else if (!strncmp(name, ":width=", 7))
636 {
637 _SET_STYLE(width, 7);
638 }
639 else if (!strncmp(name, ":spacing=", 9))
640 {
641 _SET_STYLE(spacing, 9);
642 #undef _SET_STYLE
643 }
644 else if (!strncmp(name, ":lang=", 6))
645 {
646 const char *tmp = name + 6;
647 eina_stringshare_replace_length(&(fdesc->lang), tmp, tend - tmp);
648 eina_stringshare_replace(&(fdesc->lang), evas_font_lang_normalize(fdesc->lang));
649 }
650 else if (!strncmp(name, ":fallbacks=", 11))
651 {
652 const char *tmp = name + 11;
653 eina_stringshare_replace_length(&(fdesc->fallbacks), tmp, tend - tmp);
654 }
655 }
656 }
657
658 void *
evas_font_load(const Eina_List * font_paths,int hinting,Evas_Font_Description * fdesc,const char * source,Evas_Font_Size size,Efl_Text_Font_Bitmap_Scalable bitmap_scalable)659 evas_font_load(const Eina_List *font_paths, int hinting, Evas_Font_Description *fdesc, const char *source, Evas_Font_Size size, Efl_Text_Font_Bitmap_Scalable bitmap_scalable)
660 {
661 #ifdef HAVE_FONTCONFIG
662 FcPattern *p_nm = NULL;
663 FcFontSet *set = NULL;
664 Eina_Bool file_font = EINA_FALSE;
665 #endif
666
667 Evas_Font_Set *font = NULL;
668 Eina_List *fonts, *l, *l_next;
669 Fndat *fd;
670 #ifdef HAVE_FONTCONFIG
671 Fndat *found_fd = NULL;
672 #endif
673 char *nm;
674 Font_Rend_Flags wanted_rend = 0;
675
676 if (!fdesc) return NULL;
677 fdesc->is_new = EINA_FALSE;
678
679 if (fdesc->slant != EVAS_FONT_SLANT_NORMAL)
680 wanted_rend |= FONT_REND_SLANT;
681 if (fdesc->weight == EVAS_FONT_WEIGHT_BOLD)
682 wanted_rend |= FONT_REND_WEIGHT;
683
684 evas_font_init();
685
686 EINA_LIST_FOREACH(fonts_cache, l, fd)
687 {
688 if (!evas_font_desc_cmp(fdesc, fd->fdesc))
689 {
690 if (((!source) && (!fd->source)) ||
691 ((source) && (fd->source) && (!strcmp(source, fd->source))))
692 {
693 if ((size == fd->size) &&
694 (wanted_rend == fd->wanted_rend) &&
695 (bitmap_scalable == fd->bitmap_scalable))
696 {
697 fonts_cache = eina_list_promote_list(fonts_cache, l);
698 fd->ref++;
699 return fd->font;
700 }
701 #ifdef HAVE_FONTCONFIG
702 else if (fd->set && fd->p_nm && !fd->file_font)
703 {
704 found_fd = fd;
705 }
706 #endif
707 }
708 }
709 }
710
711 #ifdef HAVE_FONTCONFIG
712 if (found_fd)
713 {
714 font = _evas_load_fontconfig(font, found_fd->set, size, wanted_rend, bitmap_scalable);
715 goto on_find;
716 }
717 #endif
718
719 EINA_LIST_FOREACH_SAFE(fonts_zero, l, l_next, fd)
720 {
721 if (!evas_font_desc_cmp(fdesc, fd->fdesc))
722 {
723 if (((!source) && (!fd->source)) ||
724 ((source) && (fd->source) && (!strcmp(source, fd->source))))
725 {
726 if ((size == fd->size) &&
727 (wanted_rend == fd->wanted_rend))
728 {
729 fonts_zero = eina_list_remove_list(fonts_zero, l);
730 fonts_cache = eina_list_prepend(fonts_cache, fd);
731 fd->ref++;
732 return fd->font;
733 }
734 #ifdef HAVE_FONTCONFIG
735 else if (fd->set && fd->p_nm && !fd->file_font)
736 {
737 found_fd = fd;
738 }
739 #endif
740 }
741 }
742 }
743
744 #ifdef HAVE_FONTCONFIG
745 if (found_fd)
746 {
747 font = _evas_load_fontconfig(font, found_fd->set, size, wanted_rend, bitmap_scalable);
748 goto on_find;
749 }
750 #endif
751
752 fonts = evas_font_set_get(fdesc->name);
753 EINA_LIST_FOREACH(fonts, l, nm) /* Load each font in append */
754 {
755 if (l == fonts || !font) /* First iteration OR no font */
756 {
757 /*This will suppress warnings for resource leak*/
758 if (font)
759 {
760 evas_common_font_free((RGBA_Font*)font);
761 font = NULL;
762 }
763
764 if (source) /* Load Font from "eet" source */
765 {
766 Eet_File *ef;
767 char fake_name[PATH_MAX];
768
769 eina_file_path_join(fake_name, PATH_MAX, source, nm);
770 font = (Evas_Font_Set *)evas_common_font_load(fake_name, size, wanted_rend, bitmap_scalable);
771 if (!font) /* Load from fake name failed, probably not cached */
772 {
773 /* read original!!! */
774 ef = eet_open(source, EET_FILE_MODE_READ);
775 if (ef)
776 {
777 void *fdata;
778 int fsize = 0;
779
780 fdata = eet_read(ef, nm, &fsize);
781 if (fdata)
782 {
783 font = (Evas_Font_Set *)evas_common_font_memory_load(source, nm, size, fdata, fsize, wanted_rend, bitmap_scalable);
784 free(fdata);
785 }
786 eet_close(ef);
787 }
788 }
789 }
790 if (!font) /* Source load failed */
791 {
792 if (_file_path_is_full_path((char *)nm)) /* Try filename */
793 font = (Evas_Font_Set *)evas_common_font_load((char *)nm, size, wanted_rend, bitmap_scalable);
794 else /* search font path */
795 {
796 const Eina_List *ll;
797 char *dir;
798
799 EINA_LIST_FOREACH(font_paths, ll, dir)
800 {
801 const char *f_file;
802
803 f_file = evas_font_dir_cache_find(dir, (char *)nm);
804 if (f_file)
805 {
806 font = (Evas_Font_Set *)evas_common_font_load(f_file, size, wanted_rend, bitmap_scalable);
807 if (font) break;
808 }
809 }
810
811 if (!font)
812 {
813 EINA_LIST_FOREACH(global_font_path, ll, dir)
814 {
815 const char *f_file;
816
817 f_file = evas_font_dir_cache_find(dir, (char *)nm);
818 if (f_file)
819 {
820 font = (Evas_Font_Set *)evas_common_font_load(f_file, size, wanted_rend, bitmap_scalable);
821 if (font) break;
822 }
823 }
824 }
825 }
826 }
827 }
828 else /* Base font loaded, append others */
829 {
830 void *ok = NULL;
831
832 if (source)
833 {
834 Eet_File *ef;
835 char fake_name[PATH_MAX];
836
837 eina_file_path_join(fake_name, PATH_MAX, source, nm);
838 if (!evas_common_font_add((RGBA_Font *)font, fake_name, size, wanted_rend, bitmap_scalable))
839 {
840 /* read original!!! */
841 ef = eet_open(source, EET_FILE_MODE_READ);
842 if (ef)
843 {
844 void *fdata;
845 int fsize = 0;
846
847 fdata = eet_read(ef, nm, &fsize);
848 if ((fdata) && (fsize > 0))
849 {
850 ok = evas_common_font_memory_add((RGBA_Font *)font, source, nm, size, fdata, fsize, wanted_rend, bitmap_scalable);
851 }
852 eet_close(ef);
853 free(fdata);
854 }
855 }
856 else
857 ok = (void *)1;
858 }
859 if (!ok)
860 {
861 if (_file_path_is_full_path((char *)nm))
862 evas_common_font_add((RGBA_Font *)font, (char *)nm, size, wanted_rend, bitmap_scalable);
863 else
864 {
865 const Eina_List *ll;
866 char *dir;
867 RGBA_Font *fn = NULL;
868
869 EINA_LIST_FOREACH(font_paths, ll, dir)
870 {
871 const char *f_file;
872
873 f_file = evas_font_dir_cache_find(dir, (char *)nm);
874 if (f_file)
875 {
876 fn = evas_common_font_add((RGBA_Font *)font, f_file, size, wanted_rend, bitmap_scalable);
877 if (fn)
878 break;
879 }
880 }
881
882 if (!fn)
883 {
884 EINA_LIST_FOREACH(global_font_path, ll, dir)
885 {
886 const char *f_file;
887
888 f_file = evas_font_dir_cache_find(dir, (char *)nm);
889 if (f_file)
890 {
891 fn = evas_common_font_add((RGBA_Font *)font, f_file, size, wanted_rend, bitmap_scalable);
892 if (fn)
893 break;
894 }
895 }
896 }
897 }
898 }
899 }
900 eina_stringshare_del(nm);
901 }
902 eina_list_free(fonts);
903
904 #ifdef HAVE_FONTCONFIG
905 if (!font) /* Search using fontconfig */
906 {
907 FcResult res;
908
909 p_nm = FcPatternBuild (NULL,
910 FC_WEIGHT, FcTypeInteger, _fc_weight_map[fdesc->weight],
911 FC_SLANT, FcTypeInteger, _fc_slant_map[fdesc->slant],
912 FC_SPACING, FcTypeInteger, _fc_spacing_map[fdesc->spacing],
913 #ifdef FC_WIDTH
914 FC_WIDTH, FcTypeInteger, _fc_width_map[fdesc->width],
915 #endif
916 NULL);
917 FcPatternAddString (p_nm, FC_FAMILY, (FcChar8*) fdesc->name);
918
919 if (fdesc->style)
920 FcPatternAddString (p_nm, FC_STYLE, (FcChar8*) fdesc->style);
921
922 /* Handle font fallbacks */
923 if (fdesc->fallbacks)
924 {
925 const char *start, *end;
926 start = fdesc->fallbacks;
927
928 while (start)
929 {
930 end = strchr(start, ',');
931 if (end)
932 {
933 char *tmp = alloca((end - start) + 1);
934 strncpy(tmp, start, end - start);
935 tmp[end - start] = 0;
936 FcPatternAddString (p_nm, FC_FAMILY, (FcChar8*) tmp);
937 start = end + 1;
938 }
939 else
940 {
941 FcPatternAddString (p_nm, FC_FAMILY, (FcChar8*) start);
942 break;
943 }
944 }
945 }
946
947 if (fdesc->lang)
948 FcPatternAddString (p_nm, FC_LANG, (FcChar8 *) fdesc->lang);
949
950 FcConfigSubstitute(fc_config, p_nm, FcMatchPattern);
951 FcDefaultSubstitute(p_nm);
952
953 /* do matching */
954 set = FcFontSort(fc_config, p_nm, FcTrue, NULL, &res);
955 if (!set)
956 {
957 //FIXME add ERR log capability
958 //ERR("No fontconfig font matches '%s'. It was the last resource, no font found!", fdesc->name);
959 FcPatternDestroy(p_nm);
960 p_nm = NULL;
961 }
962 else
963 {
964 font = _evas_load_fontconfig(font, set, size, wanted_rend, bitmap_scalable);
965 }
966 }
967 else /* Add a fallback list from fontconfig according to the found font. */
968 {
969 #if FC_MAJOR >= 2 && FC_MINOR >= 11
970 FcResult res;
971
972 FT_Face face = evas_common_font_freetype_face_get((RGBA_Font *) font);
973
974 file_font = EINA_TRUE;
975
976 if (face)
977 {
978 p_nm = FcFreeTypeQueryFace(face, (FcChar8 *) "", 0, NULL);
979 FcConfigSubstitute(fc_config, p_nm, FcMatchPattern);
980 FcDefaultSubstitute(p_nm);
981
982 /* do matching */
983 set = FcFontSort(fc_config, p_nm, FcTrue, NULL, &res);
984 if (!set)
985 {
986 FcPatternDestroy(p_nm);
987 p_nm = NULL;
988 }
989 else
990 {
991 font = _evas_load_fontconfig(font, set, size, wanted_rend, bitmap_scalable);
992 }
993 }
994 #endif
995 }
996 #endif
997
998 #ifdef HAVE_FONTCONFIG
999 on_find:
1000 #endif
1001 fd = calloc(1, sizeof(Fndat));
1002 if (fd)
1003 {
1004 fd->fdesc = evas_font_desc_ref(fdesc);
1005 if (source) fd->source = eina_stringshare_add(source);
1006 fd->font = font;
1007 fd->wanted_rend = wanted_rend;
1008 fd->size = size;
1009 fd->bitmap_scalable = bitmap_scalable;
1010 fd->ref = 1;
1011 fonts_cache = eina_list_prepend(fonts_cache, fd);
1012 #ifdef HAVE_FONTCONFIG
1013 fd->set = set;
1014 fd->p_nm = p_nm;
1015 fd->file_font = file_font;
1016 #endif
1017 }
1018
1019 if (font)
1020 evas_common_font_hinting_set((RGBA_Font *)font, hinting);
1021 return font;
1022 }
1023
1024 void
evas_font_load_hinting_set(void * font,int hinting)1025 evas_font_load_hinting_set(void *font, int hinting)
1026 {
1027 evas_common_font_hinting_set((RGBA_Font *) font, hinting);
1028 }
1029
1030 Eina_List *
evas_font_dir_available_list(const Eina_List * font_paths)1031 evas_font_dir_available_list(const Eina_List *font_paths)
1032 {
1033 const Eina_List *l;
1034 Eina_List *ll;
1035 Eina_List *available = NULL;
1036 char *dir;
1037
1038 #ifdef HAVE_FONTCONFIG
1039 /* Add font config fonts */
1040 FcPattern *p;
1041 FcFontSet *set = NULL;
1042 FcObjectSet *os;
1043 int i;
1044
1045 evas_font_init();
1046
1047 p = FcPatternCreate();
1048 os = FcObjectSetBuild(FC_FAMILY, FC_STYLE, NULL);
1049
1050 if (p && os) set = FcFontList(fc_config, p, os);
1051
1052 if (p) FcPatternDestroy(p);
1053 if (os) FcObjectSetDestroy(os);
1054
1055 if (set)
1056 {
1057 for (i = 0; i < set->nfont; i++)
1058 {
1059 char *font;
1060
1061 font = (char *)FcNameUnparse(set->fonts[i]);
1062 available = eina_list_append(available, eina_stringshare_add(font));
1063 free(font);
1064 }
1065
1066 FcFontSetDestroy(set);
1067 }
1068 #endif
1069
1070 /* Add fonts in font_paths*/
1071 if (font_paths)
1072 {
1073 if (!font_dirs) font_dirs = eina_hash_string_superfast_new(NULL);
1074
1075 EINA_LIST_FOREACH(font_paths, l, dir)
1076 {
1077 Evas_Font_Dir *fd;
1078
1079 fd = eina_hash_find(font_dirs, dir);
1080 fd = object_text_font_cache_dir_update(dir, fd);
1081 if (fd && fd->aliases)
1082 {
1083 Evas_Font_Alias *fa;
1084
1085 EINA_LIST_FOREACH(fd->aliases, ll, fa)
1086 available = eina_list_append(available, eina_stringshare_add((char *)fa->alias));
1087 }
1088 }
1089 }
1090
1091 if (global_font_path)
1092 {
1093 if (!font_dirs) font_dirs = eina_hash_string_superfast_new(NULL);
1094
1095 EINA_LIST_FOREACH(global_font_path, l, dir)
1096 {
1097 Evas_Font_Dir *fd;
1098
1099 fd = eina_hash_find(font_dirs, dir);
1100 fd = object_text_font_cache_dir_update(dir, fd);
1101 if (fd && fd->aliases)
1102 {
1103 Evas_Font_Alias *fa;
1104
1105 EINA_LIST_FOREACH(fd->aliases, ll, fa)
1106 available = eina_list_append(available, eina_stringshare_add((char *)fa->alias));
1107 }
1108 }
1109 }
1110
1111 return available;
1112 }
1113
1114 void
evas_font_dir_available_list_free(Eina_List * available)1115 evas_font_dir_available_list_free(Eina_List *available)
1116 {
1117 while (available)
1118 {
1119 eina_stringshare_del(available->data);
1120 available = eina_list_remove(available, available->data);
1121 }
1122 }
1123
1124 /* private stuff */
1125 static Eina_Bool
font_cache_dir_free(const Eina_Hash * hash EINA_UNUSED,const void * key,void * data,void * fdata EINA_UNUSED)1126 font_cache_dir_free(const Eina_Hash *hash EINA_UNUSED, const void *key, void *data, void *fdata EINA_UNUSED)
1127 {
1128 object_text_font_cache_dir_del((char *) key, data);
1129 return 1;
1130 }
1131
1132 static Evas_Font_Dir *
object_text_font_cache_dir_update(char * dir,Evas_Font_Dir * fd)1133 object_text_font_cache_dir_update(char *dir, Evas_Font_Dir *fd)
1134 {
1135 char file_path[PATH_MAX];
1136 DATA64 mt;
1137
1138 if (fd)
1139 {
1140 mt = _file_modified_time(dir);
1141 if (mt != fd->dir_mod_time)
1142 {
1143 eina_hash_del(font_dirs, dir, fd);
1144 object_text_font_cache_dir_del(dir, fd);
1145 }
1146 else
1147 {
1148 eina_file_path_join(file_path, PATH_MAX, dir, "fonts.dir");
1149 mt = _file_modified_time(file_path);
1150 if (mt != fd->fonts_dir_mod_time)
1151 {
1152 eina_hash_del(font_dirs, dir, fd);
1153 object_text_font_cache_dir_del(dir, fd);
1154 }
1155 else
1156 {
1157 eina_file_path_join(file_path, PATH_MAX, dir, "fonts.alias");
1158 mt = _file_modified_time(file_path);
1159 if (mt != fd->fonts_alias_mod_time)
1160 {
1161 eina_hash_del(font_dirs, dir, fd);
1162 object_text_font_cache_dir_del(dir, fd);
1163 }
1164 else
1165 return fd;
1166 }
1167 }
1168 }
1169 return object_text_font_cache_dir_add(dir);
1170 }
1171
1172 static Evas_Font *
object_text_font_cache_font_find_x(Evas_Font_Dir * fd,char * font)1173 object_text_font_cache_font_find_x(Evas_Font_Dir *fd, char *font)
1174 {
1175 Eina_List *l;
1176 char font_prop[14][256];
1177 int num;
1178 Evas_Font *fn;
1179
1180 num = evas_object_text_font_string_parse(font, font_prop);
1181 if (num != 14) return NULL;
1182 EINA_LIST_FOREACH(fd->fonts, l, fn)
1183 {
1184 if (fn->type == 1)
1185 {
1186 int i;
1187 int match = 0;
1188
1189 for (i = 0; i < 14; i++)
1190 {
1191 if ((font_prop[i][0] == '*') && (font_prop[i][1] == 0))
1192 match++;
1193 else
1194 {
1195 if (!strcasecmp(font_prop[i], fn->x.prop[i])) match++;
1196 else break;
1197 }
1198 }
1199 if (match == 14) return fn;
1200 }
1201 }
1202 return NULL;
1203 }
1204
1205 static Evas_Font *
object_text_font_cache_font_find_file(Evas_Font_Dir * fd,char * font)1206 object_text_font_cache_font_find_file(Evas_Font_Dir *fd, char *font)
1207 {
1208 Eina_List *l;
1209 Evas_Font *fn;
1210
1211 EINA_LIST_FOREACH(fd->fonts, l, fn)
1212 {
1213 if (fn->type == 0)
1214 {
1215 if (!strcasecmp(font, fn->simple.name)) return fn;
1216 }
1217 }
1218 return NULL;
1219 }
1220
1221 static Evas_Font *
object_text_font_cache_font_find_alias(Evas_Font_Dir * fd,char * font)1222 object_text_font_cache_font_find_alias(Evas_Font_Dir *fd, char *font)
1223 {
1224 Eina_List *l;
1225 Evas_Font_Alias *fa;
1226
1227 EINA_LIST_FOREACH(fd->aliases, l, fa)
1228 if (!strcasecmp(fa->alias, font)) return fa->fn;
1229 return NULL;
1230 }
1231
1232 static Evas_Font *
object_text_font_cache_font_find(Evas_Font_Dir * fd,char * font)1233 object_text_font_cache_font_find(Evas_Font_Dir *fd, char *font)
1234 {
1235 Evas_Font *fn;
1236
1237 fn = eina_hash_find(fd->lookup, font);
1238 if (fn) return fn;
1239 fn = object_text_font_cache_font_find_alias(fd, font);
1240 if (!fn) fn = object_text_font_cache_font_find_x(fd, font);
1241 if (!fn) fn = object_text_font_cache_font_find_file(fd, font);
1242 if (!fn) return NULL;
1243 eina_hash_add(fd->lookup, font, fn);
1244 return fn;
1245 }
1246
1247 static Evas_Font_Dir *
object_text_font_cache_dir_add(char * dir)1248 object_text_font_cache_dir_add(char *dir)
1249 {
1250 char file_path[PATH_MAX];
1251 Evas_Font_Dir *fd;
1252 char *file;
1253 char tmp2[PATH_MAX];
1254 Eina_List *fdir;
1255 Evas_Font *fn;
1256 FILE *f;
1257
1258 fd = calloc(1, sizeof(Evas_Font_Dir));
1259 if (!fd) return NULL;
1260 fd->lookup = eina_hash_string_superfast_new(NULL);
1261
1262 eina_hash_add(font_dirs, dir, fd);
1263
1264 /* READ fonts.alias, fonts.dir and directory listing */
1265
1266 /* fonts.dir */
1267 eina_file_path_join(file_path, PATH_MAX, dir, "fonts.dir");
1268
1269 f = fopen(file_path, "rb");
1270 if (f)
1271 {
1272 int num;
1273 char fname[4096], fdef[4096];
1274
1275 if (fscanf(f, "%i\n", &num) != 1) goto cant_read;
1276 /* read font lines */
1277 while (fscanf(f, "%4090s %[^\n]\n", fname, fdef) == 2)
1278 {
1279 char font_prop[14][256];
1280 int i;
1281
1282 /* skip comments */
1283 if ((fdef[0] == '!') || (fdef[0] == '#')) continue;
1284 /* parse font def */
1285 num = evas_object_text_font_string_parse((char *)fdef, font_prop);
1286 if (num == 14)
1287 {
1288 fn = calloc(1, sizeof(Evas_Font));
1289 if (fn)
1290 {
1291 fn->type = 1;
1292 for (i = 0; i < 14; i++)
1293 fn->x.prop[i] = eina_stringshare_add(font_prop[i]);
1294 eina_file_path_join(tmp2, PATH_MAX, dir, fname);
1295 fn->path = eina_stringshare_add(tmp2);
1296 fd->fonts = eina_list_append(fd->fonts, fn);
1297 }
1298 }
1299 }
1300 cant_read: ;
1301 fclose(f);
1302 }
1303
1304 /* directoy listing */
1305 fdir = _file_path_list(dir, "*.ttf", 0);
1306 EINA_LIST_FREE(fdir, file)
1307 {
1308 eina_file_path_join(file_path, PATH_MAX, dir, file);
1309 fn = calloc(1, sizeof(Evas_Font));
1310 if (fn)
1311 {
1312 char *p;
1313
1314 fn->type = 0;
1315 p = strrchr(file, '.');
1316 if (p) fn->simple.name = eina_stringshare_add_length(file, p - file);
1317 else fn->simple.name = eina_stringshare_add(file);
1318 eina_file_path_join(tmp2, PATH_MAX, dir, file);
1319 fn->path = eina_stringshare_add(tmp2);
1320 fd->fonts = eina_list_append(fd->fonts, fn);
1321 }
1322 free(file);
1323 }
1324
1325 /* fonts.alias */
1326 eina_file_path_join(file_path, PATH_MAX, dir, "fonts.alias");
1327
1328 f = fopen(file_path, "rb");
1329 if (f)
1330 {
1331 char fname[4096], fdef[4096];
1332
1333 /* read font alias lines */
1334 while (fscanf(f, "%4090s %4090[^\n]\n", fname, fdef) == 2)
1335 {
1336 Evas_Font_Alias *fa;
1337
1338 /* skip comments */
1339 if ((fname[0] == '!') || (fname[0] == '#')) continue;
1340 fa = calloc(1, sizeof(Evas_Font_Alias));
1341 if (fa)
1342 {
1343 fa->alias = eina_stringshare_add(fname);
1344 fa->fn = object_text_font_cache_font_find_x(fd, fdef);
1345 if ((!fa->alias) || (!fa->fn))
1346 {
1347 if (fa->alias) eina_stringshare_del(fa->alias);
1348 free(fa);
1349 }
1350 else
1351 fd->aliases = eina_list_append(fd->aliases, fa);
1352 }
1353 }
1354 fclose(f);
1355 }
1356
1357 fd->dir_mod_time = _file_modified_time(dir);
1358
1359 eina_file_path_join(file_path, PATH_MAX, dir, "fonts.dir");
1360 fd->fonts_dir_mod_time = _file_modified_time(file_path);
1361
1362 eina_file_path_join(file_path, PATH_MAX, dir, "fonts.alias");
1363 fd->fonts_alias_mod_time = _file_modified_time(file_path);
1364
1365 return fd;
1366 }
1367
1368 static void
object_text_font_cache_dir_del(char * dir EINA_UNUSED,Evas_Font_Dir * fd)1369 object_text_font_cache_dir_del(char *dir EINA_UNUSED, Evas_Font_Dir *fd)
1370 {
1371 if (fd->lookup) eina_hash_free(fd->lookup);
1372 while (fd->fonts)
1373 {
1374 Evas_Font *fn;
1375 int i;
1376
1377 fn = fd->fonts->data;
1378 fd->fonts = eina_list_remove(fd->fonts, fn);
1379 for (i = 0; i < 14; i++)
1380 {
1381 if (fn->x.prop[i]) eina_stringshare_del(fn->x.prop[i]);
1382 }
1383 if (fn->simple.name) eina_stringshare_del(fn->simple.name);
1384 if (fn->path) eina_stringshare_del(fn->path);
1385 free(fn);
1386 }
1387 while (fd->aliases)
1388 {
1389 Evas_Font_Alias *fa;
1390
1391 fa = fd->aliases->data;
1392 fd->aliases = eina_list_remove(fd->aliases, fa);
1393 if (fa->alias) eina_stringshare_del(fa->alias);
1394 free(fa);
1395 }
1396 free(fd);
1397 }
1398
1399 static int
evas_object_text_font_string_parse(char * buffer,char dest[14][256])1400 evas_object_text_font_string_parse(char *buffer, char dest[14][256])
1401 {
1402 char *p;
1403 int n, m, i;
1404
1405 n = 0;
1406 m = 0;
1407 p = buffer;
1408 if (p[0] != '-') return 0;
1409 i = 1;
1410 while (p[i])
1411 {
1412 dest[n][m] = p[i];
1413 if ((p[i] == '-') || (m == 255))
1414 {
1415 dest[n][m] = 0;
1416 n++;
1417 m = -1;
1418 }
1419 i++;
1420 m++;
1421 if (n == 14) return n;
1422 }
1423 dest[n][m] = 0;
1424 n++;
1425 return n;
1426 }
1427
1428 EAPI void
evas_font_path_global_append(const char * path)1429 evas_font_path_global_append(const char *path)
1430 {
1431 if (!path) return;
1432 global_font_path = eina_list_append(global_font_path, eina_stringshare_add(path));
1433 #ifdef HAVE_FONTCONFIG
1434 if (fc_config)
1435 FcConfigAppFontAddDir(fc_config, (const FcChar8 *) path);
1436 #endif
1437 }
1438
1439 EAPI void
evas_font_path_global_prepend(const char * path)1440 evas_font_path_global_prepend(const char *path)
1441 {
1442 if (!path) return;
1443 global_font_path = eina_list_prepend(global_font_path, eina_stringshare_add(path));
1444 #ifdef HAVE_FONTCONFIG
1445 if (fc_config)
1446 FcConfigAppFontAddDir(fc_config, (const FcChar8 *) path);
1447 #endif
1448 }
1449
1450 EAPI void
evas_font_path_global_clear(void)1451 evas_font_path_global_clear(void)
1452 {
1453 while (global_font_path)
1454 {
1455 eina_stringshare_del(global_font_path->data);
1456 global_font_path = eina_list_remove(global_font_path, global_font_path->data);
1457 }
1458 #ifdef HAVE_FONTCONFIG
1459 if (fc_config)
1460 FcConfigAppFontClear(fc_config);
1461 #endif
1462 }
1463
1464 EAPI const Eina_List *
evas_font_path_global_list(void)1465 evas_font_path_global_list(void)
1466 {
1467 return global_font_path;
1468 }
1469
1470 EAPI void
evas_font_reinit(void)1471 evas_font_reinit(void)
1472 {
1473 #ifdef HAVE_FONTCONFIG
1474 Eina_List *l;
1475 char *path;
1476
1477 if (fc_config)
1478 {
1479 FcConfigDestroy(fc_config);
1480 fc_config = FcInitLoadConfigAndFonts();
1481
1482 EINA_LIST_FOREACH(global_font_path, l, path)
1483 FcConfigAppFontAddDir(fc_config, (const FcChar8 *) path);
1484 }
1485 #endif
1486 }
1487