2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
5 #include "evas_common.h"
6 #include "evas_private.h"
8 extern FT_Library evas_ft_lib;
10 static int font_cache_usage = 0;
11 static int font_cache = 0;
12 static Evas_Object_List * fonts_src = NULL;
13 static Evas_Object_List * fonts = NULL;
15 static Evas_Bool font_modify_cache_cb(const Evas_Hash *hash, const char *key, void *data, void *fdata);
16 static Evas_Bool font_flush_free_glyph_cb(const Evas_Hash *hash, const char *key, void *data, void *fdata);
18 EAPI RGBA_Font_Source *
19 evas_common_font_source_memory_load(const char *name, const void *data, int data_size)
24 fs = calloc(1, sizeof(RGBA_Font_Source) + data_size);
26 fs->data = ((unsigned char *)fs) + sizeof(RGBA_Font_Source);
27 fs->data_size = data_size;
29 memcpy(fs->data, data, data_size);
30 error = FT_New_Memory_Face(evas_ft_lib, fs->data, fs->data_size, 0, &(fs->ft.face));
36 fs->name = evas_stringshare_add(name);
38 error = FT_Select_Charmap(fs->ft.face, ft_encoding_unicode);
39 fs->ft.orig_upem = fs->ft.face->units_per_EM;
41 fonts_src = evas_object_list_prepend(fonts_src, fs);
45 EAPI RGBA_Font_Source *
46 evas_common_font_source_load(const char *name)
50 fs = calloc(1, sizeof(RGBA_Font_Source));
57 fs->name = evas_stringshare_add(name);
63 fonts_src = evas_object_list_prepend(fonts_src, fs);
68 evas_common_font_source_load_complete(RGBA_Font_Source *fs)
72 error = FT_New_Face(evas_ft_lib, fs->file, 0, &(fs->ft.face));
79 error = FT_Select_Charmap(fs->ft.face, ft_encoding_unicode);
82 FT_Done_Face(fs->ft.face);
87 fs->ft.orig_upem = fs->ft.face->units_per_EM;
91 EAPI RGBA_Font_Source *
92 evas_common_font_source_find(const char *name)
96 if (!name) return NULL;
97 for (l = fonts_src; l; l = l->next)
101 fs = (RGBA_Font_Source *)l;
102 if ((fs->name) && (!strcmp(name, fs->name)))
105 fonts_src = evas_object_list_remove(fonts_src, fs);
106 fonts_src = evas_object_list_prepend(fonts_src, fs);
114 evas_common_font_source_free(RGBA_Font_Source *fs)
117 if (fs->references > 0) return;
119 fonts_src = evas_object_list_remove(fonts_src, fs);
120 FT_Done_Face(fs->ft.face);
121 if (fs->charmap) evas_array_hash_free(fs->charmap);
122 if (fs->name) evas_stringshare_del(fs->name);
127 evas_common_font_size_use(RGBA_Font *fn)
131 for (l = fn->fonts; l; l = l->next)
137 if (fi->src->current_size != fi->size)
139 FT_Activate_Size(fi->ft.size);
140 fi->src->current_size = fi->size;
146 evas_common_font_int_memory_load(const char *name, int size, const void *data, int data_size)
150 fi = evas_common_font_int_find(name, size);
153 fi = calloc(1, sizeof(RGBA_Font_Int));
154 if (!fi) return NULL;
156 fi->src = evas_common_font_source_find(name);
158 fi->src = evas_common_font_source_memory_load(name, data, data_size);
168 fi = evas_common_font_int_load_init(fi);
169 evas_common_font_int_load_complete(fi);
175 evas_common_font_int_load(const char *name, int size)
179 fi = evas_common_font_int_find(name, size);
182 fi = calloc(1, sizeof(RGBA_Font_Int));
183 if (!fi) return NULL;
185 fi->src = evas_common_font_source_find(name);
186 if (!fi->src && evas_file_path_is_file(name))
187 fi->src = evas_common_font_source_load(name);
197 return evas_common_font_int_load_init(fi);
201 evas_common_font_int_load_init(RGBA_Font_Int *fi)
207 fonts = evas_object_list_prepend(fonts, fi);
212 evas_common_font_int_load_complete(RGBA_Font_Int *fi)
216 error = FT_New_Size(fi->src->ft.face, &(fi->ft.size));
219 FT_Activate_Size(fi->ft.size);
221 fi->real_size = fi->size * 64;
222 error = FT_Set_Char_Size(fi->src->ft.face, 0, fi->real_size, 75, 75);
225 fi->real_size = fi->size;
226 error = FT_Set_Pixel_Sizes(fi->src->ft.face, 0, fi->real_size);
232 int chosen_width = 0;
234 for (i = 0; i < fi->src->ft.face->num_fixed_sizes; i++)
239 s = fi->src->ft.face->available_sizes[i].height;
240 cd = chosen_size - fi->size;
241 if (cd < 0) cd = -cd;
246 chosen_width = fi->src->ft.face->available_sizes[i].width;
251 fi->real_size = chosen_size;
252 error = FT_Set_Pixel_Sizes(fi->src->ft.face, chosen_width, fi->real_size);
255 /* couldn't choose the size anyway... what now? */
258 fi->src->current_size = fi->size;
264 evas_common_font_memory_load(const char *name, int size, const void *data, int data_size)
269 fi = evas_common_font_int_memory_load(name, size, data, data_size);
270 if (!fi) return NULL;
271 fn = calloc(1, sizeof(RGBA_Font));
277 fn->fonts = evas_list_append(fn->fonts, fi);
278 fn->hinting = FONT_BYTECODE_HINT;
279 fi->hinting = fn->hinting;
286 evas_common_font_load(const char *name, int size)
291 fi = evas_common_font_int_load(name, size);
292 if (!fi) return NULL;
294 /* First font, complete load */
297 if (!fi->src->ft.face)
299 if (evas_common_font_source_load_complete(fi->src))
302 if (fi->references == 0)
304 evas_common_font_int_modify_cache_by(fi, 1);
305 evas_common_font_flush();
310 evas_common_font_int_load_complete(fi);
313 fn = calloc(1, sizeof(RGBA_Font));
317 if (fi->references == 0)
319 evas_common_font_int_modify_cache_by(fi, 1);
320 evas_common_font_flush();
324 fn->fonts = evas_list_append(fn->fonts, fi);
325 fn->hinting = FONT_BYTECODE_HINT;
326 fi->hinting = fn->hinting;
333 evas_common_font_add(RGBA_Font *fn, const char *name, int size)
339 fi = evas_common_font_int_load(name, size);
342 fn->fonts = evas_list_append(fn->fonts, fi);
343 fi->hinting = fn->hinting;
350 evas_common_font_memory_add(RGBA_Font *fn, const char *name, int size, const void *data, int data_size)
356 fi = evas_common_font_int_memory_load(name, size, data, data_size);
359 fn->fonts = evas_list_append(fn->fonts, fi);
360 fi->hinting = fn->hinting;
367 evas_common_font_free(RGBA_Font *fn)
374 if (fn->references > 0) return;
375 for (l = fn->fonts; l; l = l->next)
381 if (fi->references == 0)
383 evas_common_font_int_modify_cache_by(fi, 1);
384 evas_common_font_flush();
387 evas_list_free(fn->fonts);
393 evas_common_font_hinting_set(RGBA_Font *fn, Font_Hint_Flags hinting)
399 fn->hinting = hinting;
400 for (l = fn->fonts; l; l = l->next)
405 fi->hinting = fn->hinting;
410 evas_common_hinting_available(Font_Hint_Flags hinting)
416 /* these two hinting modes are always available */
418 case FONT_BYTECODE_HINT:
419 /* Only use the bytecode interpreter if support for the _patented_
420 * algorithms is available because the free bytecode
421 * interpreter's results are too crappy.
423 * On freetyp 2.2+, we can ask the library about support for
424 * the patented interpreter. On older versions, we need to use
425 * macros to check for it.
427 #if FREETYPE_MINOR >= 2
428 return FT_Get_TrueType_Engine_Type(evas_ft_lib) >=
429 FT_TRUETYPE_ENGINE_TYPE_PATENTED;
431 /* we may not rely on TT_CONFIG_OPTION_BYTECODE_INTERPRETER
432 * here to find out whether it's supported.
434 * so, assume it is. o_O
440 /* shouldn't get here - need to add another case statement */
445 evas_common_font_memory_hinting_load(const char *name, int size, const void *data, int data_size, Font_Hint_Flags hinting)
449 fn = evas_common_font_memory_load(name, size, data, data_size);
450 if (fn) evas_common_font_hinting_set(fn, hinting);
455 evas_common_font_hinting_load(const char *name, int size, Font_Hint_Flags hinting)
459 fn = evas_common_font_load(name, size);
460 if (fn) evas_common_font_hinting_set(fn, hinting);
465 evas_common_font_hinting_add(RGBA_Font *fn, const char *name, int size, Font_Hint_Flags hinting)
467 fn = evas_common_font_add(fn, name, size);
468 if (fn) evas_common_font_hinting_set(fn, hinting);
473 evas_common_font_memory_hinting_add(RGBA_Font *fn, const char *name, int size, const void *data, int data_size, Font_Hint_Flags hinting)
475 fn = evas_common_font_memory_add(fn, name, size, data, data_size);
476 if (fn) evas_common_font_hinting_set(fn, hinting);
481 font_modify_cache_cb(const Evas_Hash *hash, const char *key, void *data, void *fdata)
488 font_cache_usage += (*dir) *
489 ((fg->glyph_out->bitmap.width * fg->glyph_out->bitmap.rows) +
490 sizeof(RGBA_Font_Glyph) + sizeof(Evas_List) + 400); /* fudge values */
496 /* when the fi->references == 0 we increase this instead of really deleting
497 * we then check if the cache_useage size is larger than allowed
498 * !If the cache is NOT too large we dont delete font_int
499 * !If the cache is too large we really delete font_int */
501 evas_common_font_int_modify_cache_by(RGBA_Font_Int *fi, int dir)
505 if (fi->glyphs) sz_hash = sizeof(Evas_Hash);
506 evas_hash_foreach(fi->glyphs, font_modify_cache_cb, &dir);
507 font_cache_usage += dir * (sizeof(RGBA_Font) + sz_hash +
508 sizeof(FT_FaceRec) + 16384); /* fudge values */
512 evas_common_font_cache_get(void)
518 evas_common_font_cache_set(int size)
521 evas_common_font_flush();
525 evas_common_font_flush(void)
527 if (font_cache_usage < font_cache) return;
528 while (font_cache_usage > font_cache) evas_common_font_flush_last();
532 font_flush_free_glyph_cb(const Evas_Hash *hash, const char *key, void *data, void *fdata)
537 FT_Done_Glyph(fg->glyph);
538 /* extension calls */
539 if (fg->ext_dat_free) fg->ext_dat_free(fg->ext_dat);
547 /* We run this when the cache gets larger than allowed size
548 * We check cache size each time a fi->references goes to 0
549 * PERFORMS: Find font_int(s) with references == 0 and delete them */
551 evas_common_font_flush_last(void)
554 RGBA_Font_Int *fi = NULL;
556 for (l = fonts; l; l = l->next)
558 RGBA_Font_Int *fi_tmp;
560 fi_tmp = (RGBA_Font_Int *)l;
561 if (fi_tmp->references == 0) fi = fi_tmp;
565 FT_Done_Size(fi->ft.size);
567 fonts = evas_object_list_remove(fonts, fi);
568 evas_common_font_int_modify_cache_by(fi, -1);
570 evas_hash_foreach(fi->glyphs, font_flush_free_glyph_cb, NULL);
571 evas_hash_free(fi->glyphs);
573 evas_common_font_source_free(fi->src);
579 evas_common_font_int_find(const char *name, int size)
583 for (l = fonts; l; l = l->next)
587 fi = (RGBA_Font_Int *)l;
588 if ((fi->size == size) && (!strcmp(name, fi->src->name)))
590 if (fi->references == 0) evas_common_font_int_modify_cache_by(fi, -1);
592 fonts = evas_object_list_remove(fonts, fi);
593 fonts = evas_object_list_prepend(fonts, fi);