ok and METRIC then! :)
[profile/ivi/evas.git] / src / lib / engines / common / evas_font_main.c
1 #include "evas_common.h"
2 #include "evas_private.h"
3
4 #include "evas_font_private.h"
5
6 #ifdef EVAS_CSERVE2
7 # include "../../cserve2/evas_cs2_private.h"
8 #endif
9
10 #include <assert.h>
11
12 #include FT_OUTLINE_H
13 #include FT_SYNTHESIS_H
14
15 FT_Library      evas_ft_lib = 0;
16 static int      initialised = 0;
17
18 LK(lock_font_draw); // for freetype2 API calls
19 LK(lock_bidi); // for evas bidi internal usage.
20 LK(lock_ot); // for evas bidi internal usage.
21
22 EAPI void
23 evas_common_font_init(void)
24 {
25    int error;
26    const char *s;
27
28    initialised++;
29    if (initialised != 1) return;
30    error = FT_Init_FreeType(&evas_ft_lib);
31    if (error) return;
32    evas_common_font_load_init();
33    evas_common_font_draw_init();
34    s = getenv("EVAS_FONT_DPI");
35    if (s)
36      {
37         int dpi = atoi(s);
38
39         if (dpi > 0) evas_common_font_dpi_set(dpi);
40      }
41    LKI(lock_font_draw);
42    LKI(lock_bidi);
43    LKI(lock_ot);
44 }
45
46 EAPI void
47 evas_common_font_shutdown(void)
48 {
49    if (initialised < 1) return;
50    initialised--;
51    if (initialised != 0) return;
52
53    evas_common_font_load_shutdown();
54    evas_common_font_cache_set(0);
55    evas_common_font_flush();
56
57    FT_Done_FreeType(evas_ft_lib);
58    evas_ft_lib = 0;
59
60    LKD(lock_font_draw);
61    LKD(lock_bidi);
62    LKD(lock_ot);
63 }
64
65 EAPI void
66 evas_common_font_font_all_unload(void)
67 {
68    evas_common_font_all_clear();
69 }
70
71 EAPI int
72 evas_common_font_ascent_get(RGBA_Font *fn)
73 {
74    int val;
75    RGBA_Font_Int *fi;
76
77 //   evas_common_font_size_use(fn);
78 #if 0
79      {
80         Eina_List *l;
81         
82         EINA_LIST_FOREACH(fn->fonts, l, fi)
83           {
84              if (!fi->src->ft.face) continue;
85              if (fi->src->current_size != fi->size)
86                {
87                   FTLOCK();
88                   FT_Activate_Size(fi->ft.size);
89                   FTUNLOCK();
90                   fi->src->current_size = fi->size;
91                }
92              val = (int)fi->src->ft.face->size->metrics.ascender;
93              if (fi->src->ft.face->units_per_EM == 0)
94                return val;
95              dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
96              ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
97              printf(" ==== %p: %i\n", fi, ret);
98           }
99      }
100 #endif
101    fi = fn->fonts->data;
102    evas_common_font_int_reload(fi);
103    if (fi->src->current_size != fi->size)
104      {
105         FTLOCK();
106         FT_Activate_Size(fi->ft.size);
107         FTUNLOCK();
108         fi->src->current_size = fi->size;
109      }
110    if (!FT_IS_SCALABLE(fi->src->ft.face))
111      {
112         WRN("NOT SCALABLE!");
113      }
114    val = (int)fi->src->ft.face->size->metrics.ascender;
115    return FONT_METRIC_ROUNDUP(val);
116 //   printf("%i | %i\n", val, val >> 6);
117 //   if (fi->src->ft.face->units_per_EM == 0)
118 //     return val;
119 //   dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
120 //   ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
121 //   return ret;
122 }
123
124 EAPI int
125 evas_common_font_descent_get(RGBA_Font *fn)
126 {
127    int val;
128    RGBA_Font_Int *fi;
129
130 //   evas_common_font_size_use(fn);
131    fi = fn->fonts->data;
132    evas_common_font_int_reload(fi);
133    if (fi->src->current_size != fi->size)
134      {
135         FTLOCK();
136         FT_Activate_Size(fi->ft.size);
137         FTUNLOCK();
138         fi->src->current_size = fi->size;
139      }
140    val = -(int)fi->src->ft.face->size->metrics.descender;
141    return FONT_METRIC_ROUNDUP(val);
142 //   if (fi->src->ft.face->units_per_EM == 0)
143 //     return val;
144 //   dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
145 //   ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
146 //   return ret;
147 }
148
149 EAPI int
150 evas_common_font_max_ascent_get(RGBA_Font *fn)
151 {
152    int val, dv;
153    int ret;
154    RGBA_Font_Int *fi;
155
156 //   evas_common_font_size_use(fn);
157    fi = fn->fonts->data;
158    evas_common_font_int_reload(fi);
159   if (fi->src->current_size != fi->size)
160      {
161         FTLOCK();
162         FT_Activate_Size(fi->ft.size);
163         FTUNLOCK();
164         fi->src->current_size = fi->size;
165      }
166    if ((fi->src->ft.face->bbox.yMax == 0) &&
167        (fi->src->ft.face->bbox.yMin == 0) &&
168        (fi->src->ft.face->units_per_EM == 0))
169      val = FONT_METRIC_ROUNDUP((int)fi->src->ft.face->size->metrics.ascender);
170    else
171      val = (int)fi->src->ft.face->bbox.yMax;
172    if (fi->src->ft.face->units_per_EM == 0)
173      return val;
174    dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
175    ret = FONT_METRIC_CONV(val, dv, fi->src->ft.face->size->metrics.y_scale);
176    return ret;
177 }
178
179 EAPI int
180 evas_common_font_max_descent_get(RGBA_Font *fn)
181 {
182    int val, dv;
183    int ret;
184    RGBA_Font_Int *fi;
185
186 //   evas_common_font_size_use(fn);
187    fi = fn->fonts->data;
188    evas_common_font_int_reload(fi);
189    if (fi->src->current_size != fi->size)
190      {
191         FTLOCK();
192         FT_Activate_Size(fi->ft.size);
193         FTUNLOCK();
194         fi->src->current_size = fi->size;
195      }
196    if ((fi->src->ft.face->bbox.yMax == 0) &&
197        (fi->src->ft.face->bbox.yMin == 0) &&
198        (fi->src->ft.face->units_per_EM == 0))
199      val = FONT_METRIC_ROUNDUP(-(int)fi->src->ft.face->size->metrics.descender);
200    else
201      val = -(int)fi->src->ft.face->bbox.yMin;
202    if (fi->src->ft.face->units_per_EM == 0)
203      return val;
204    dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
205    ret = FONT_METRIC_CONV(val, dv, fi->src->ft.face->size->metrics.y_scale);
206    return ret;
207 }
208
209 EAPI int
210 evas_common_font_get_line_advance(RGBA_Font *fn)
211 {
212    int val;
213    RGBA_Font_Int *fi;
214
215 //   evas_common_font_size_use(fn);
216    fi = fn->fonts->data;
217    evas_common_font_int_reload(fi);
218    if (fi->src->current_size != fi->size)
219      {
220         FTLOCK();
221         FT_Activate_Size(fi->ft.size);
222         FTUNLOCK();
223         fi->src->current_size = fi->size;
224      }
225    val = (int)fi->src->ft.face->size->metrics.height;
226    if ((fi->src->ft.face->bbox.yMax == 0) &&
227        (fi->src->ft.face->bbox.yMin == 0) &&
228        (fi->src->ft.face->units_per_EM == 0))
229      return FONT_METRIC_ROUNDUP(val);
230    else if (fi->src->ft.face->units_per_EM == 0)
231      return val;
232    return FONT_METRIC_ROUNDUP(val);
233 //   dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
234 //   ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
235 //   return ret;
236 }
237
238 /* Set of common functions that are used in a couple of places. */
239
240 static void
241 _fash_int2_free(Fash_Int_Map2 *fash)
242 {
243    int i;
244
245    for (i = 0; i < 256; i++) if (fash->bucket[i]) free(fash->bucket[i]);
246    free(fash);
247 }
248
249 static void
250 _fash_int_free(Fash_Int *fash)
251 {
252    int i;
253
254    for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_int2_free(fash->bucket[i]);
255    free(fash);
256 }
257
258 static Fash_Int *
259 _fash_int_new(void)
260 {
261    Fash_Int *fash = calloc(1, sizeof(Fash_Int));
262    fash->freeme = _fash_int_free;
263    return fash;
264 }
265
266 static Fash_Item_Index_Map *
267 _fash_int_find(Fash_Int *fash, int item)
268 {
269    int grp, maj, min;
270
271    // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
272    grp = (item >> 16) & 0xff;
273    maj = (item >> 8) & 0xff;
274    min = item & 0xff;
275    if (!fash->bucket[grp]) return NULL;
276    if (!fash->bucket[grp]->bucket[maj]) return NULL;
277    return &(fash->bucket[grp]->bucket[maj]->item[min]);
278 }
279
280 static void
281 _fash_int_add(Fash_Int *fash, int item, RGBA_Font_Int *fint, int idx)
282 {
283    int grp, maj, min;
284
285    // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
286    grp = (item >> 16) & 0xff;
287    maj = (item >> 8) & 0xff;
288    min = item & 0xff;
289    if (!fash->bucket[grp])
290      fash->bucket[grp] = calloc(1, sizeof(Fash_Int_Map2));
291    EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]);
292    if (!fash->bucket[grp]->bucket[maj])
293      fash->bucket[grp]->bucket[maj] = calloc(1, sizeof(Fash_Int_Map));
294    EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]->bucket[maj]);
295    fash->bucket[grp]->bucket[maj]->item[min].fint = fint;
296    fash->bucket[grp]->bucket[maj]->item[min].index = idx;
297 }
298
299 static void
300 _fash_glyph_free(Fash_Glyph_Map *fmap)
301 {
302    int i;
303
304    for (i = 0; i <= 0xff; i++)
305      {
306         RGBA_Font_Glyph *fg = fmap->item[i];
307         if ((fg) && (fg != (void *)(-1)))
308           {
309              FT_Done_Glyph(fg->glyph);
310              /* extension calls */
311              if (fg->ext_dat_free) fg->ext_dat_free(fg->ext_dat);
312              if (fg->glyph_out_free) fg->glyph_out_free(fg->glyph_out);
313              free(fg);
314              fmap->item[i] = NULL;
315           }
316      }
317   free(fmap);
318 }
319
320 static void
321 _fash_gl2_free(Fash_Glyph_Map2 *fash)
322 {
323    int i;
324
325    // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
326    for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_glyph_free(fash->bucket[i]);
327    free(fash);
328 }
329
330 static void
331 _fash_gl_free(Fash_Glyph *fash)
332 {
333    int i;
334
335     // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
336    for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_gl2_free(fash->bucket[i]);
337    free(fash);
338 }
339
340 static Fash_Glyph *
341 _fash_gl_new(void)
342 {
343    Fash_Glyph *fash = calloc(1, sizeof(Fash_Glyph));
344    fash->freeme = _fash_gl_free;
345    return fash;
346 }
347
348 static RGBA_Font_Glyph *
349 _fash_gl_find(Fash_Glyph *fash, int item)
350 {
351    int grp, maj, min;
352
353    // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
354    grp = (item >> 16) & 0xff;
355    maj = (item >> 8) & 0xff;
356    min = item & 0xff;
357    if (!fash->bucket[grp]) return NULL;
358    if (!fash->bucket[grp]->bucket[maj]) return NULL;
359    return fash->bucket[grp]->bucket[maj]->item[min];
360 }
361
362 static void
363 _fash_gl_add(Fash_Glyph *fash, int item, RGBA_Font_Glyph *glyph)
364 {
365    int grp, maj, min;
366
367    // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
368    grp = (item >> 16) & 0xff;
369    maj = (item >> 8) & 0xff;
370    min = item & 0xff;
371    if (!fash->bucket[grp])
372      fash->bucket[grp] = calloc(1, sizeof(Fash_Glyph_Map2));
373    EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]);
374    if (!fash->bucket[grp]->bucket[maj])
375      fash->bucket[grp]->bucket[maj] = calloc(1, sizeof(Fash_Glyph_Map));
376    EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]->bucket[maj]);
377    fash->bucket[grp]->bucket[maj]->item[min] = glyph;
378 }
379
380 EAPI RGBA_Font_Glyph *
381 evas_common_font_int_cache_glyph_get(RGBA_Font_Int *fi, FT_UInt idx)
382 {
383    RGBA_Font_Glyph *fg;
384    FT_Error error;
385    const FT_Int32 hintflags[3] =
386      { FT_LOAD_NO_HINTING, FT_LOAD_FORCE_AUTOHINT, FT_LOAD_NO_AUTOHINT };
387    static FT_Matrix transform = {0x10000, _EVAS_FONT_SLANT_TAN * 0x10000,
388         0x00000, 0x10000};
389
390    evas_common_font_int_promote(fi);
391    if (fi->fash)
392      {
393         fg = _fash_gl_find(fi->fash, idx);
394         if (fg == (void *)(-1)) return NULL;
395         else if (fg)
396           {
397 #ifdef EVAS_CSERVE2
398              if (fi->cs2_handler)
399                evas_cserve2_font_glyph_used(fi->cs2_handler, idx,
400                                             fi->hinting);
401 #endif
402              return fg;
403           }
404      }
405 //   fg = eina_hash_find(fi->glyphs, &hindex);
406 //   if (fg) return fg;
407
408    evas_common_font_int_reload(fi);
409    FTLOCK();
410    error = FT_Load_Glyph(fi->src->ft.face, idx,
411                          FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP |
412                          hintflags[fi->hinting]);
413    FTUNLOCK();
414    if (error)
415      {
416         if (!fi->fash) fi->fash = _fash_gl_new();
417         if (fi->fash) _fash_gl_add(fi->fash, idx, (void *)(-1));
418         return NULL;
419      }
420
421    /* Transform the outline of Glyph according to runtime_rend. */
422    if (fi->runtime_rend & FONT_REND_SLANT)
423       FT_Outline_Transform(&fi->src->ft.face->glyph->outline, &transform);
424    /* Embolden the outline of Glyph according to rundtime_rend. */
425    if (fi->runtime_rend & FONT_REND_WEIGHT)
426       FT_GlyphSlot_Embolden(fi->src->ft.face->glyph);
427
428    fg = malloc(sizeof(struct _RGBA_Font_Glyph));
429    if (!fg) return NULL;
430    memset(fg, 0, (sizeof(struct _RGBA_Font_Glyph)));
431
432    FTLOCK();
433    error = FT_Get_Glyph(fi->src->ft.face->glyph, &(fg->glyph));
434    FTUNLOCK();
435    if (error)
436      {
437         free(fg);
438         if (!fi->fash) fi->fash = _fash_gl_new();
439         if (fi->fash) _fash_gl_add(fi->fash, idx, (void *)(-1));
440         return NULL;
441      }
442
443      {
444         FT_BBox outbox;
445         FT_Glyph_Get_CBox(fg->glyph,
446               ((fi->hinting == 0) ? FT_GLYPH_BBOX_UNSCALED :
447                FT_GLYPH_BBOX_GRIDFIT),
448               &outbox);
449         fg->width = EVAS_FONT_ROUND_26_6_TO_INT(outbox.xMax - outbox.xMin);
450         fg->x_bear = EVAS_FONT_ROUND_26_6_TO_INT(outbox.xMin);
451         fg->y_bear = EVAS_FONT_ROUND_26_6_TO_INT(outbox.yMax);
452      }
453
454    fg->index = idx;
455    fg->fi = fi;
456
457    if (!fi->fash) fi->fash = _fash_gl_new();
458    if (fi->fash) _fash_gl_add(fi->fash, idx, fg);
459
460 #ifdef EVAS_CSERVE2
461    if (fi->cs2_handler)
462      evas_cserve2_font_glyph_request(fi->cs2_handler, idx, fi->hinting);
463 #endif
464
465 //   eina_hash_direct_add(fi->glyphs, &fg->index, fg);
466    return fg;
467 }
468
469 EAPI Eina_Bool
470 evas_common_font_int_cache_glyph_render(RGBA_Font_Glyph *fg)
471 {
472    int size;
473    FT_Error error;
474    RGBA_Font_Int *fi = fg->fi;
475    FT_BitmapGlyph fbg;
476
477 #ifdef EVAS_CSERVE2
478    if (fi->cs2_handler)
479      {
480         fg->glyph_out = evas_cserve2_font_glyph_bitmap_get(fi->cs2_handler,
481                                                            fg->index,
482                                                            fg->fi->hinting);
483         if (fg->glyph_out)
484           return EINA_TRUE;
485      }
486 #endif
487
488    /* no cserve2 case */
489    FTLOCK();
490    error = FT_Glyph_To_Bitmap(&(fg->glyph), FT_RENDER_MODE_NORMAL, 0, 1);
491    if (error)
492      {
493         FT_Done_Glyph(fg->glyph);
494         FTUNLOCK();
495         free(fg);
496         if (!fi->fash) fi->fash = _fash_gl_new();
497         if (fi->fash) _fash_gl_add(fi->fash, fg->index, (void *)(-1));
498         return EINA_FALSE;
499      }
500    FTUNLOCK();
501
502    fbg = (FT_BitmapGlyph)fg->glyph;
503
504    fg->glyph_out = malloc(sizeof(RGBA_Font_Glyph_Out));
505    fg->glyph_out->bitmap.rows = fbg->bitmap.rows;
506    fg->glyph_out->bitmap.width = fbg->bitmap.width;
507    fg->glyph_out->bitmap.pitch = fbg->bitmap.pitch;
508    fg->glyph_out->bitmap.buffer = fbg->bitmap.buffer;
509    fg->glyph_out->bitmap.num_grays = fbg->bitmap.num_grays;
510    fg->glyph_out->bitmap.pixel_mode = fbg->bitmap.pixel_mode;
511
512    fg->glyph_out_free = free;
513    /* This '+ 200' is just an estimation of how much memory freetype will use
514     * on it's size. This value is not really used anywhere in code - it's
515     * only for statistics. */
516    size = sizeof(RGBA_Font_Glyph) + sizeof(Eina_List) +
517     (fg->glyph_out->bitmap.width * fg->glyph_out->bitmap.rows) + 200;
518    fi->usage += size;
519    if (fi->inuse) evas_common_font_int_use_increase(size);
520
521    return EINA_TRUE;
522 }
523
524 typedef struct _Font_Char_Index Font_Char_Index;
525 struct _Font_Char_Index
526 {
527    FT_UInt index;
528    Eina_Unicode gl;
529 };
530
531 EAPI FT_UInt
532 evas_common_get_char_index(RGBA_Font_Int* fi, Eina_Unicode gl)
533 {
534    static const unsigned short mapfix[] =
535      {
536         0x00b0, 0x7,
537         0x00b1, 0x8,
538         0x00b7, 0x1f,
539         0x03c0, 0x1c,
540         0x20a4, 0xa3,
541         0x2260, 0x1d,
542         0x2264, 0x1a,
543         0x2265, 0x1b,
544         0x23ba, 0x10,
545         0x23bb, 0x11,
546         0x23bc, 0x13,
547         0x23bd, 0x14,
548         0x2409, 0x3,
549         0x240a, 0x6,
550         0x240b, 0xa,
551         0x240c, 0x4,
552         0x240d, 0x5,
553         0x2424, 0x9,
554         0x2500, 0x12,
555         0x2502, 0x19,
556         0x250c, 0xd,
557         0x2510, 0xc,
558         0x2514, 0xe,
559         0x2518, 0xb,
560         0x251c, 0x15,
561         0x2524, 0x16,
562         0x252c, 0x18,
563         0x2534, 0x17,
564         0x253c, 0xf,
565         0x2592, 0x2,
566         0x25c6, 0x1,
567      };
568    Font_Char_Index result;
569    //FT_UInt ret;
570
571 #ifdef HAVE_PTHREAD
572 ///   pthread_mutex_lock(&fi->ft_mutex);
573 #endif
574
575 //   result = eina_hash_find(fi->indexes, &gl);
576 //   if (result) goto on_correct;
577 //
578 //   result = malloc(sizeof (Font_Char_Index));
579 //   if (!result)
580 //     {
581 //#ifdef HAVE_PTHREAD
582 //      pthread_mutex_unlock(&fi->ft_mutex);
583 //#endif
584 //      return FT_Get_Char_Index(fi->src->ft.face, gl);
585 //     }
586
587    evas_common_font_int_reload(fi);
588    /*
589     * There is no point in locking FreeType at this point as all caller
590     * are running in the main loop at a time where there is zero chance
591     * that something else try to use it.
592     */
593    /* FTLOCK(); */
594    result.index = FT_Get_Char_Index(fi->src->ft.face, gl);
595    /* FTUNLOCK(); */
596    result.gl = gl;
597
598 //   eina_hash_direct_add(fi->indexes, &result->gl, result);
599 //
600 // on_correct:
601 #ifdef HAVE_PTHREAD
602 //   pthread_mutex_unlock(&fi->ft_mutex);
603 #endif
604    // this is a workaround freetype bugs where for a bitmap old style font
605    // even if it has unicode information and mappings, they are not used
606    // to find terminal line/drawing chars, so do this by hand with a table
607    if ((result.index <= 0) && (fi->src->ft.face->num_fixed_sizes == 1) &&
608       (fi->src->ft.face->num_glyphs < 512))
609      {
610         int i, min = 0, max;
611
612         // binary search through sorted table of codepoints to new
613         // codepoints with a guess that bitmap font is playing the old
614         // game of putting line drawing chars in specific ranges
615         max = sizeof(mapfix) / (sizeof(mapfix[0]) * 2);
616         i = (min + max) / 2;                                          
617         for (;;)
618           {
619              unsigned short v;
620              
621              v = mapfix[i << 1];
622              if (gl == v)
623                {
624                   gl = mapfix[(i << 1) + 1];
625                   FTLOCK();
626                   result.index = FT_Get_Char_Index(fi->src->ft.face, gl);
627                   FTUNLOCK();
628                   break;
629                }
630              // failure to find at all
631              if ((max - min) <= 2) break;
632              // if glyph above out position...
633              if (gl > v)
634                {
635                   min = i;
636                   if ((max - min) == 1) i = max;
637                   else i = (min + max) / 2;
638                }
639              // if glyph below out position
640              else if (gl < v)
641                {
642                   max = i;
643                   if ((max - min) == 1) i = min;
644                   else i = (min + max) / 2;
645                }
646           }
647      }
648    return result.index;
649 }
650
651 EAPI int
652 evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, Eina_Unicode gl)
653 {
654    Eina_List *l;
655
656    if (fn->fash)
657      {
658         Fash_Item_Index_Map *fm = _fash_int_find(fn->fash, gl);
659         if (fm)
660           {
661              if (fm->fint)
662                {
663                   *fi_ret = fm->fint;
664                   return fm->index;
665                }
666              else if (fm->index == -1) return 0;
667           }
668      }
669
670    for (l = fn->fonts; l; l = l->next)
671      {
672         RGBA_Font_Int *fi;
673         int idx;
674
675         fi = l->data;
676
677 #if 0 /* FIXME: charmap user is disabled and use a deprecated data type. */
678 /*        
679         if (fi->src->charmap) // Charmap loaded, FI/FS blank
680           {
681              idx = evas_array_hash_search(fi->src->charmap, gl);
682              if (idx != 0)
683                {
684                   evas_common_font_source_load_complete(fi->src);
685                   evas_common_font_int_load_complete(fi);
686
687                   evas_array_hash_free(fi->src->charmap);
688                   fi->src->charmap = NULL;
689
690                   *fi_ret = fi;
691                   return idx;
692                }
693            }
694         else
695 */
696 #endif
697         if (!fi->src->ft.face) /* Charmap not loaded, FI/FS blank */
698           {
699              evas_common_font_int_reload(fi);
700           }
701         if (fi->src->ft.face)
702           {
703              idx = evas_common_get_char_index(fi, gl);
704              if (idx != 0)
705                {
706                   if (!fi->ft.size)
707                     evas_common_font_int_load_complete(fi);
708                   if (!fn->fash) fn->fash = _fash_int_new();
709                   if (fn->fash) _fash_int_add(fn->fash, gl, fi, idx);
710                   *fi_ret = fi;
711                   return idx;
712                }
713              else
714                {
715                   if (!fn->fash) fn->fash = _fash_int_new();
716                   if (fn->fash) _fash_int_add(fn->fash, gl, NULL, -1);
717                }
718           }
719      }
720    *fi_ret = NULL;
721    return 0;
722 }