ok and METRIC then! :)
[profile/ivi/evas.git] / src / lib / engines / common / evas_font_load.c
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 EVAS_CSERVE2
10 # include "../../cserve2/evas_cs2_private.h"
11 #endif
12
13 #ifdef USE_HARFBUZZ
14 # include <hb.h>
15 # include <hb-ft.h>
16 #endif
17
18 extern FT_Library         evas_ft_lib;
19
20 static int                font_cache_usage = 0;
21 static int                font_cache = 0;
22 static int                font_dpi = 75;
23
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;
29
30 static void _evas_common_font_int_clear(RGBA_Font_Int *fi);
31
32 static int
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__)
35 {
36    /* RGBA_Font_Source->name is a stringshare */
37    if (k1->src->name == k2->src->name)
38      {
39         if (k1->size == k2->size)
40            return k1->wanted_rend - k2->wanted_rend;
41         else
42            return k1->size - k2->size;
43      }
44    return strcmp(k1->src->name, k2->src->name);
45 }
46
47 static int
48 _evas_font_cache_int_hash(const RGBA_Font_Int *key, int key_length __UNUSED__)
49 {
50    int hash;
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));
55    return hash;
56 }
57
58 static void
59 _evas_common_font_source_free(RGBA_Font_Source *fs)
60 {
61    FTLOCK();
62    FT_Done_Face(fs->ft.face);
63    FTUNLOCK();
64    if (fs->name) eina_stringshare_del(fs->name);
65    if (fs->file) eina_stringshare_del(fs->file);
66    free(fs);
67 }
68
69 static void
70 _evas_common_font_int_free(RGBA_Font_Int *fi)
71 {
72    FT_Done_Size(fi->ft.size);
73
74    evas_common_font_int_modify_cache_by(fi, -1);
75    _evas_common_font_int_clear(fi);
76    eina_hash_free(fi->kerning);
77
78    LKD(fi->ft_mutex);
79 #ifdef USE_HARFBUZZ
80    hb_font_destroy(fi->ft.hb_font);
81 #endif
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);
85    if (fi->inuse)
86     {
87       fonts_use_lru = eina_inlist_remove(fonts_use_lru, EINA_INLIST_GET(fi));
88       fi->inuse = 0;
89       fonts_use_usage -= fi->usage;
90       fi->usage = 0;
91     }
92 #ifdef EVAS_CSERVE2
93    evas_cserve2_font_free(fi->cs2_handler);
94 #endif
95    free(fi);
96 }
97
98 void
99 evas_common_font_load_init(void)
100 {
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),
106                          5);
107 }
108
109 void
110 evas_common_font_load_shutdown(void)
111 {
112    eina_hash_free(fonts);
113    fonts = NULL;
114    eina_hash_free(fonts_src);
115    fonts_src = NULL;
116 }
117
118 EAPI void
119 evas_common_font_dpi_set(int dpi)
120 {
121    font_dpi = dpi;
122 }
123
124 EAPI RGBA_Font_Source *
125 evas_common_font_source_memory_load(const char *name, const void *data, int data_size)
126 {
127    int error; 
128    RGBA_Font_Source *fs;
129
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);
137    FTLOCK();
138    error = FT_New_Memory_Face(evas_ft_lib, fs->data, fs->data_size, 0, &(fs->ft.face));
139    FTUNLOCK();
140    if (error)
141      {
142         free(fs);
143         return NULL;
144      }
145    fs->name = eina_stringshare_add(name);
146    fs->file = NULL;
147    FTLOCK();
148    error = FT_Select_Charmap(fs->ft.face, ft_encoding_unicode);
149   if (error)
150     {
151       FT_Done_Face(fs->ft.face);
152       fs->ft.face = NULL;
153       free(fs);
154       return NULL;
155     }
156    FTUNLOCK();
157    fs->ft.orig_upem = fs->ft.face->units_per_EM;
158    fs->references = 1;
159    eina_hash_direct_add(fonts_src, fs->name, fs);
160    return fs;
161 }
162
163 EAPI RGBA_Font_Source *
164 evas_common_font_source_load(const char *name)
165 {
166    RGBA_Font_Source *fs;
167
168    assert(name != NULL);
169    fs = calloc(1, sizeof(RGBA_Font_Source));
170    if (!fs) return NULL;
171    fs->data = NULL;
172    fs->data_size = 0;
173    fs->current_size = 0;
174    fs->ft.face = NULL;
175    fs->name = eina_stringshare_add(name);
176    fs->file = eina_stringshare_ref(fs->name);
177    fs->ft.orig_upem = 0;
178    fs->references = 1;
179    eina_hash_direct_add(fonts_src, fs->name, fs);
180    return fs;
181 }
182
183 void
184 evas_common_font_source_unload(RGBA_Font_Source *fs)
185 {
186    FTLOCK();
187    FT_Done_Face(fs->ft.face);
188    fs->ft.face = NULL;
189    FTUNLOCK();
190 }
191
192 void
193 evas_common_font_source_reload(RGBA_Font_Source *fs)
194 {
195   if (fs->ft.face) return;
196   if (fs->data)
197     {
198       int error;
199       
200       FTLOCK();
201       error = FT_New_Memory_Face(evas_ft_lib, fs->data, fs->data_size, 0, &(fs->ft.face));
202       FTUNLOCK();
203       if (error) return;
204       FTLOCK();
205       error = FT_Select_Charmap(fs->ft.face, ft_encoding_unicode);
206       if (error)
207         {
208           FT_Done_Face(fs->ft.face);
209           fs->ft.face = NULL;
210         }
211       FTUNLOCK();
212     }
213   else
214     evas_common_font_source_load_complete(fs);
215 }
216
217 EAPI int
218 evas_common_font_source_load_complete(RGBA_Font_Source *fs)
219 {
220    int error;
221
222    FTLOCK();
223    error = FT_New_Face(evas_ft_lib, fs->file, 0, &(fs->ft.face));
224    if (error)
225      {
226         FTUNLOCK();
227         fs->ft.face = NULL;
228         return error;
229      }
230    error = FT_Select_Charmap(fs->ft.face, ft_encoding_unicode);
231    if (error)
232      {
233         FT_Done_Face(fs->ft.face);
234         FTUNLOCK();
235         fs->ft.face = NULL;
236         return error;
237      }
238    FTUNLOCK();
239    fs->ft.orig_upem = fs->ft.face->units_per_EM;
240    return error;
241 }
242
243 EAPI RGBA_Font_Source *
244 evas_common_font_source_find(const char *name)
245 {
246    RGBA_Font_Source *fs;
247
248    if (!name) return NULL;
249    fs = eina_hash_find(fonts_src, name);
250    if (fs)
251      {
252         fs->references++;
253         return fs;
254      }
255    return NULL;
256 }
257
258 EAPI void
259 evas_common_font_source_free(RGBA_Font_Source *fs)
260 {
261    fs->references--;
262    if (fs->references > 0) return;
263    eina_hash_del(fonts_src, fs->name, fs);
264 }
265
266 EAPI void
267 evas_common_font_size_use(RGBA_Font *fn)
268 {
269    RGBA_Font_Int *fi;
270    Eina_List *l;
271
272    EINA_LIST_FOREACH(fn->fonts, l, fi)
273      {
274         if (fi->src->current_size != fi->size)
275           {
276              evas_common_font_source_reload(fi->src);
277              FTLOCK();
278              FT_Activate_Size(fi->ft.size);
279              FTUNLOCK();
280              fi->src->current_size = fi->size;
281           }
282      }
283 }
284
285 static int
286 _evas_common_font_double_int_cmp(const int *key1, __UNUSED__ int key1_length,
287                                  const int *key2, __UNUSED__ int key2_length)
288 {
289    if (key1[0] - key2[0] == 0) return key1[1] - key2[1];
290    return key1[0] - key2[0];
291 }
292
293 static int
294 _evas_common_font_double_int_hash(const unsigned int key[2], int key_length)
295 {
296    return 
297     eina_hash_int32(&key[0], key_length) ^ 
298     eina_hash_int32(&key[1], key_length);
299 }
300
301 static void
302 _evas_common_font_int_cache_init(RGBA_Font_Int *fi)
303 {
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),
308                                free, 3);
309    LKI(fi->ft_mutex);
310 }
311
312 EAPI RGBA_Font_Int *
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)
314 {
315    RGBA_Font_Int *fi;
316    char *fake_name;
317
318    fake_name = evas_file_path_join(source, name);
319    fi = evas_common_font_int_find(fake_name, size, wanted_rend);
320    if (fi)
321      {
322         free(fake_name);
323         return fi;
324      }
325    fi = calloc(1, sizeof(RGBA_Font_Int));
326    if (!fi)
327      {
328         free(fake_name);
329         return NULL;
330      }
331    fi->src = evas_common_font_source_find(fake_name);
332    if (!fi->src)
333     fi->src = evas_common_font_source_memory_load(fake_name, data, data_size);
334    if (!fi->src)
335      {
336         free(fi);
337         free(fake_name);
338         return NULL;
339      }
340    fi->size = 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);
344 #ifdef EVAS_CSERVE2
345    if (evas_cserve2_use_get())
346      fi->cs2_handler = evas_cserve2_font_load(source, name, size, font_dpi,
347                                               wanted_rend);
348 #endif
349    free(fake_name);
350    return fi;
351 }
352
353 EAPI RGBA_Font_Int *
354 evas_common_font_int_load(const char *name, int size,
355                           Font_Rend_Flags wanted_rend)
356 {
357    RGBA_Font_Int *fi;
358
359    fi = evas_common_font_int_find(name, size, wanted_rend);
360    if (fi) return fi;
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);
366
367    if (!fi->src)
368      {
369         free(fi);
370         return NULL;
371      }
372    fi->size = size;
373    fi->wanted_rend = wanted_rend;
374    _evas_common_font_int_cache_init(fi);
375    fi = evas_common_font_int_load_init(fi);
376 #ifdef EVAS_CSERVE2
377    if (evas_cserve2_use_get())
378      fi->cs2_handler = evas_cserve2_font_load(NULL, name, size, font_dpi,
379                                               wanted_rend);
380 #endif
381 //   evas_common_font_int_load_complete(fi);
382    return fi;
383 }
384
385 EAPI RGBA_Font_Int *
386 evas_common_font_int_load_init(RGBA_Font_Int *fi)
387 {
388    fi->ft.size = NULL;
389    fi->references = 1;
390    eina_hash_direct_add(fonts, fi, fi);
391    return fi;
392 }
393
394 EAPI RGBA_Font_Int *
395 evas_common_font_int_load_complete(RGBA_Font_Int *fi)
396 {
397    int val, dv;
398    int ret;
399    int error;
400
401    FTLOCK();
402    error = FT_New_Size(fi->src->ft.face, &(fi->ft.size));
403    if (!error)
404      {
405         FT_Activate_Size(fi->ft.size);
406      }
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);
409    if (error)
410      error = FT_Set_Pixel_Sizes(fi->src->ft.face, 0, fi->real_size);
411    FTUNLOCK();
412    if (error)
413      {
414         int i, maxd = 0x7fffffff;
415         int chosen_size = 0;
416         int chosen_size2 = 0;
417
418         for (i = 0; i < fi->src->ft.face->num_fixed_sizes; i++)
419           {
420              int s, cd;
421              
422              s = fi->src->ft.face->available_sizes[i].size;
423              cd = chosen_size - fi->real_size;
424              if (cd < 0) cd = -cd;
425              if (cd < maxd)
426                {
427                   maxd = cd;
428                   chosen_size = s;
429                   chosen_size2 = fi->src->ft.face->available_sizes[i].y_ppem;
430                   if (maxd == 0) break;
431                }
432           }
433         fi->real_size = chosen_size;
434         FTLOCK();
435         error = FT_Set_Pixel_Sizes(fi->src->ft.face, 0, fi->real_size);
436         FTUNLOCK();
437         if (error)
438           {
439              error = FT_Set_Char_Size(fi->src->ft.face, 0, fi->real_size, font_dpi, font_dpi);
440              if (error)
441                {
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);
445                   if (error)
446                     {
447                        /* couldn't choose the size anyway... what now? */
448                     }
449                }
450           }
451      }
452    fi->src->current_size = 0;
453    fi->max_h = 0;
454    val = (int)fi->src->ft.face->bbox.yMax;
455    if (fi->src->ft.face->units_per_EM != 0)
456      {
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);
459      }
460    else
461      {
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);
465         else
466           ret = val;
467      }
468    fi->max_h += ret;
469    val = -(int)fi->src->ft.face->bbox.yMin;
470    if (fi->src->ft.face->units_per_EM != 0)
471      {
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);
474      }
475    else
476      {
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);
480         else
481           ret = val;
482      }
483    fi->max_h += ret;
484
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;
492
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;
496
497    return fi;
498 }
499
500 EAPI RGBA_Font *
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)
502 {
503    RGBA_Font *fn;
504    RGBA_Font_Int *fi;
505
506    fi = evas_common_font_int_memory_load(source, name, size, data, data_size,
507                                          wanted_rend);
508    if (!fi) return NULL;
509    fn = calloc(1, sizeof(RGBA_Font));
510    if (!fn)
511      {
512         evas_common_font_int_unref(fi);
513         return NULL;
514      }
515    fn->fonts = eina_list_append(fn->fonts, fi);
516    fn->hinting = FONT_BYTECODE_HINT;
517    fi->hinting = fn->hinting;
518    fn->references = 1;
519    LKI(fn->lock);
520    if (fi->inuse) evas_common_font_int_promote(fi);
521    else
522     {
523       fi->inuse = 1;
524       fonts_use_lru = eina_inlist_prepend(fonts_use_lru, EINA_INLIST_GET(fi));
525     }
526    return fn;
527 }
528
529
530 //ZZZ: font struct looks like:
531 // fn->(fi, fi, fi, ...)
532 //   fi->fs
533
534 EAPI RGBA_Font *
535 evas_common_font_load(const char *name, int size, Font_Rend_Flags wanted_rend)
536 {
537    RGBA_Font *fn;
538    RGBA_Font_Int *fi;
539
540    fi = evas_common_font_int_load(name, size, wanted_rend);
541    if (!fi) return NULL;
542    /* First font, complete load */
543    if (!fi->ft.size)
544      {
545         if (!fi->src->ft.face)
546           {
547              if (evas_common_font_source_load_complete(fi->src))
548                {
549                   evas_common_font_int_unref(fi);
550                   return NULL;
551                }
552           }
553         evas_common_font_int_load_complete(fi);
554      }
555    fn = calloc(1, sizeof(RGBA_Font));
556    if (!fn)
557      {
558         evas_common_font_int_unref(fi);
559         return NULL;
560      }
561
562    fn->fonts = eina_list_append(fn->fonts, fi);
563    fn->hinting = FONT_BYTECODE_HINT;
564    fi->hinting = fn->hinting;
565    fn->references = 1;
566    LKI(fn->lock);
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
576 EAPI RGBA_Font *
577 evas_common_font_add(RGBA_Font *fn, const char *name, int size, Font_Rend_Flags wanted_rend)
578 {
579    RGBA_Font_Int *fi;
580
581    if (!fn) return NULL;
582    fi = evas_common_font_int_load(name, size, wanted_rend);
583    if (fi)
584      {
585         fn->fonts = eina_list_append(fn->fonts, fi);
586         fi->hinting = fn->hinting;
587         if (fi->inuse) evas_common_font_int_promote(fi);
588         else
589          {
590            fi->inuse = 1;
591            fonts_use_lru = eina_inlist_prepend(fonts_use_lru, EINA_INLIST_GET(fi));
592          }
593         return fn;
594      }
595    return NULL;
596 }
597
598 EAPI RGBA_Font *
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)
600 {
601    RGBA_Font_Int *fi;
602
603    if (!fn)
604       return NULL;
605    fi = evas_common_font_int_memory_load(source, name, size, data, data_size, wanted_rend);
606    if (fi)
607      {
608         fn->fonts = eina_list_append(fn->fonts, fi);
609         fi->hinting = fn->hinting;
610         if (fi->inuse) evas_common_font_int_promote(fi);
611         else
612          {
613            fi->inuse = 1;
614            fonts_use_lru = eina_inlist_prepend(fonts_use_lru, EINA_INLIST_GET(fi));
615          }
616         return fn;
617      }
618    return NULL;
619 }
620
621 EAPI void
622 evas_common_font_int_unref(RGBA_Font_Int *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         evas_common_font_flush();
630      }
631 }
632
633 EAPI void
634 evas_common_font_free(RGBA_Font *fn)
635 {
636    Eina_List *l;
637    RGBA_Font_Int *fi;
638
639    if (!fn) return;
640    fn->references--;
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);
647    LKD(fn->lock);
648    free(fn);
649 }
650
651 EAPI void
652 evas_common_font_hinting_set(RGBA_Font *fn, Font_Hint_Flags hinting)
653 {
654    Eina_List *l;
655    RGBA_Font_Int *fi;
656
657    if (!fn) return;
658    fn->hinting = hinting;
659    EINA_LIST_FOREACH(fn->fonts, l, fi)
660      {
661         fi->hinting = fn->hinting;
662      }
663 }
664
665 EAPI Eina_Bool
666 evas_common_hinting_available(Font_Hint_Flags hinting)
667 {
668    switch (hinting)
669      {
670       case FONT_NO_HINT:
671       case FONT_AUTO_HINT:
672          /* these two hinting modes are always available */
673          return EINA_TRUE;
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.
678           *
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.
682           */
683 #if FREETYPE_MINOR >= 2
684          return FT_Get_TrueType_Engine_Type(evas_ft_lib) >=
685                 FT_TRUETYPE_ENGINE_TYPE_PATENTED;
686 #else
687          /* we may not rely on TT_CONFIG_OPTION_BYTECODE_INTERPRETER
688           * here to find out whether it's supported.
689           *
690           * so, assume it is. o_O
691           */
692          return EINA_TRUE;
693 #endif
694      }
695    /* shouldn't get here - need to add another case statement */
696    return EINA_FALSE;
697 }
698
699 EAPI RGBA_Font *
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)
701 {
702    RGBA_Font *fn;
703
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);
706    return fn;
707 }
708
709 EAPI RGBA_Font *
710 evas_common_font_hinting_load(const char *name, int size, Font_Hint_Flags hinting, Font_Rend_Flags wanted_rend)
711 {
712    RGBA_Font *fn;
713
714    fn = evas_common_font_load(name, size, wanted_rend);
715    if (fn) evas_common_font_hinting_set(fn, hinting);
716    return fn;
717 }
718
719 EAPI RGBA_Font *
720 evas_common_font_hinting_add(RGBA_Font *fn, const char *name, int size, Font_Hint_Flags hinting, Font_Rend_Flags wanted_rend)
721 {
722    fn = evas_common_font_add(fn, name, size, wanted_rend);
723    if (fn) evas_common_font_hinting_set(fn, hinting);
724    return fn;
725 }
726
727 EAPI RGBA_Font *
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)
729 {
730    fn = evas_common_font_memory_add(fn, source, name, size, data, data_size,
731                                     wanted_rend);
732    if (fn) evas_common_font_hinting_set(fn, hinting);
733    return fn;
734 }
735
736 static void
737 _evas_common_font_int_clear(RGBA_Font_Int *fi)
738 {
739    LKL(fi->ft_mutex);
740    if (!fi->fash)
741      {
742         LKU(fi->ft_mutex);
743         return;
744      }
745    evas_common_font_int_modify_cache_by(fi, -1);
746    if (fi->references <= 1)
747      {
748         if (fi->fash)
749           {
750              fi->fash->freeme(fi->fash);
751              fi->fash = NULL;
752           }
753      }
754    if (fi->inuse) fonts_use_usage -= fi->usage;
755    fi->usage = 0;
756    fi->generation++;
757    LKU(fi->ft_mutex);
758 }
759
760 static Eina_Bool
761 _evas_common_font_all_clear_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__)
762 {
763    RGBA_Font_Int *fi = data;
764    _evas_common_font_int_clear(fi);
765    return 1;
766 }
767
768 EAPI void
769 evas_common_font_all_clear(void)
770 {
771    eina_hash_foreach(fonts, _evas_common_font_all_clear_cb, NULL);
772 }
773
774 void
775 evas_common_font_int_promote(RGBA_Font_Int *fi)
776 {
777   return;
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));
782 }
783
784 void
785 evas_common_font_int_use_increase(int size)
786 {
787   fonts_use_usage += size;
788 }
789
790 void
791 evas_common_font_int_use_trim(void)
792 {
793   Eina_Inlist *l;
794
795   return;
796   if (fonts_use_usage <= (font_cache << 1)) return;
797   if (!fonts_use_lru) return;
798   l = fonts_use_lru->last;
799   while (l)
800     {
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);
807       l = l->prev;
808     }
809 }
810
811 void
812 evas_common_font_int_unload(RGBA_Font_Int *fi)
813 {
814   return;
815   if (!fi->src->ft.face) return;
816   _evas_common_font_int_clear(fi);
817   FT_Done_Size(fi->ft.size);
818   fi->ft.size = NULL;
819   evas_common_font_source_unload(fi->src);
820 }
821
822 void
823 evas_common_font_int_reload(RGBA_Font_Int *fi)
824 {
825   if (fi->src->ft.face) return;
826   evas_common_font_source_load_complete(fi->src);
827   return;
828   evas_common_font_source_reload(fi->src);
829   evas_common_font_int_load_complete(fi);
830 }
831
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 */
836 EAPI void
837 evas_common_font_int_modify_cache_by(RGBA_Font_Int *fi, int dir)
838 {
839    font_cache_usage += dir * (sizeof(RGBA_Font) + fi->usage +
840                               sizeof(FT_FaceRec) + 16384); /* fudge values */
841 }
842
843 EAPI int
844 evas_common_font_cache_get(void)
845 {
846    return font_cache;
847 }
848
849 EAPI void
850 evas_common_font_cache_set(int size)
851 {
852    font_cache = size;
853    evas_common_font_flush();
854    evas_common_font_int_use_trim();
855 }
856
857 EAPI void
858 evas_common_font_flush(void)
859 {
860    if (font_cache_usage < font_cache) return;
861    while (font_cache_usage > font_cache)
862      {
863         int pfont_cache_usage;
864         
865         pfont_cache_usage = font_cache_usage;
866         evas_common_font_flush_last();
867         if (pfont_cache_usage == font_cache_usage) break;
868      }
869 }
870
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 */
874 EAPI void
875 evas_common_font_flush_last(void)
876 {
877    RGBA_Font_Int *fi = NULL;
878
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);
883 }
884
885 EAPI RGBA_Font_Int *
886 evas_common_font_int_find(const char *name, int size,
887                           Font_Rend_Flags wanted_rend)
888 {
889    RGBA_Font_Int tmp_fi;
890    RGBA_Font_Source tmp_fn;
891    RGBA_Font_Int *fi;
892
893    tmp_fn.name = (char*) eina_stringshare_add(name);
894    tmp_fi.src = &tmp_fn;
895    tmp_fi.size = size;
896    tmp_fi.wanted_rend = wanted_rend;
897    fi = eina_hash_find(fonts, &tmp_fi);
898    if (fi)
899      {
900         if (fi->references == 0)
901           {
902              evas_common_font_int_modify_cache_by(fi, -1);
903              fonts_lru = eina_list_remove(fonts_lru, fi);
904           }
905         fi->references++;
906      }
907    eina_stringshare_del(tmp_fn.name);
908    return fi;
909 }