2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
5 #include "evas_common.h"
6 #include "evas_private.h"
10 #include "evas_font_private.h" /* for Frame-Queuing support */
12 extern FT_Library evas_ft_lib;
14 static int font_cache_usage = 0;
15 static int font_cache = 0;
16 static int font_dpi = 75;
18 static Eina_Hash * fonts_src = NULL;
19 static Eina_Hash * fonts = NULL;
20 static Eina_List * fonts_lru = NULL;
22 //static Eina_Bool font_modify_cache_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata);
23 //static Eina_Bool font_flush_free_glyph_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata);
24 static void _evas_common_font_int_clear(RGBA_Font_Int *fi);
27 _evas_font_cache_int_cmp(const RGBA_Font_Int *k1, int k1_length __UNUSED__,
28 const RGBA_Font_Int *k2, int k2_length __UNUSED__)
30 /* RGBA_Font_Source->name is a stringshare */
31 if (k1->src->name == k2->src->name)
32 return k1->size - k2->size;
33 return strcmp(k1->src->name, k2->src->name);;
37 _evas_font_cache_int_hash(const RGBA_Font_Int *key, int key_length __UNUSED__)
41 hash = eina_hash_djb2(key->src->name, eina_stringshare_strlen(key->src->name) + 1);
42 hash ^= eina_hash_int32(&key->size, sizeof (int));
48 _evas_common_font_source_free(RGBA_Font_Source *fs)
51 FT_Done_Face(fs->ft.face);
53 #if 0 /* FIXME: Disable as it is only used by dead code using deprecated datatype. */
54 // if (fs->charmap) evas_array_hash_free(fs->charmap);
56 if (fs->name) eina_stringshare_del(fs->name);
61 font_flush_free_glyph_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata)
67 FT_Done_Glyph(fg->glyph);
70 if (fg->ext_dat_free) fg->ext_dat_free(fg->ext_dat);
79 _evas_common_font_int_free(RGBA_Font_Int *fi)
81 FT_Done_Size(fi->ft.size);
83 evas_common_font_int_modify_cache_by(fi, -1);
85 _evas_common_font_int_clear(fi);
86 // eina_hash_foreach(fi->glyphs, font_flush_free_glyph_cb, NULL);
87 // eina_hash_free(fi->glyphs);
89 eina_hash_free(fi->kerning);
90 // eina_hash_free(fi->indexes);
93 pthread_mutex_destroy(&fi->ft_mutex);
96 evas_common_font_source_free(fi->src);
98 if (fi->references == 0)
99 fonts_lru = eina_list_remove(fonts_lru, fi);
101 if (fi->fash) fi->fash->freeme(fi->fash);
106 evas_common_font_load_init(void)
108 fonts_src = eina_hash_string_small_new(EINA_FREE_CB(_evas_common_font_source_free));
109 fonts = eina_hash_new(NULL,
110 EINA_KEY_CMP(_evas_font_cache_int_cmp),
111 EINA_KEY_HASH(_evas_font_cache_int_hash),
112 EINA_FREE_CB(_evas_common_font_int_free),
117 evas_common_font_load_shutdown(void)
119 eina_hash_free(fonts);
122 eina_hash_free(fonts_src);
127 evas_common_font_dpi_set(int dpi)
132 EAPI RGBA_Font_Source *
133 evas_common_font_source_memory_load(const char *name, const void *data, int data_size)
136 RGBA_Font_Source *fs;
138 assert(name != NULL);
140 fs = calloc(1, sizeof(RGBA_Font_Source) + data_size);
141 if (!fs) return NULL;
142 fs->data = ((unsigned char *)fs) + sizeof(RGBA_Font_Source);
143 fs->data_size = data_size;
144 fs->current_size = 0;
145 memcpy(fs->data, data, data_size);
147 error = FT_New_Memory_Face(evas_ft_lib, fs->data, fs->data_size, 0, &(fs->ft.face));
154 fs->name = eina_stringshare_add(name);
157 error = FT_Select_Charmap(fs->ft.face, ft_encoding_unicode);
159 fs->ft.orig_upem = fs->ft.face->units_per_EM;
162 eina_hash_direct_add(fonts_src, fs->name, fs);
166 EAPI RGBA_Font_Source *
167 evas_common_font_source_load(const char *name)
169 RGBA_Font_Source *fs;
171 assert(name != NULL);
173 fs = calloc(1, sizeof(RGBA_Font_Source));
174 if (!fs) return NULL;
177 fs->current_size = 0;
180 fs->name = eina_stringshare_add(name);
183 fs->ft.orig_upem = 0;
187 eina_hash_direct_add(fonts_src, fs->name, fs);
192 evas_common_font_source_load_complete(RGBA_Font_Source *fs)
197 error = FT_New_Face(evas_ft_lib, fs->file, 0, &(fs->ft.face));
205 error = FT_Select_Charmap(fs->ft.face, ft_encoding_unicode);
208 FT_Done_Face(fs->ft.face);
215 fs->ft.orig_upem = fs->ft.face->units_per_EM;
219 EAPI RGBA_Font_Source *
220 evas_common_font_source_find(const char *name)
222 RGBA_Font_Source *fs;
224 if (!name) return NULL;
225 fs = eina_hash_find(fonts_src, name);
235 evas_common_font_source_free(RGBA_Font_Source *fs)
238 if (fs->references > 0) return;
240 eina_hash_del(fonts_src, fs->name, fs);
244 evas_common_font_size_use(RGBA_Font *fn)
249 EINA_LIST_FOREACH(fn->fonts, l, fi)
251 if (fi->src->current_size != fi->size)
254 FT_Activate_Size(fi->ft.size);
256 fi->src->current_size = fi->size;
262 _evas_common_font_int_cmp(const int *key1, __UNUSED__ int key1_length,
263 const int *key2, __UNUSED__ int key2_length)
265 return *key1 - *key2;
269 _evas_common_font_double_int_cmp(const int *key1, __UNUSED__ int key1_length,
270 const int *key2, __UNUSED__ int key2_length)
272 if (key1[0] - key2[0] == 0)
273 return key1[1] - key2[1];
274 return key1[0] - key2[0];
278 _evas_common_font_double_int_hash(const unsigned int key[2], int key_length)
282 tmp = eina_hash_int32(&key[0], key_length);
283 tmp ^= eina_hash_int32(&key[1], key_length);
289 _evas_common_font_int_cache_init(RGBA_Font_Int *fi)
291 /* Add some font kerning cache. */
292 // fi->indexes = eina_hash_new(NULL,
293 // EINA_KEY_CMP(_evas_common_font_int_cmp),
294 // EINA_KEY_HASH(eina_hash_int32),
296 fi->kerning = eina_hash_new(NULL,
297 EINA_KEY_CMP(_evas_common_font_double_int_cmp),
298 EINA_KEY_HASH(_evas_common_font_double_int_hash),
301 pthread_mutex_init(&fi->ft_mutex, NULL);
306 evas_common_font_int_memory_load(const char *name, int size, const void *data, int data_size)
310 fi = evas_common_font_int_find(name, size);
313 fi = calloc(1, sizeof(RGBA_Font_Int));
314 if (!fi) return NULL;
316 fi->src = evas_common_font_source_find(name);
318 fi->src = evas_common_font_source_memory_load(name, data, data_size);
328 _evas_common_font_int_cache_init(fi);
330 fi = evas_common_font_int_load_init(fi);
331 evas_common_font_int_load_complete(fi);
337 evas_common_font_int_load(const char *name, int size)
341 fi = evas_common_font_int_find(name, size);
344 fi = calloc(1, sizeof(RGBA_Font_Int));
345 if (!fi) return NULL;
347 fi->src = evas_common_font_source_find(name);
348 if (!fi->src && evas_file_path_is_file(name))
349 fi->src = evas_common_font_source_load(name);
359 _evas_common_font_int_cache_init(fi);
361 return evas_common_font_int_load_init(fi);
365 evas_common_font_int_load_init(RGBA_Font_Int *fi)
368 // fi->glyphs = eina_hash_new(NULL,
369 // EINA_KEY_CMP(_evas_common_font_int_cmp),
370 // EINA_KEY_HASH(eina_hash_int32),
376 eina_hash_direct_add(fonts, fi, fi);
382 evas_common_font_int_load_complete(RGBA_Font_Int *fi)
389 error = FT_New_Size(fi->src->ft.face, &(fi->ft.size));
392 FT_Activate_Size(fi->ft.size);
394 fi->real_size = fi->size * 64;
395 error = FT_Set_Char_Size(fi->src->ft.face, 0, fi->real_size, font_dpi, font_dpi);
398 fi->real_size = fi->size;
399 error = FT_Set_Pixel_Sizes(fi->src->ft.face, 0, fi->real_size);
406 int chosen_width = 0;
408 for (i = 0; i < fi->src->ft.face->num_fixed_sizes; i++)
413 s = fi->src->ft.face->available_sizes[i].height;
414 cd = chosen_size - fi->size;
415 if (cd < 0) cd = -cd;
420 chosen_width = fi->src->ft.face->available_sizes[i].width;
425 fi->real_size = chosen_size;
427 error = FT_Set_Pixel_Sizes(fi->src->ft.face, chosen_width, fi->real_size);
431 /* couldn't choose the size anyway... what now? */
434 fi->src->current_size = 0;
438 val = (int)fi->src->ft.face->bbox.yMax;
439 if (fi->src->ft.face->units_per_EM != 0)
441 dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
442 ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
448 val = -(int)fi->src->ft.face->bbox.yMin;
449 if (fi->src->ft.face->units_per_EM != 0)
451 dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
452 ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
462 evas_common_font_memory_load(const char *name, int size, const void *data, int data_size)
467 fi = evas_common_font_int_memory_load(name, size, data, data_size);
468 if (!fi) return NULL;
469 fn = calloc(1, sizeof(RGBA_Font));
475 fn->fonts = eina_list_append(fn->fonts, fi);
476 fn->hinting = FONT_BYTECODE_HINT;
477 fi->hinting = fn->hinting;
480 #ifdef EVAS_FRAME_QUEUING
483 pthread_cond_init(&(fn->cond_fq_del), NULL);
489 evas_common_font_load(const char *name, int size)
494 fi = evas_common_font_int_load(name, size);
495 if (!fi) return NULL;
497 /* First font, complete load */
500 if (!fi->src->ft.face)
502 if (evas_common_font_source_load_complete(fi->src))
505 if (fi->references == 0)
507 fonts_lru = eina_list_prepend(fonts_lru, fi);
508 evas_common_font_int_modify_cache_by(fi, 1);
509 evas_common_font_flush();
514 evas_common_font_int_load_complete(fi);
517 fn = calloc(1, sizeof(RGBA_Font));
521 if (fi->references == 0)
523 fonts_lru = eina_list_prepend(fonts_lru, fi);
524 evas_common_font_int_modify_cache_by(fi, 1);
525 evas_common_font_flush();
529 fn->fonts = eina_list_append(fn->fonts, fi);
530 fn->hinting = FONT_BYTECODE_HINT;
531 fi->hinting = fn->hinting;
534 #ifdef EVAS_FRAME_QUEUING
537 pthread_cond_init(&(fn->cond_fq_del), NULL);
543 evas_common_font_add(RGBA_Font *fn, const char *name, int size)
549 fi = evas_common_font_int_load(name, size);
552 fn->fonts = eina_list_append(fn->fonts, fi);
553 fi->hinting = fn->hinting;
560 evas_common_font_memory_add(RGBA_Font *fn, const char *name, int size, const void *data, int data_size)
566 fi = evas_common_font_int_memory_load(name, size, data, data_size);
569 fn->fonts = eina_list_append(fn->fonts, fi);
570 fi->hinting = fn->hinting;
577 evas_common_font_free(RGBA_Font *fn)
584 if (fn->references > 0) return;
585 #ifdef EVAS_FRAME_QUEUING
588 if (fn->ref_fq[0] != fn->ref_fq[1])
598 EINA_LIST_FOREACH(fn->fonts, l, fi)
601 if (fi->references == 0)
603 fonts_lru = eina_list_append(fonts_lru, fi);
604 evas_common_font_int_modify_cache_by(fi, 1);
607 evas_common_font_flush();
608 eina_list_free(fn->fonts);
609 if (fn->fash) fn->fash->freeme(fn->fash);
611 #ifdef EVAS_FRAME_QUEUING
614 pthread_cond_destroy(&(fn->cond_fq_del));
621 evas_common_font_hinting_set(RGBA_Font *fn, Font_Hint_Flags hinting)
628 fn->hinting = hinting;
629 EINA_LIST_FOREACH(fn->fonts, l, fi)
630 fi->hinting = fn->hinting;
634 evas_common_hinting_available(Font_Hint_Flags hinting)
640 /* these two hinting modes are always available */
642 case FONT_BYTECODE_HINT:
643 /* Only use the bytecode interpreter if support for the _patented_
644 * algorithms is available because the free bytecode
645 * interpreter's results are too crappy.
647 * On freetyp 2.2+, we can ask the library about support for
648 * the patented interpreter. On older versions, we need to use
649 * macros to check for it.
651 #if FREETYPE_MINOR >= 2
652 return FT_Get_TrueType_Engine_Type(evas_ft_lib) >=
653 FT_TRUETYPE_ENGINE_TYPE_PATENTED;
655 /* we may not rely on TT_CONFIG_OPTION_BYTECODE_INTERPRETER
656 * here to find out whether it's supported.
658 * so, assume it is. o_O
664 /* shouldn't get here - need to add another case statement */
669 evas_common_font_memory_hinting_load(const char *name, int size, const void *data, int data_size, Font_Hint_Flags hinting)
673 fn = evas_common_font_memory_load(name, size, data, data_size);
674 if (fn) evas_common_font_hinting_set(fn, hinting);
679 evas_common_font_hinting_load(const char *name, int size, Font_Hint_Flags hinting)
683 fn = evas_common_font_load(name, size);
684 if (fn) evas_common_font_hinting_set(fn, hinting);
689 evas_common_font_hinting_add(RGBA_Font *fn, const char *name, int size, Font_Hint_Flags hinting)
691 fn = evas_common_font_add(fn, name, size);
692 if (fn) evas_common_font_hinting_set(fn, hinting);
697 evas_common_font_memory_hinting_add(RGBA_Font *fn, const char *name, int size, const void *data, int data_size, Font_Hint_Flags hinting)
699 fn = evas_common_font_memory_add(fn, name, size, data, data_size);
700 if (fn) evas_common_font_hinting_set(fn, hinting);
705 _evas_common_font_int_clear(RGBA_Font_Int *fi)
716 evas_common_font_int_modify_cache_by(fi, -1);
718 for (j = 0; j <= 0xff; j++) // fixme: to do > 65k
720 Fash_Glyph_Map *fmap = fi->fash->bucket[j];
723 for (i = 0; i <= 0xff; i++)
725 RGBA_Font_Glyph *fg = fmap->item[i];
726 if ((fg) && (fg != (void *)(-1)))
728 FT_Done_Glyph(fg->glyph);
729 /* extension calls */
730 if (fg->ext_dat_free) fg->ext_dat_free(fg->ext_dat);
732 fmap->item[i] = NULL;
737 fi->fash->freeme(fi->fash);
743 _evas_common_font_all_clear_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata)
745 RGBA_Font_Int *fi = data;
746 _evas_common_font_int_clear(fi);
751 evas_common_font_all_clear(void)
753 eina_hash_foreach(fonts, _evas_common_font_all_clear_cb, NULL);
758 font_modify_cache_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata)
765 font_cache_usage += (*dir) *
766 ((fg->glyph_out->bitmap.width * fg->glyph_out->bitmap.rows) +
767 sizeof(RGBA_Font_Glyph) + sizeof(Eina_List) + 400); // fudge values
773 /* when the fi->references == 0 we increase this instead of really deleting
774 * we then check if the cache_useage size is larger than allowed
775 * !If the cache is NOT too large we dont delete font_int
776 * !If the cache is too large we really delete font_int */
778 evas_common_font_int_modify_cache_by(RGBA_Font_Int *fi, int dir)
785 for (j = 0; j <= 0xff; j++) // fixme: to do > 65k
787 Fash_Glyph_Map *fmap = fi->fash->bucket[j];
790 for (i = 0; i <= 0xff; i++)
792 RGBA_Font_Glyph *fg = fmap->item[i];
793 if ((fg) && (fg != (void *)(-1)))
795 sizeof(RGBA_Font_Glyph) + sizeof(Eina_List) +
796 (fg->glyph_out->bitmap.width *
797 fg->glyph_out->bitmap.rows) +
803 // if (fi->glyphs) sz_hash = eina_hash_population(fi->glyphs);
804 // eina_hash_foreach(fi->glyphs, font_modify_cache_cb, &dir);
805 font_cache_usage += dir * (sizeof(RGBA_Font) + sz_hash +
806 sizeof(FT_FaceRec) + 16384); /* fudge values */
810 evas_common_font_cache_get(void)
816 evas_common_font_cache_set(int size)
819 evas_common_font_flush();
823 evas_common_font_flush(void)
825 if (font_cache_usage < font_cache) return;
826 while (font_cache_usage > font_cache)
828 int pfont_cache_usage;
830 pfont_cache_usage = font_cache_usage;
831 evas_common_font_flush_last();
832 if (pfont_cache_usage == font_cache_usage) break;
836 /* We run this when the cache gets larger than allowed size
837 * We check cache size each time a fi->references goes to 0
838 * PERFORMS: Find font_int(s) with references == 0 and delete them */
840 evas_common_font_flush_last(void)
842 RGBA_Font_Int *fi = NULL;
844 if (!fonts_lru) return ;
846 fi = eina_list_data_get(fonts_lru);
847 fonts_lru = eina_list_remove_list(fonts_lru, fonts_lru);
849 eina_hash_del(fonts, fi, fi);
853 evas_common_font_int_find(const char *name, int size)
855 RGBA_Font_Int tmp_fi;
856 RGBA_Font_Source tmp_fn;
859 tmp_fn.name = (char*) eina_stringshare_add(name);
860 tmp_fi.src = &tmp_fn;
863 fi = eina_hash_find(fonts, &tmp_fi);
866 if (fi->references == 0)
868 evas_common_font_int_modify_cache_by(fi, -1);
869 fonts_lru = eina_list_remove(fonts_lru, fi);
874 eina_stringshare_del(tmp_fn.name);