aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/lib/engines/common/evas_font_load.c
diff options
context:
space:
mode:
authorDavid Walter Seikel2013-01-13 17:29:19 +1000
committerDavid Walter Seikel2013-01-13 17:29:19 +1000
commit07274513e984f0b5544586c74508ccd16e7dcafa (patch)
treeb32ff2a9136fbc1a4a6a0ed1e4d79cde0f5f16d9 /libraries/evas/src/lib/engines/common/evas_font_load.c
parentAdded Irrlicht 1.8, but without all the Windows binaries. (diff)
downloadSledjHamr-07274513e984f0b5544586c74508ccd16e7dcafa.zip
SledjHamr-07274513e984f0b5544586c74508ccd16e7dcafa.tar.gz
SledjHamr-07274513e984f0b5544586c74508ccd16e7dcafa.tar.bz2
SledjHamr-07274513e984f0b5544586c74508ccd16e7dcafa.tar.xz
Remove EFL, since it's been released now.
Diffstat (limited to 'libraries/evas/src/lib/engines/common/evas_font_load.c')
-rw-r--r--libraries/evas/src/lib/engines/common/evas_font_load.c925
1 files changed, 0 insertions, 925 deletions
diff --git a/libraries/evas/src/lib/engines/common/evas_font_load.c b/libraries/evas/src/lib/engines/common/evas_font_load.c
deleted file mode 100644
index abba9e3..0000000
--- a/libraries/evas/src/lib/engines/common/evas_font_load.c
+++ /dev/null
@@ -1,925 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3
4#include <assert.h>
5
6#include "evas_font_private.h" /* for Frame-Queuing support */
7#include "evas_font_ot.h"
8
9#ifdef USE_HARFBUZZ
10# include <hb.h>
11# include <hb-ft.h>
12#endif
13
14extern FT_Library evas_ft_lib;
15
16static int font_cache_usage = 0;
17static int font_cache = 0;
18static int font_dpi = 75;
19
20static Eina_Hash *fonts_src = NULL;
21static Eina_Hash *fonts = NULL;
22static Eina_List *fonts_lru = NULL;
23static Eina_Inlist *fonts_use_lru = NULL;
24static int fonts_use_usage = 0;
25
26static void _evas_common_font_int_clear(RGBA_Font_Int *fi);
27
28static int
29_evas_font_cache_int_cmp(const RGBA_Font_Int *k1, int k1_length __UNUSED__,
30 const RGBA_Font_Int *k2, int k2_length __UNUSED__)
31{
32 /* RGBA_Font_Source->name is a stringshare */
33 if (k1->src->name == k2->src->name)
34 {
35 if (k1->size == k2->size)
36 return k1->wanted_rend - k2->wanted_rend;
37 else
38 return k1->size - k2->size;
39 }
40 return strcmp(k1->src->name, k2->src->name);
41}
42
43static int
44_evas_font_cache_int_hash(const RGBA_Font_Int *key, int key_length __UNUSED__)
45{
46 int hash;
47 unsigned int wanted_rend = key->wanted_rend;
48 hash = eina_hash_djb2(key->src->name, eina_stringshare_strlen(key->src->name) + 1);
49 hash ^= eina_hash_int32(&key->size, sizeof (int));
50 hash ^= eina_hash_int32(&wanted_rend, sizeof (int));
51 return hash;
52}
53
54static void
55_evas_common_font_source_free(RGBA_Font_Source *fs)
56{
57 FTLOCK();
58 FT_Done_Face(fs->ft.face);
59 FTUNLOCK();
60 if (fs->name) eina_stringshare_del(fs->name);
61 if (fs->file) eina_stringshare_del(fs->file);
62 free(fs);
63}
64
65static void
66_evas_common_font_int_free(RGBA_Font_Int *fi)
67{
68 FT_Done_Size(fi->ft.size);
69
70 evas_common_font_int_modify_cache_by(fi, -1);
71 _evas_common_font_int_clear(fi);
72 eina_hash_free(fi->kerning);
73
74 LKD(fi->ft_mutex);
75#ifdef USE_HARFBUZZ
76 hb_font_destroy(fi->ft.hb_font);
77#endif
78 evas_common_font_source_free(fi->src);
79 if (fi->references == 0) fonts_lru = eina_list_remove(fonts_lru, fi);
80 if (fi->fash) fi->fash->freeme(fi->fash);
81 if (fi->inuse)
82 {
83 fonts_use_lru = eina_inlist_remove(fonts_use_lru, EINA_INLIST_GET(fi));
84 fi->inuse = 0;
85 fonts_use_usage -= fi->usage;
86 fi->usage = 0;
87 }
88 free(fi);
89}
90
91void
92evas_common_font_load_init(void)
93{
94 fonts_src = eina_hash_string_small_new(EINA_FREE_CB(_evas_common_font_source_free));
95 fonts = eina_hash_new(NULL,
96 EINA_KEY_CMP(_evas_font_cache_int_cmp),
97 EINA_KEY_HASH(_evas_font_cache_int_hash),
98 EINA_FREE_CB(_evas_common_font_int_free),
99 5);
100}
101
102void
103evas_common_font_load_shutdown(void)
104{
105 eina_hash_free(fonts);
106 fonts = NULL;
107 eina_hash_free(fonts_src);
108 fonts_src = NULL;
109}
110
111EAPI void
112evas_common_font_dpi_set(int dpi)
113{
114 font_dpi = dpi;
115}
116
117EAPI RGBA_Font_Source *
118evas_common_font_source_memory_load(const char *name, const void *data, int data_size)
119{
120 int error;
121 RGBA_Font_Source *fs;
122
123 assert(name != NULL);
124 fs = calloc(1, sizeof(RGBA_Font_Source) + data_size);
125 if (!fs) return NULL;
126 fs->data = ((unsigned char *)fs) + sizeof(RGBA_Font_Source);
127 fs->data_size = data_size;
128 fs->current_size = 0;
129 memcpy(fs->data, data, data_size);
130 FTLOCK();
131 error = FT_New_Memory_Face(evas_ft_lib, fs->data, fs->data_size, 0, &(fs->ft.face));
132 FTUNLOCK();
133 if (error)
134 {
135 free(fs);
136 return NULL;
137 }
138 fs->name = eina_stringshare_add(name);
139 fs->file = NULL;
140 FTLOCK();
141 error = FT_Select_Charmap(fs->ft.face, ft_encoding_unicode);
142 if (error)
143 {
144 FT_Done_Face(fs->ft.face);
145 fs->ft.face = NULL;
146 free(fs);
147 return NULL;
148 }
149 FTUNLOCK();
150 fs->ft.orig_upem = fs->ft.face->units_per_EM;
151 fs->references = 1;
152 eina_hash_direct_add(fonts_src, fs->name, fs);
153 return fs;
154}
155
156EAPI RGBA_Font_Source *
157evas_common_font_source_load(const char *name)
158{
159 RGBA_Font_Source *fs;
160
161 assert(name != NULL);
162 fs = calloc(1, sizeof(RGBA_Font_Source));
163 if (!fs) return NULL;
164 fs->data = NULL;
165 fs->data_size = 0;
166 fs->current_size = 0;
167 fs->ft.face = NULL;
168 fs->name = eina_stringshare_add(name);
169 fs->file = eina_stringshare_ref(fs->name);
170 fs->ft.orig_upem = 0;
171 fs->references = 1;
172 eina_hash_direct_add(fonts_src, fs->name, fs);
173 return fs;
174}
175
176void
177evas_common_font_source_unload(RGBA_Font_Source *fs)
178{
179 FTLOCK();
180 FT_Done_Face(fs->ft.face);
181 fs->ft.face = NULL;
182 FTUNLOCK();
183}
184
185void
186evas_common_font_source_reload(RGBA_Font_Source *fs)
187{
188 if (fs->ft.face) return;
189 if (fs->data)
190 {
191 int error;
192
193 FTLOCK();
194 error = FT_New_Memory_Face(evas_ft_lib, fs->data, fs->data_size, 0, &(fs->ft.face));
195 FTUNLOCK();
196 if (error) return;
197 FTLOCK();
198 error = FT_Select_Charmap(fs->ft.face, ft_encoding_unicode);
199 if (error)
200 {
201 FT_Done_Face(fs->ft.face);
202 fs->ft.face = NULL;
203 }
204 FTUNLOCK();
205 }
206 else
207 evas_common_font_source_load_complete(fs);
208}
209
210EAPI int
211evas_common_font_source_load_complete(RGBA_Font_Source *fs)
212{
213 int error;
214
215 FTLOCK();
216 error = FT_New_Face(evas_ft_lib, fs->file, 0, &(fs->ft.face));
217 if (error)
218 {
219 FTUNLOCK();
220 fs->ft.face = NULL;
221 return error;
222 }
223 error = FT_Select_Charmap(fs->ft.face, ft_encoding_unicode);
224 if (error)
225 {
226 FT_Done_Face(fs->ft.face);
227 FTUNLOCK();
228 fs->ft.face = NULL;
229 return error;
230 }
231 FTUNLOCK();
232 fs->ft.orig_upem = fs->ft.face->units_per_EM;
233 return error;
234}
235
236EAPI RGBA_Font_Source *
237evas_common_font_source_find(const char *name)
238{
239 RGBA_Font_Source *fs;
240
241 if (!name) return NULL;
242 fs = eina_hash_find(fonts_src, name);
243 if (fs)
244 {
245 fs->references++;
246 return fs;
247 }
248 return NULL;
249}
250
251EAPI void
252evas_common_font_source_free(RGBA_Font_Source *fs)
253{
254 fs->references--;
255 if (fs->references > 0) return;
256 eina_hash_del(fonts_src, fs->name, fs);
257}
258
259EAPI void
260evas_common_font_size_use(RGBA_Font *fn)
261{
262 RGBA_Font_Int *fi;
263 Eina_List *l;
264
265 EINA_LIST_FOREACH(fn->fonts, l, fi)
266 {
267 if (fi->src->current_size != fi->size)
268 {
269 evas_common_font_source_reload(fi->src);
270 FTLOCK();
271 FT_Activate_Size(fi->ft.size);
272 FTUNLOCK();
273 fi->src->current_size = fi->size;
274 }
275 }
276}
277
278static int
279_evas_common_font_double_int_cmp(const int *key1, __UNUSED__ int key1_length,
280 const int *key2, __UNUSED__ int key2_length)
281{
282 if (key1[0] - key2[0] == 0) return key1[1] - key2[1];
283 return key1[0] - key2[0];
284}
285
286static int
287_evas_common_font_double_int_hash(const unsigned int key[2], int key_length)
288{
289 return
290 eina_hash_int32(&key[0], key_length) ^
291 eina_hash_int32(&key[1], key_length);
292}
293
294static void
295_evas_common_font_int_cache_init(RGBA_Font_Int *fi)
296{
297 /* Add some font kerning cache. */
298 fi->kerning = eina_hash_new(NULL,
299 EINA_KEY_CMP(_evas_common_font_double_int_cmp),
300 EINA_KEY_HASH(_evas_common_font_double_int_hash),
301 free, 3);
302 LKI(fi->ft_mutex);
303}
304
305EAPI RGBA_Font_Int *
306evas_common_font_int_memory_load(const char *name, int size, const void *data, int data_size, Font_Rend_Flags wanted_rend)
307{
308 RGBA_Font_Int *fi;
309
310 fi = evas_common_font_int_find(name, size, wanted_rend);
311 if (fi) return fi;
312 fi = calloc(1, sizeof(RGBA_Font_Int));
313 if (!fi) return NULL;
314 fi->src = evas_common_font_source_find(name);
315 if (!fi->src)
316 fi->src = evas_common_font_source_memory_load(name, data, data_size);
317 if (!fi->src)
318 {
319 free(fi);
320 return NULL;
321 }
322 fi->size = size;
323 _evas_common_font_int_cache_init(fi);
324 fi = evas_common_font_int_load_init(fi);
325 evas_common_font_int_load_complete(fi);
326 return fi;
327}
328
329EAPI RGBA_Font_Int *
330evas_common_font_int_load(const char *name, int size,
331 Font_Rend_Flags wanted_rend)
332{
333 RGBA_Font_Int *fi;
334
335 fi = evas_common_font_int_find(name, size, wanted_rend);
336 if (fi) return fi;
337 fi = calloc(1, sizeof(RGBA_Font_Int));
338 if (!fi) return NULL;
339 fi->src = evas_common_font_source_find(name);
340 if (!fi->src && evas_file_path_is_file(name))
341 fi->src = evas_common_font_source_load(name);
342
343 if (!fi->src)
344 {
345 free(fi);
346 return NULL;
347 }
348 fi->size = size;
349 fi->wanted_rend = wanted_rend;
350 _evas_common_font_int_cache_init(fi);
351 fi = evas_common_font_int_load_init(fi);
352// evas_common_font_int_load_complete(fi);
353 return fi;
354}
355
356EAPI RGBA_Font_Int *
357evas_common_font_int_load_init(RGBA_Font_Int *fi)
358{
359 fi->ft.size = NULL;
360 fi->references = 1;
361 eina_hash_direct_add(fonts, fi, fi);
362 return fi;
363}
364
365EAPI RGBA_Font_Int *
366evas_common_font_int_load_complete(RGBA_Font_Int *fi)
367{
368 int val, dv;
369 int ret;
370 int error;
371
372 FTLOCK();
373 error = FT_New_Size(fi->src->ft.face, &(fi->ft.size));
374 if (!error)
375 {
376 FT_Activate_Size(fi->ft.size);
377 }
378 fi->real_size = fi->size * 64;
379 error = FT_Set_Char_Size(fi->src->ft.face, 0, fi->real_size, font_dpi, font_dpi);
380 if (error)
381 {
382 fi->real_size = fi->size;
383 error = FT_Set_Pixel_Sizes(fi->src->ft.face, 0, fi->real_size);
384 }
385 FTUNLOCK();
386 if (error)
387 {
388 int i;
389 int chosen_size = 0;
390 int chosen_width = 0;
391
392 for (i = 0; i < fi->src->ft.face->num_fixed_sizes; i++)
393 {
394 int s;
395 int d, cd;
396
397 s = fi->src->ft.face->available_sizes[i].height;
398 cd = chosen_size - fi->size;
399 if (cd < 0) cd = -cd;
400 d = s - fi->size;
401 if (d < 0) d = -d;
402 if (d < cd)
403 {
404 chosen_width = fi->src->ft.face->available_sizes[i].width;
405 chosen_size = s;
406 }
407 if (d == 0) break;
408 }
409 fi->real_size = chosen_size;
410 FTLOCK();
411 error = FT_Set_Pixel_Sizes(fi->src->ft.face, chosen_width, fi->real_size);
412 FTUNLOCK();
413 if (error)
414 {
415 /* couldn't choose the size anyway... what now? */
416 }
417 }
418 fi->src->current_size = 0;
419 fi->max_h = 0;
420 val = (int)fi->src->ft.face->bbox.yMax;
421 if (fi->src->ft.face->units_per_EM != 0)
422 {
423 dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
424 ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
425 }
426 else ret = val;
427 fi->max_h += ret;
428 val = -(int)fi->src->ft.face->bbox.yMin;
429 if (fi->src->ft.face->units_per_EM != 0)
430 {
431 dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
432 ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
433 }
434 else ret = val;
435 fi->max_h += ret;
436
437 /* If the loaded font doesn't match with wanted_rend value requested by
438 * textobject and textblock, Set the runtime_rend value as FONT_REND_SLANT
439 * or FONT_REND_WEIGHT for software rendering. */
440 fi->runtime_rend = FONT_REND_REGULAR;
441 if ((fi->wanted_rend & FONT_REND_SLANT) &&
442 !(fi->src->ft.face->style_flags & FT_STYLE_FLAG_ITALIC))
443 fi->runtime_rend |= FONT_REND_SLANT;
444
445 if ((fi->wanted_rend & FONT_REND_WEIGHT) &&
446 !(fi->src->ft.face->style_flags & FT_STYLE_FLAG_BOLD))
447 fi->runtime_rend |= FONT_REND_WEIGHT;
448
449 return fi;
450}
451
452EAPI RGBA_Font *
453evas_common_font_memory_load(const char *name, int size, const void *data, int data_size, Font_Rend_Flags wanted_rend)
454{
455 RGBA_Font *fn;
456 RGBA_Font_Int *fi;
457
458 fi = evas_common_font_int_memory_load(name, size, data, data_size,
459 wanted_rend);
460 if (!fi) return NULL;
461 fn = calloc(1, sizeof(RGBA_Font));
462 if (!fn)
463 {
464 fi->references--;
465 if (fi->references == 0)
466 {
467 fonts_lru = eina_list_prepend(fonts_lru, fi);
468 evas_common_font_int_modify_cache_by(fi, 1);
469 evas_common_font_flush();
470 }
471 return NULL;
472 }
473 fn->fonts = eina_list_append(fn->fonts, fi);
474 fn->hinting = FONT_BYTECODE_HINT;
475 fi->hinting = fn->hinting;
476 fn->references = 1;
477 LKI(fn->lock);
478#ifdef EVAS_FRAME_QUEUING
479 LKI(fn->ref_fq_add);
480 LKI(fn->ref_fq_del);
481 eina_condition_new(&(fn->cond_fq_del), &(fn->ref_fq_del));
482#endif
483 if (fi->inuse) evas_common_font_int_promote(fi);
484 else
485 {
486 fi->inuse = 1;
487 fonts_use_lru = eina_inlist_prepend(fonts_use_lru, EINA_INLIST_GET(fi));
488 }
489 return fn;
490}
491
492
493//ZZZ: font struct looks like:
494// fn->(fi, fi, fi, ...)
495// fi->fs
496
497EAPI RGBA_Font *
498evas_common_font_load(const char *name, int size, Font_Rend_Flags wanted_rend)
499{
500 RGBA_Font *fn;
501 RGBA_Font_Int *fi;
502
503 fi = evas_common_font_int_load(name, size, wanted_rend);
504 if (!fi) return NULL;
505 /* First font, complete load */
506 if (!fi->ft.size)
507 {
508 if (!fi->src->ft.face)
509 {
510 if (evas_common_font_source_load_complete(fi->src))
511 {
512 fi->references--;
513 if (fi->references == 0)
514 {
515 fonts_lru = eina_list_prepend(fonts_lru, fi);
516 evas_common_font_int_modify_cache_by(fi, 1);
517 evas_common_font_flush();
518 }
519 return NULL;
520 }
521 }
522 evas_common_font_int_load_complete(fi);
523 }
524 fn = calloc(1, sizeof(RGBA_Font));
525 if (!fn)
526 {
527 fi->references--;
528 if (fi->references == 0)
529 {
530 fonts_lru = eina_list_prepend(fonts_lru, fi);
531 evas_common_font_int_modify_cache_by(fi, 1);
532 evas_common_font_flush();
533 }
534 return NULL;
535 }
536
537 fn->fonts = eina_list_append(fn->fonts, fi);
538 fn->hinting = FONT_BYTECODE_HINT;
539 fi->hinting = fn->hinting;
540 fn->references = 1;
541 LKI(fn->lock);
542#ifdef EVAS_FRAME_QUEUING
543 LKI(fn->ref_fq_add);
544 LKI(fn->ref_fq_del);
545 eina_condition_new(&(fn->cond_fq_del), &(fn->ref_fq_del));
546#endif
547 if (fi->inuse) evas_common_font_int_promote(fi);
548 else
549 {
550 fi->inuse = 1;
551 fonts_use_lru = eina_inlist_prepend(fonts_use_lru, EINA_INLIST_GET(fi));
552 }
553 return fn;
554}
555
556EAPI RGBA_Font *
557evas_common_font_add(RGBA_Font *fn, const char *name, int size, Font_Rend_Flags wanted_rend)
558{
559 RGBA_Font_Int *fi;
560
561 if (!fn) return NULL;
562 fi = evas_common_font_int_load(name, size, wanted_rend);
563 if (fi)
564 {
565 fn->fonts = eina_list_append(fn->fonts, fi);
566 fi->hinting = fn->hinting;
567 if (fi->inuse) evas_common_font_int_promote(fi);
568 else
569 {
570 fi->inuse = 1;
571 fonts_use_lru = eina_inlist_prepend(fonts_use_lru, EINA_INLIST_GET(fi));
572 }
573 return fn;
574 }
575 return NULL;
576}
577
578EAPI RGBA_Font *
579evas_common_font_memory_add(RGBA_Font *fn, const char *name, int size, const void *data, int data_size, Font_Rend_Flags wanted_rend)
580{
581 RGBA_Font_Int *fi;
582
583 if (!fn)
584 return NULL;
585 fi = evas_common_font_int_memory_load(name, size, data, data_size, wanted_rend);
586 if (fi)
587 {
588 fn->fonts = eina_list_append(fn->fonts, fi);
589 fi->hinting = fn->hinting;
590 if (fi->inuse) evas_common_font_int_promote(fi);
591 else
592 {
593 fi->inuse = 1;
594 fonts_use_lru = eina_inlist_prepend(fonts_use_lru, EINA_INLIST_GET(fi));
595 }
596 return fn;
597 }
598 return NULL;
599}
600
601EAPI void
602evas_common_font_free(RGBA_Font *fn)
603{
604 Eina_List *l;
605 RGBA_Font_Int *fi;
606
607 if (!fn) return;
608 fn->references--;
609 if (fn->references > 0) return;
610#ifdef EVAS_FRAME_QUEUING
611 LKL(fn->ref_fq_add);
612 LKL(fn->ref_fq_del);
613 if (fn->ref_fq[0] != fn->ref_fq[1])
614 {
615 LKU(fn->ref_fq_add);
616 LKU(fn->ref_fq_del);
617 return;
618 }
619 LKU(fn->ref_fq_add);
620 LKU(fn->ref_fq_del);
621#endif
622 EINA_LIST_FOREACH(fn->fonts, l, fi)
623 {
624 fi->references--;
625 if (fi->references == 0)
626 {
627 fonts_lru = eina_list_append(fonts_lru, fi);
628 evas_common_font_int_modify_cache_by(fi, 1);
629 }
630 }
631 evas_common_font_flush();
632 eina_list_free(fn->fonts);
633 if (fn->fash) fn->fash->freeme(fn->fash);
634 LKD(fn->lock);
635#ifdef EVAS_FRAME_QUEUING
636 LKD(fn->ref_fq_add);
637 LKD(fn->ref_fq_del);
638 eina_condition_free(&(fn->cond_fq_del));
639#endif
640 free(fn);
641}
642
643EAPI void
644evas_common_font_hinting_set(RGBA_Font *fn, Font_Hint_Flags hinting)
645{
646 Eina_List *l;
647 RGBA_Font_Int *fi;
648
649 if (!fn) return;
650 fn->hinting = hinting;
651 EINA_LIST_FOREACH(fn->fonts, l, fi)
652 {
653 fi->hinting = fn->hinting;
654 }
655}
656
657EAPI Eina_Bool
658evas_common_hinting_available(Font_Hint_Flags hinting)
659{
660 switch (hinting)
661 {
662 case FONT_NO_HINT:
663 case FONT_AUTO_HINT:
664 /* these two hinting modes are always available */
665 return EINA_TRUE;
666 case FONT_BYTECODE_HINT:
667 /* Only use the bytecode interpreter if support for the _patented_
668 * algorithms is available because the free bytecode
669 * interpreter's results are too crappy.
670 *
671 * On freetyp 2.2+, we can ask the library about support for
672 * the patented interpreter. On older versions, we need to use
673 * macros to check for it.
674 */
675#if FREETYPE_MINOR >= 2
676 return FT_Get_TrueType_Engine_Type(evas_ft_lib) >=
677 FT_TRUETYPE_ENGINE_TYPE_PATENTED;
678#else
679 /* we may not rely on TT_CONFIG_OPTION_BYTECODE_INTERPRETER
680 * here to find out whether it's supported.
681 *
682 * so, assume it is. o_O
683 */
684 return EINA_TRUE;
685#endif
686 }
687 /* shouldn't get here - need to add another case statement */
688 return EINA_FALSE;
689}
690
691EAPI RGBA_Font *
692evas_common_font_memory_hinting_load(const char *name, int size, const void *data, int data_size, Font_Hint_Flags hinting, Font_Rend_Flags wanted_rend)
693{
694 RGBA_Font *fn;
695
696 fn = evas_common_font_memory_load(name, size, data, data_size, wanted_rend);
697 if (fn) evas_common_font_hinting_set(fn, hinting);
698 return fn;
699}
700
701EAPI RGBA_Font *
702evas_common_font_hinting_load(const char *name, int size, Font_Hint_Flags hinting, Font_Rend_Flags wanted_rend)
703{
704 RGBA_Font *fn;
705
706 fn = evas_common_font_load(name, size, wanted_rend);
707 if (fn) evas_common_font_hinting_set(fn, hinting);
708 return fn;
709}
710
711EAPI RGBA_Font *
712evas_common_font_hinting_add(RGBA_Font *fn, const char *name, int size, Font_Hint_Flags hinting, Font_Rend_Flags wanted_rend)
713{
714 fn = evas_common_font_add(fn, name, size, wanted_rend);
715 if (fn) evas_common_font_hinting_set(fn, hinting);
716 return fn;
717}
718
719EAPI RGBA_Font *
720evas_common_font_memory_hinting_add(RGBA_Font *fn, const char *name, int size, const void *data, int data_size, Font_Hint_Flags hinting, Font_Rend_Flags wanted_rend)
721{
722 fn = evas_common_font_memory_add(fn, name, size, data, data_size,
723 wanted_rend);
724 if (fn) evas_common_font_hinting_set(fn, hinting);
725 return fn;
726}
727
728static void
729_evas_common_font_int_clear(RGBA_Font_Int *fi)
730{
731 int i, j, k;
732
733 LKL(fi->ft_mutex);
734 if (!fi->fash)
735 {
736 LKU(fi->ft_mutex);
737 return;
738 }
739 evas_common_font_int_modify_cache_by(fi, -1);
740 if (fi->fash)
741 {
742 for (k = 0; k <= 0xff; k++) // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
743 {
744 Fash_Glyph_Map2 *fmap2 = fi->fash->bucket[k];
745 if (fmap2)
746 {
747 for (j = 0; j <= 0xff; j++) // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
748 {
749 Fash_Glyph_Map *fmap = fmap2->bucket[j];
750 if (fmap)
751 {
752 for (i = 0; i <= 0xff; i++)
753 {
754 RGBA_Font_Glyph *fg = fmap->item[i];
755 if ((fg) && (fg != (void *)(-1)))
756 {
757 FT_Done_Glyph(fg->glyph);
758 /* extension calls */
759 if (fg->ext_dat_free) fg->ext_dat_free(fg->ext_dat);
760 free(fg);
761 fmap->item[i] = NULL;
762 }
763 }
764 }
765 }
766 }
767 }
768 fi->fash->freeme(fi->fash);
769 fi->fash = NULL;
770 }
771 if (fi->inuse) fonts_use_usage -= fi->usage;
772 fi->usage = 0;
773 LKU(fi->ft_mutex);
774}
775
776static Eina_Bool
777_evas_common_font_all_clear_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__)
778{
779 RGBA_Font_Int *fi = data;
780 _evas_common_font_int_clear(fi);
781 return 1;
782}
783
784EAPI void
785evas_common_font_all_clear(void)
786{
787 eina_hash_foreach(fonts, _evas_common_font_all_clear_cb, NULL);
788}
789
790void
791evas_common_font_int_promote(RGBA_Font_Int *fi)
792{
793 return;
794 if (fonts_use_lru == (Eina_Inlist *)fi) return;
795 if (!fi->inuse) return;
796 fonts_use_lru = eina_inlist_remove(fonts_use_lru, EINA_INLIST_GET(fi));
797 fonts_use_lru = eina_inlist_prepend(fonts_use_lru, EINA_INLIST_GET(fi));
798}
799
800void
801evas_common_font_int_use_increase(int size)
802{
803 fonts_use_usage += size;
804}
805
806void
807evas_common_font_int_use_trim(void)
808{
809 Eina_Inlist *l;
810
811 return;
812 if (fonts_use_usage <= (font_cache << 1)) return;
813 if (!fonts_use_lru) return;
814 l = fonts_use_lru->last;
815 while (l)
816 {
817 RGBA_Font_Int *fi = (RGBA_Font_Int *)l;
818 if (fonts_use_usage <= (font_cache << 1)) break;
819 // FIXME: del fi->kerning content
820 _evas_common_font_int_clear(fi);
821 evas_common_font_int_unload(fi);
822 evas_common_font_int_promote(fi);
823 l = l->prev;
824 }
825}
826
827void
828evas_common_font_int_unload(RGBA_Font_Int *fi)
829{
830 return;
831 if (!fi->src->ft.face) return;
832 _evas_common_font_int_clear(fi);
833 FT_Done_Size(fi->ft.size);
834 fi->ft.size = NULL;
835 evas_common_font_source_unload(fi->src);
836}
837
838void
839evas_common_font_int_reload(RGBA_Font_Int *fi)
840{
841 if (fi->src->ft.face) return;
842 evas_common_font_source_load_complete(fi->src);
843 return;
844 evas_common_font_source_reload(fi->src);
845 evas_common_font_int_load_complete(fi);
846}
847
848/* when the fi->references == 0 we increase this instead of really deleting
849 * we then check if the cache_useage size is larger than allowed
850 * !If the cache is NOT too large we dont delete font_int
851 * !If the cache is too large we really delete font_int */
852EAPI void
853evas_common_font_int_modify_cache_by(RGBA_Font_Int *fi, int dir)
854{
855 font_cache_usage += dir * (sizeof(RGBA_Font) + fi->usage +
856 sizeof(FT_FaceRec) + 16384); /* fudge values */
857}
858
859EAPI int
860evas_common_font_cache_get(void)
861{
862 return font_cache;
863}
864
865EAPI void
866evas_common_font_cache_set(int size)
867{
868 font_cache = size;
869 evas_common_font_flush();
870 evas_common_font_int_use_trim();
871}
872
873EAPI void
874evas_common_font_flush(void)
875{
876 if (font_cache_usage < font_cache) return;
877 while (font_cache_usage > font_cache)
878 {
879 int pfont_cache_usage;
880
881 pfont_cache_usage = font_cache_usage;
882 evas_common_font_flush_last();
883 if (pfont_cache_usage == font_cache_usage) break;
884 }
885}
886
887/* We run this when the cache gets larger than allowed size
888 * We check cache size each time a fi->references goes to 0
889 * PERFORMS: Find font_int(s) with references == 0 and delete them */
890EAPI void
891evas_common_font_flush_last(void)
892{
893 RGBA_Font_Int *fi = NULL;
894
895 if (!fonts_lru) return ;
896 fi = eina_list_data_get(fonts_lru);
897 fonts_lru = eina_list_remove_list(fonts_lru, fonts_lru);
898 eina_hash_del(fonts, fi, fi);
899}
900
901EAPI RGBA_Font_Int *
902evas_common_font_int_find(const char *name, int size,
903 Font_Rend_Flags wanted_rend)
904{
905 RGBA_Font_Int tmp_fi;
906 RGBA_Font_Source tmp_fn;
907 RGBA_Font_Int *fi;
908
909 tmp_fn.name = (char*) eina_stringshare_add(name);
910 tmp_fi.src = &tmp_fn;
911 tmp_fi.size = size;
912 tmp_fi.wanted_rend = wanted_rend;
913 fi = eina_hash_find(fonts, &tmp_fi);
914 if (fi)
915 {
916 if (fi->references == 0)
917 {
918 evas_common_font_int_modify_cache_by(fi, -1);
919 fonts_lru = eina_list_remove(fonts_lru, fi);
920 }
921 fi->references++;
922 }
923 eina_stringshare_del(tmp_fn.name);
924 return fi;
925}