1 #include "evas_common.h"
2 #include "evas_private.h"
6 #include "evas_font_private.h" /* for Frame-Queuing support */
7 #include "evas_font_ot.h"
10 # include "../../cserve2/evas_cs2_private.h"
18 extern FT_Library evas_ft_lib;
20 static int font_cache_usage = 0;
21 static int font_cache = 0;
22 static int font_dpi = 75;
24 static Eina_Hash *fonts_src = NULL;
25 static Eina_Hash *fonts = NULL;
26 static Eina_List *fonts_lru = NULL;
27 static Eina_Inlist *fonts_use_lru = NULL;
28 static int fonts_use_usage = 0;
30 static void _evas_common_font_int_clear(RGBA_Font_Int *fi);
33 _evas_font_cache_int_cmp(const RGBA_Font_Int *k1, int k1_length __UNUSED__,
34 const RGBA_Font_Int *k2, int k2_length __UNUSED__)
36 /* RGBA_Font_Source->name is a stringshare */
37 if (k1->src->name == k2->src->name)
39 if (k1->size == k2->size)
40 return k1->wanted_rend - k2->wanted_rend;
42 return k1->size - k2->size;
44 return strcmp(k1->src->name, k2->src->name);
48 _evas_font_cache_int_hash(const RGBA_Font_Int *key, int key_length __UNUSED__)
51 unsigned int wanted_rend = key->wanted_rend;
52 hash = eina_hash_djb2(key->src->name, eina_stringshare_strlen(key->src->name) + 1);
53 hash ^= eina_hash_int32(&key->size, sizeof (int));
54 hash ^= eina_hash_int32(&wanted_rend, sizeof (int));
59 _evas_common_font_source_free(RGBA_Font_Source *fs)
62 FT_Done_Face(fs->ft.face);
64 if (fs->name) eina_stringshare_del(fs->name);
65 if (fs->file) eina_stringshare_del(fs->file);
70 _evas_common_font_int_free(RGBA_Font_Int *fi)
72 FT_Done_Size(fi->ft.size);
74 evas_common_font_int_modify_cache_by(fi, -1);
75 _evas_common_font_int_clear(fi);
76 eina_hash_free(fi->kerning);
80 hb_font_destroy(fi->ft.hb_font);
82 evas_common_font_source_free(fi->src);
83 if (fi->references <= 0) fonts_lru = eina_list_remove(fonts_lru, fi);
84 if (fi->fash) fi->fash->freeme(fi->fash);
87 fonts_use_lru = eina_inlist_remove(fonts_use_lru, EINA_INLIST_GET(fi));
89 fonts_use_usage -= fi->usage;
93 evas_cserve2_font_free(fi->cs2_handler);
99 evas_common_font_load_init(void)
101 fonts_src = eina_hash_string_small_new(EINA_FREE_CB(_evas_common_font_source_free));
102 fonts = eina_hash_new(NULL,
103 EINA_KEY_CMP(_evas_font_cache_int_cmp),
104 EINA_KEY_HASH(_evas_font_cache_int_hash),
105 EINA_FREE_CB(_evas_common_font_int_free),
110 evas_common_font_load_shutdown(void)
112 eina_hash_free(fonts);
114 eina_hash_free(fonts_src);
119 evas_common_font_dpi_set(int dpi)
124 EAPI RGBA_Font_Source *
125 evas_common_font_source_memory_load(const char *name, const void *data, int data_size)
128 RGBA_Font_Source *fs;
130 assert(name != NULL);
131 fs = calloc(1, sizeof(RGBA_Font_Source) + data_size);
132 if (!fs) return NULL;
133 fs->data = ((unsigned char *)fs) + sizeof(RGBA_Font_Source);
134 fs->data_size = data_size;
135 fs->current_size = 0;
136 memcpy(fs->data, data, data_size);
138 error = FT_New_Memory_Face(evas_ft_lib, fs->data, fs->data_size, 0, &(fs->ft.face));
145 fs->name = eina_stringshare_add(name);
148 error = FT_Select_Charmap(fs->ft.face, ft_encoding_unicode);
151 FT_Done_Face(fs->ft.face);
157 fs->ft.orig_upem = fs->ft.face->units_per_EM;
159 eina_hash_direct_add(fonts_src, fs->name, fs);
163 EAPI RGBA_Font_Source *
164 evas_common_font_source_load(const char *name)
166 RGBA_Font_Source *fs;
168 assert(name != NULL);
169 fs = calloc(1, sizeof(RGBA_Font_Source));
170 if (!fs) return NULL;
173 fs->current_size = 0;
175 fs->name = eina_stringshare_add(name);
176 fs->file = eina_stringshare_ref(fs->name);
177 fs->ft.orig_upem = 0;
179 eina_hash_direct_add(fonts_src, fs->name, fs);
184 evas_common_font_source_unload(RGBA_Font_Source *fs)
187 FT_Done_Face(fs->ft.face);
193 evas_common_font_source_reload(RGBA_Font_Source *fs)
195 if (fs->ft.face) return;
201 error = FT_New_Memory_Face(evas_ft_lib, fs->data, fs->data_size, 0, &(fs->ft.face));
205 error = FT_Select_Charmap(fs->ft.face, ft_encoding_unicode);
208 FT_Done_Face(fs->ft.face);
214 evas_common_font_source_load_complete(fs);
218 evas_common_font_source_load_complete(RGBA_Font_Source *fs)
223 error = FT_New_Face(evas_ft_lib, fs->file, 0, &(fs->ft.face));
230 error = FT_Select_Charmap(fs->ft.face, ft_encoding_unicode);
233 FT_Done_Face(fs->ft.face);
239 fs->ft.orig_upem = fs->ft.face->units_per_EM;
243 EAPI RGBA_Font_Source *
244 evas_common_font_source_find(const char *name)
246 RGBA_Font_Source *fs;
248 if (!name) return NULL;
249 fs = eina_hash_find(fonts_src, name);
259 evas_common_font_source_free(RGBA_Font_Source *fs)
262 if (fs->references > 0) return;
263 eina_hash_del(fonts_src, fs->name, fs);
267 evas_common_font_size_use(RGBA_Font *fn)
272 EINA_LIST_FOREACH(fn->fonts, l, fi)
274 if (fi->src->current_size != fi->size)
276 evas_common_font_source_reload(fi->src);
278 FT_Activate_Size(fi->ft.size);
280 fi->src->current_size = fi->size;
286 _evas_common_font_double_int_cmp(const int *key1, __UNUSED__ int key1_length,
287 const int *key2, __UNUSED__ int key2_length)
289 if (key1[0] - key2[0] == 0) return key1[1] - key2[1];
290 return key1[0] - key2[0];
294 _evas_common_font_double_int_hash(const unsigned int key[2], int key_length)
297 eina_hash_int32(&key[0], key_length) ^
298 eina_hash_int32(&key[1], key_length);
302 _evas_common_font_int_cache_init(RGBA_Font_Int *fi)
304 /* Add some font kerning cache. */
305 fi->kerning = eina_hash_new(NULL,
306 EINA_KEY_CMP(_evas_common_font_double_int_cmp),
307 EINA_KEY_HASH(_evas_common_font_double_int_hash),
313 evas_common_font_int_memory_load(const char *source, const char *name, int size, const void *data, int data_size, Font_Rend_Flags wanted_rend)
318 fake_name = evas_file_path_join(source, name);
319 fi = evas_common_font_int_find(fake_name, size, wanted_rend);
325 fi = calloc(1, sizeof(RGBA_Font_Int));
331 fi->src = evas_common_font_source_find(fake_name);
333 fi->src = evas_common_font_source_memory_load(fake_name, data, data_size);
341 _evas_common_font_int_cache_init(fi);
342 fi = evas_common_font_int_load_init(fi);
343 evas_common_font_int_load_complete(fi);
345 if (evas_cserve2_use_get())
346 fi->cs2_handler = evas_cserve2_font_load(source, name, size, font_dpi,
354 evas_common_font_int_load(const char *name, int size,
355 Font_Rend_Flags wanted_rend)
359 fi = evas_common_font_int_find(name, size, wanted_rend);
361 fi = calloc(1, sizeof(RGBA_Font_Int));
362 if (!fi) return NULL;
363 fi->src = evas_common_font_source_find(name);
364 if (!fi->src && evas_file_path_is_file(name))
365 fi->src = evas_common_font_source_load(name);
373 fi->wanted_rend = wanted_rend;
374 _evas_common_font_int_cache_init(fi);
375 fi = evas_common_font_int_load_init(fi);
377 if (evas_cserve2_use_get())
378 fi->cs2_handler = evas_cserve2_font_load(NULL, name, size, font_dpi,
381 // evas_common_font_int_load_complete(fi);
386 evas_common_font_int_load_init(RGBA_Font_Int *fi)
390 eina_hash_direct_add(fonts, fi, fi);
395 evas_common_font_int_load_complete(RGBA_Font_Int *fi)
402 error = FT_New_Size(fi->src->ft.face, &(fi->ft.size));
405 FT_Activate_Size(fi->ft.size);
407 fi->real_size = fi->size * 64;
408 error = FT_Set_Char_Size(fi->src->ft.face, 0, fi->real_size, font_dpi, font_dpi);
410 error = FT_Set_Pixel_Sizes(fi->src->ft.face, 0, fi->real_size);
414 int i, maxd = 0x7fffffff;
416 int chosen_size2 = 0;
418 for (i = 0; i < fi->src->ft.face->num_fixed_sizes; i++)
422 s = fi->src->ft.face->available_sizes[i].size;
423 cd = chosen_size - fi->real_size;
424 if (cd < 0) cd = -cd;
429 chosen_size2 = fi->src->ft.face->available_sizes[i].y_ppem;
430 if (maxd == 0) break;
433 fi->real_size = chosen_size;
435 error = FT_Set_Pixel_Sizes(fi->src->ft.face, 0, fi->real_size);
439 error = FT_Set_Char_Size(fi->src->ft.face, 0, fi->real_size, font_dpi, font_dpi);
442 /* hack around broken fonts */
443 fi->real_size = (chosen_size2 / 64) * 60;
444 error = FT_Set_Char_Size(fi->src->ft.face, 0, fi->real_size, font_dpi, font_dpi);
447 /* couldn't choose the size anyway... what now? */
452 fi->src->current_size = 0;
454 val = (int)fi->src->ft.face->bbox.yMax;
455 if (fi->src->ft.face->units_per_EM != 0)
457 dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
458 ret = FONT_METRIC_CONV(val, dv, fi->src->ft.face->size->metrics.y_scale);
462 if ((fi->src->ft.face->bbox.yMax == 0) &&
463 (fi->src->ft.face->bbox.yMin == 0))
464 ret = FONT_METRIC_ROUNDUP((int)fi->ft.size->metrics.ascender);
469 val = -(int)fi->src->ft.face->bbox.yMin;
470 if (fi->src->ft.face->units_per_EM != 0)
472 dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
473 ret = FONT_METRIC_CONV(val, dv, fi->src->ft.face->size->metrics.y_scale);
477 if ((fi->src->ft.face->bbox.yMax == 0) &&
478 (fi->src->ft.face->bbox.yMin == 0))
479 ret = FONT_METRIC_ROUNDUP(-(int)fi->ft.size->metrics.descender);
485 /* If the loaded font doesn't match with wanted_rend value requested by
486 * textobject and textblock, Set the runtime_rend value as FONT_REND_SLANT
487 * or FONT_REND_WEIGHT for software rendering. */
488 fi->runtime_rend = FONT_REND_REGULAR;
489 if ((fi->wanted_rend & FONT_REND_SLANT) &&
490 !(fi->src->ft.face->style_flags & FT_STYLE_FLAG_ITALIC))
491 fi->runtime_rend |= FONT_REND_SLANT;
493 if ((fi->wanted_rend & FONT_REND_WEIGHT) &&
494 !(fi->src->ft.face->style_flags & FT_STYLE_FLAG_BOLD))
495 fi->runtime_rend |= FONT_REND_WEIGHT;
501 evas_common_font_memory_load(const char *source, const char *name, int size, const void *data, int data_size, Font_Rend_Flags wanted_rend)
506 fi = evas_common_font_int_memory_load(source, name, size, data, data_size,
508 if (!fi) return NULL;
509 fn = calloc(1, sizeof(RGBA_Font));
512 evas_common_font_int_unref(fi);
515 fn->fonts = eina_list_append(fn->fonts, fi);
516 fn->hinting = FONT_BYTECODE_HINT;
517 fi->hinting = fn->hinting;
520 if (fi->inuse) evas_common_font_int_promote(fi);
524 fonts_use_lru = eina_inlist_prepend(fonts_use_lru, EINA_INLIST_GET(fi));
530 //ZZZ: font struct looks like:
531 // fn->(fi, fi, fi, ...)
535 evas_common_font_load(const char *name, int size, Font_Rend_Flags wanted_rend)
540 fi = evas_common_font_int_load(name, size, wanted_rend);
541 if (!fi) return NULL;
542 /* First font, complete load */
545 if (!fi->src->ft.face)
547 if (evas_common_font_source_load_complete(fi->src))
549 evas_common_font_int_unref(fi);
553 evas_common_font_int_load_complete(fi);
555 fn = calloc(1, sizeof(RGBA_Font));
558 evas_common_font_int_unref(fi);
562 fn->fonts = eina_list_append(fn->fonts, fi);
563 fn->hinting = FONT_BYTECODE_HINT;
564 fi->hinting = fn->hinting;
567 if (fi->inuse) evas_common_font_int_promote(fi);
571 fonts_use_lru = eina_inlist_prepend(fonts_use_lru, EINA_INLIST_GET(fi));
577 evas_common_font_add(RGBA_Font *fn, const char *name, int size, Font_Rend_Flags wanted_rend)
581 if (!fn) return NULL;
582 fi = evas_common_font_int_load(name, size, wanted_rend);
585 fn->fonts = eina_list_append(fn->fonts, fi);
586 fi->hinting = fn->hinting;
587 if (fi->inuse) evas_common_font_int_promote(fi);
591 fonts_use_lru = eina_inlist_prepend(fonts_use_lru, EINA_INLIST_GET(fi));
599 evas_common_font_memory_add(RGBA_Font *fn, const char *source, const char *name, int size, const void *data, int data_size, Font_Rend_Flags wanted_rend)
605 fi = evas_common_font_int_memory_load(source, name, size, data, data_size, wanted_rend);
608 fn->fonts = eina_list_append(fn->fonts, fi);
609 fi->hinting = fn->hinting;
610 if (fi->inuse) evas_common_font_int_promote(fi);
614 fonts_use_lru = eina_inlist_prepend(fonts_use_lru, EINA_INLIST_GET(fi));
622 evas_common_font_int_unref(RGBA_Font_Int *fi)
625 if (fi->references == 0)
627 fonts_lru = eina_list_append(fonts_lru, fi);
628 evas_common_font_int_modify_cache_by(fi, 1);
629 evas_common_font_flush();
634 evas_common_font_free(RGBA_Font *fn)
641 if (fn->references > 0) return;
642 EINA_LIST_FOREACH(fn->fonts, l, fi)
643 evas_common_font_int_unref(fi);
644 evas_common_font_flush();
645 eina_list_free(fn->fonts);
646 if (fn->fash) fn->fash->freeme(fn->fash);
652 evas_common_font_hinting_set(RGBA_Font *fn, Font_Hint_Flags hinting)
658 fn->hinting = hinting;
659 EINA_LIST_FOREACH(fn->fonts, l, fi)
661 fi->hinting = fn->hinting;
666 evas_common_hinting_available(Font_Hint_Flags hinting)
672 /* these two hinting modes are always available */
674 case FONT_BYTECODE_HINT:
675 /* Only use the bytecode interpreter if support for the _patented_
676 * algorithms is available because the free bytecode
677 * interpreter's results are too crappy.
679 * On freetyp 2.2+, we can ask the library about support for
680 * the patented interpreter. On older versions, we need to use
681 * macros to check for it.
683 #if FREETYPE_MINOR >= 2
684 return FT_Get_TrueType_Engine_Type(evas_ft_lib) >=
685 FT_TRUETYPE_ENGINE_TYPE_PATENTED;
687 /* we may not rely on TT_CONFIG_OPTION_BYTECODE_INTERPRETER
688 * here to find out whether it's supported.
690 * so, assume it is. o_O
695 /* shouldn't get here - need to add another case statement */
700 evas_common_font_memory_hinting_load(const char *source, const char *name, int size, const void *data, int data_size, Font_Hint_Flags hinting, Font_Rend_Flags wanted_rend)
704 fn = evas_common_font_memory_load(source, name, size, data, data_size, wanted_rend);
705 if (fn) evas_common_font_hinting_set(fn, hinting);
710 evas_common_font_hinting_load(const char *name, int size, Font_Hint_Flags hinting, Font_Rend_Flags wanted_rend)
714 fn = evas_common_font_load(name, size, wanted_rend);
715 if (fn) evas_common_font_hinting_set(fn, hinting);
720 evas_common_font_hinting_add(RGBA_Font *fn, const char *name, int size, Font_Hint_Flags hinting, Font_Rend_Flags wanted_rend)
722 fn = evas_common_font_add(fn, name, size, wanted_rend);
723 if (fn) evas_common_font_hinting_set(fn, hinting);
728 evas_common_font_memory_hinting_add(RGBA_Font *fn, const char *source, const char *name, int size, const void *data, int data_size, Font_Hint_Flags hinting, Font_Rend_Flags wanted_rend)
730 fn = evas_common_font_memory_add(fn, source, name, size, data, data_size,
732 if (fn) evas_common_font_hinting_set(fn, hinting);
737 _evas_common_font_int_clear(RGBA_Font_Int *fi)
745 evas_common_font_int_modify_cache_by(fi, -1);
746 if (fi->references <= 1)
750 fi->fash->freeme(fi->fash);
754 if (fi->inuse) fonts_use_usage -= fi->usage;
761 _evas_common_font_all_clear_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__)
763 RGBA_Font_Int *fi = data;
764 _evas_common_font_int_clear(fi);
769 evas_common_font_all_clear(void)
771 eina_hash_foreach(fonts, _evas_common_font_all_clear_cb, NULL);
775 evas_common_font_int_promote(RGBA_Font_Int *fi)
778 if (fonts_use_lru == (Eina_Inlist *)fi) return;
779 if (!fi->inuse) return;
780 fonts_use_lru = eina_inlist_remove(fonts_use_lru, EINA_INLIST_GET(fi));
781 fonts_use_lru = eina_inlist_prepend(fonts_use_lru, EINA_INLIST_GET(fi));
785 evas_common_font_int_use_increase(int size)
787 fonts_use_usage += size;
791 evas_common_font_int_use_trim(void)
796 if (fonts_use_usage <= (font_cache << 1)) return;
797 if (!fonts_use_lru) return;
798 l = fonts_use_lru->last;
801 RGBA_Font_Int *fi = (RGBA_Font_Int *)l;
802 if (fonts_use_usage <= (font_cache << 1)) break;
803 // FIXME: del fi->kerning content
804 _evas_common_font_int_clear(fi);
805 evas_common_font_int_unload(fi);
806 evas_common_font_int_promote(fi);
812 evas_common_font_int_unload(RGBA_Font_Int *fi)
815 if (!fi->src->ft.face) return;
816 _evas_common_font_int_clear(fi);
817 FT_Done_Size(fi->ft.size);
819 evas_common_font_source_unload(fi->src);
823 evas_common_font_int_reload(RGBA_Font_Int *fi)
825 if (fi->src->ft.face) return;
826 evas_common_font_source_load_complete(fi->src);
828 evas_common_font_source_reload(fi->src);
829 evas_common_font_int_load_complete(fi);
832 /* when the fi->references == 0 we increase this instead of really deleting
833 * we then check if the cache_useage size is larger than allowed
834 * !If the cache is NOT too large we dont delete font_int
835 * !If the cache is too large we really delete font_int */
837 evas_common_font_int_modify_cache_by(RGBA_Font_Int *fi, int dir)
839 font_cache_usage += dir * (sizeof(RGBA_Font) + fi->usage +
840 sizeof(FT_FaceRec) + 16384); /* fudge values */
844 evas_common_font_cache_get(void)
850 evas_common_font_cache_set(int size)
853 evas_common_font_flush();
854 evas_common_font_int_use_trim();
858 evas_common_font_flush(void)
860 if (font_cache_usage < font_cache) return;
861 while (font_cache_usage > font_cache)
863 int pfont_cache_usage;
865 pfont_cache_usage = font_cache_usage;
866 evas_common_font_flush_last();
867 if (pfont_cache_usage == font_cache_usage) break;
871 /* We run this when the cache gets larger than allowed size
872 * We check cache size each time a fi->references goes to 0
873 * PERFORMS: Find font_int(s) with references == 0 and delete them */
875 evas_common_font_flush_last(void)
877 RGBA_Font_Int *fi = NULL;
879 if (!fonts_lru) return ;
880 fi = eina_list_data_get(fonts_lru);
881 fonts_lru = eina_list_remove_list(fonts_lru, fonts_lru);
882 eina_hash_del(fonts, fi, fi);
886 evas_common_font_int_find(const char *name, int size,
887 Font_Rend_Flags wanted_rend)
889 RGBA_Font_Int tmp_fi;
890 RGBA_Font_Source tmp_fn;
893 tmp_fn.name = (char*) eina_stringshare_add(name);
894 tmp_fi.src = &tmp_fn;
896 tmp_fi.wanted_rend = wanted_rend;
897 fi = eina_hash_find(fonts, &tmp_fi);
900 if (fi->references == 0)
902 evas_common_font_int_modify_cache_by(fi, -1);
903 fonts_lru = eina_list_remove(fonts_lru, fi);
907 eina_stringshare_del(tmp_fn.name);