Evas font-draw: Use bitmap offset in the glyph when drawing.
[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 #include <assert.h>
7
8 #include FT_OUTLINE_H
9
10 FT_Library      evas_ft_lib = 0;
11 static int      initialised = 0;
12
13 LK(lock_font_draw); // for freetype2 API calls
14 LK(lock_bidi); // for evas bidi internal usage.
15 LK(lock_ot); // for evas bidi internal usage.
16
17 EAPI void
18 evas_common_font_init(void)
19 {
20    int error;
21    const char *s;
22
23    initialised++;
24    if (initialised != 1) return;
25    error = FT_Init_FreeType(&evas_ft_lib);
26    if (error) return;
27    evas_common_font_load_init();
28    evas_common_font_draw_init();
29    s = getenv("EVAS_FONT_DPI");
30    if (s)
31      {
32         int dpi = atoi(s);
33
34         if (dpi > 0) evas_common_font_dpi_set(dpi);
35      }
36    LKI(lock_font_draw);
37    LKI(lock_bidi);
38    LKI(lock_ot);
39 }
40
41 EAPI void
42 evas_common_font_shutdown(void)
43 {
44    if (initialised < 1) return;
45    initialised--;
46    if (initialised != 0) return;
47
48    LKD(lock_font_draw);
49    LKD(lock_bidi);
50    LKD(lock_ot);
51
52    evas_common_font_load_shutdown();
53    evas_common_font_cache_set(0);
54    evas_common_font_flush();
55
56    FT_Done_FreeType(evas_ft_lib);
57    evas_ft_lib = 0;
58 }
59
60 EAPI void
61 evas_common_font_font_all_unload(void)
62 {
63    evas_common_font_all_clear();
64 }
65
66 EAPI int
67 evas_common_font_ascent_get(RGBA_Font *fn)
68 {
69    int val;
70    RGBA_Font_Int *fi;
71
72 //   evas_common_font_size_use(fn);
73 #if 0
74      {
75         Eina_List *l;
76         
77         EINA_LIST_FOREACH(fn->fonts, l, fi)
78           {
79              if (!fi->src->ft.face) continue;
80              if (fi->src->current_size != fi->size)
81                {
82                   FTLOCK();
83                   FT_Activate_Size(fi->ft.size);
84                   FTUNLOCK();
85                   fi->src->current_size = fi->size;
86                }
87              val = (int)fi->src->ft.face->size->metrics.ascender;
88              if (fi->src->ft.face->units_per_EM == 0)
89                return val;
90              dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
91              ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
92              printf(" ==== %p: %i\n", fi, ret);
93           }
94      }
95 #endif
96    fi = fn->fonts->data;
97    evas_common_font_int_reload(fi);
98    if (fi->src->current_size != fi->size)
99      {
100         FTLOCK();
101         FT_Activate_Size(fi->ft.size);
102         FTUNLOCK();
103         fi->src->current_size = fi->size;
104      }
105    if (!FT_IS_SCALABLE(fi->src->ft.face))
106      {
107         WRN("NOT SCALABLE!");
108      }
109    val = (int)fi->src->ft.face->size->metrics.ascender;
110    return val >> 6;
111 //   printf("%i | %i\n", val, val >> 6);
112 //   if (fi->src->ft.face->units_per_EM == 0)
113 //     return val;
114 //   dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
115 //   ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
116 //   return ret;
117 }
118
119 EAPI int
120 evas_common_font_descent_get(RGBA_Font *fn)
121 {
122    int val;
123    RGBA_Font_Int *fi;
124
125 //   evas_common_font_size_use(fn);
126    fi = fn->fonts->data;
127    evas_common_font_int_reload(fi);
128    if (fi->src->current_size != fi->size)
129      {
130         FTLOCK();
131         FT_Activate_Size(fi->ft.size);
132         FTUNLOCK();
133         fi->src->current_size = fi->size;
134      }
135    val = -(int)fi->src->ft.face->size->metrics.descender;
136    return val >> 6;
137 //   if (fi->src->ft.face->units_per_EM == 0)
138 //     return val;
139 //   dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
140 //   ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
141 //   return ret;
142 }
143
144 EAPI int
145 evas_common_font_max_ascent_get(RGBA_Font *fn)
146 {
147    int val, dv;
148    int ret;
149    RGBA_Font_Int *fi;
150
151 //   evas_common_font_size_use(fn);
152    fi = fn->fonts->data;
153    evas_common_font_int_reload(fi);
154   if (fi->src->current_size != fi->size)
155      {
156         FTLOCK();
157         FT_Activate_Size(fi->ft.size);
158         FTUNLOCK();
159         fi->src->current_size = fi->size;
160      }
161    val = (int)fi->src->ft.face->bbox.yMax;
162    if (fi->src->ft.face->units_per_EM == 0)
163      return val;
164    dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
165    ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
166    return ret;
167 }
168
169 EAPI int
170 evas_common_font_max_descent_get(RGBA_Font *fn)
171 {
172    int val, dv;
173    int ret;
174    RGBA_Font_Int *fi;
175
176 //   evas_common_font_size_use(fn);
177    fi = fn->fonts->data;
178    evas_common_font_int_reload(fi);
179    if (fi->src->current_size != fi->size)
180      {
181         FTLOCK();
182         FT_Activate_Size(fi->ft.size);
183         FTUNLOCK();
184         fi->src->current_size = fi->size;
185      }
186    val = -(int)fi->src->ft.face->bbox.yMin;
187    if (fi->src->ft.face->units_per_EM == 0)
188      return val;
189    dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
190    ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
191    return ret;
192 }
193
194 EAPI int
195 evas_common_font_get_line_advance(RGBA_Font *fn)
196 {
197    int val;
198    RGBA_Font_Int *fi;
199
200 //   evas_common_font_size_use(fn);
201    fi = fn->fonts->data;
202    evas_common_font_int_reload(fi);
203    if (fi->src->current_size != fi->size)
204      {
205         FTLOCK();
206         FT_Activate_Size(fi->ft.size);
207         FTUNLOCK();
208         fi->src->current_size = fi->size;
209      }
210    val = (int)fi->src->ft.face->size->metrics.height;
211    if (fi->src->ft.face->units_per_EM == 0)
212      return val;
213    return val >> 6;
214 //   dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
215 //   ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
216 //   return ret;
217 }
218
219 /* Set of common functions that are used in a couple of places. */
220
221 static void
222 _fash_int2_free(Fash_Int_Map2 *fash)
223 {
224    int i;
225
226    for (i = 0; i < 256; i++) if (fash->bucket[i]) free(fash->bucket[i]);
227    free(fash);
228 }
229
230 static void
231 _fash_int_free(Fash_Int *fash)
232 {
233    int i;
234
235    for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_int2_free(fash->bucket[i]);
236    free(fash);
237 }
238
239 static Fash_Int *
240 _fash_int_new(void)
241 {
242    Fash_Int *fash = calloc(1, sizeof(Fash_Int));
243    fash->freeme = _fash_int_free;
244    return fash;
245 }
246
247 static Fash_Item_Index_Map *
248 _fash_int_find(Fash_Int *fash, int item)
249 {
250    int grp, maj, min;
251
252    // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
253    grp = (item >> 16) & 0xff;
254    maj = (item >> 8) & 0xff;
255    min = item & 0xff;
256    if (!fash->bucket[grp]) return NULL;
257    if (!fash->bucket[grp]->bucket[maj]) return NULL;
258    return &(fash->bucket[grp]->bucket[maj]->item[min]);
259 }
260
261 static void
262 _fash_int_add(Fash_Int *fash, int item, RGBA_Font_Int *fint, int idx)
263 {
264    int grp, maj, min;
265
266    // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
267    grp = (item >> 16) & 0xff;
268    maj = (item >> 8) & 0xff;
269    min = item & 0xff;
270    if (!fash->bucket[grp])
271      fash->bucket[grp] = calloc(1, sizeof(Fash_Int_Map2));
272    EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]);
273    if (!fash->bucket[grp]->bucket[maj])
274      fash->bucket[grp]->bucket[maj] = calloc(1, sizeof(Fash_Int_Map));
275    EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]->bucket[maj]);
276    fash->bucket[grp]->bucket[maj]->item[min].fint = fint;
277    fash->bucket[grp]->bucket[maj]->item[min].index = idx;
278 }
279
280 static void
281 _fash_gl2_free(Fash_Glyph_Map2 *fash)
282 {
283    int i;
284
285    for (i = 0; i < 256; i++) if (fash->bucket[i]) free(fash->bucket[i]);
286    free(fash);
287 }
288
289 static void
290 _fash_gl_free(Fash_Glyph *fash)
291 {
292    int i;
293
294    for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_gl2_free(fash->bucket[i]);
295    free(fash);
296 }
297
298 static Fash_Glyph *
299 _fash_gl_new(void)
300 {
301    Fash_Glyph *fash = calloc(1, sizeof(Fash_Glyph));
302    fash->freeme = _fash_gl_free;
303    return fash;
304 }
305
306 static RGBA_Font_Glyph *
307 _fash_gl_find(Fash_Glyph *fash, int item)
308 {
309    int grp, maj, min;
310
311    // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
312    grp = (item >> 16) & 0xff;
313    maj = (item >> 8) & 0xff;
314    min = item & 0xff;
315    if (!fash->bucket[grp]) return NULL;
316    if (!fash->bucket[grp]->bucket[maj]) return NULL;
317    return fash->bucket[grp]->bucket[maj]->item[min];
318 }
319
320 static void
321 _fash_gl_add(Fash_Glyph *fash, int item, RGBA_Font_Glyph *glyph)
322 {
323    int grp, maj, min;
324
325    // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
326    grp = (item >> 16) & 0xff;
327    maj = (item >> 8) & 0xff;
328    min = item & 0xff;
329    if (!fash->bucket[grp])
330      fash->bucket[grp] = calloc(1, sizeof(Fash_Glyph_Map2));
331    EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]);
332    if (!fash->bucket[grp]->bucket[maj])
333      fash->bucket[grp]->bucket[maj] = calloc(1, sizeof(Fash_Glyph_Map));
334    EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]->bucket[maj]);
335    fash->bucket[grp]->bucket[maj]->item[min] = glyph;
336 }
337
338 EAPI RGBA_Font_Glyph *
339 evas_common_font_int_cache_glyph_get(RGBA_Font_Int *fi, FT_UInt idx)
340 {
341    RGBA_Font_Glyph *fg;
342    FT_Error error;
343    const FT_Int32 hintflags[3] =
344      { FT_LOAD_NO_HINTING, FT_LOAD_FORCE_AUTOHINT, FT_LOAD_NO_AUTOHINT };
345    static FT_Matrix transform = {0x10000, 0x05000, 0x0000, 0x10000}; // about 12 degree.
346
347    evas_common_font_int_promote(fi);
348    if (fi->fash)
349      {
350         fg = _fash_gl_find(fi->fash, idx);
351         if (fg == (void *)(-1)) return NULL;
352         else if (fg) return fg;
353      }
354
355 //   fg = eina_hash_find(fi->glyphs, &hindex);
356 //   if (fg) return fg;
357
358    evas_common_font_int_reload(fi);
359    FTLOCK();
360    error = FT_Load_Glyph(fi->src->ft.face, idx,
361                          FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP |
362                          hintflags[fi->hinting]);
363    FTUNLOCK();
364    if (error)
365      {
366         if (!fi->fash) fi->fash = _fash_gl_new();
367         if (fi->fash) _fash_gl_add(fi->fash, idx, (void *)(-1));
368         return NULL;
369      }
370
371    /* Transform the outline of Glyph according to runtime_rend. */
372    if (fi->runtime_rend & FONT_REND_SLANT)
373       FT_Outline_Transform(&fi->src->ft.face->glyph->outline, &transform);
374    /* Embolden the outline of Glyph according to rundtime_rend. */
375    if (fi->runtime_rend & FONT_REND_WEIGHT)
376       FT_Outline_Embolden(&fi->src->ft.face->glyph->outline,
377             (fi->src->ft.face->size->metrics.x_ppem * 5 * 64) / 100);
378
379    fg = malloc(sizeof(struct _RGBA_Font_Glyph));
380    if (!fg) return NULL;
381    memset(fg, 0, (sizeof(struct _RGBA_Font_Glyph)));
382
383    FTLOCK();
384    error = FT_Get_Glyph(fi->src->ft.face->glyph, &(fg->glyph));
385    FTUNLOCK();
386    if (error)
387      {
388         free(fg);
389         if (!fi->fash) fi->fash = _fash_gl_new();
390         if (fi->fash) _fash_gl_add(fi->fash, idx, (void *)(-1));
391         return NULL;
392      }
393
394      {
395         FT_BBox outbox;
396         FT_Outline_Get_CBox(&fi->src->ft.face->glyph->outline, &outbox);
397         fg->width = EVAS_FONT_ROUND_26_6_TO_INT(outbox.xMax - outbox.xMin);
398         fg->x_bear = EVAS_FONT_ROUND_26_6_TO_INT(outbox.xMin);
399      }
400
401    fg->index = idx;
402    fg->fi = fi;
403
404    if (!fi->fash) fi->fash = _fash_gl_new();
405    if (fi->fash) _fash_gl_add(fi->fash, idx, fg);
406
407 //   eina_hash_direct_add(fi->glyphs, &fg->index, fg);
408    return fg;
409 }
410
411 EAPI Eina_Bool
412 evas_common_font_int_cache_glyph_render(RGBA_Font_Glyph *fg)
413 {
414    int size;
415    FT_Error error;
416    RGBA_Font_Int *fi = fg->fi;
417    FTLOCK();
418    error = FT_Glyph_To_Bitmap(&(fg->glyph), FT_RENDER_MODE_NORMAL, 0, 1);
419    if (error)
420      {
421         FT_Done_Glyph(fg->glyph);
422         FTUNLOCK();
423         free(fg);
424         if (!fi->fash) fi->fash = _fash_gl_new();
425         if (fi->fash) _fash_gl_add(fi->fash, fg->index, (void *)(-1));
426         return EINA_FALSE;
427      }
428    FTUNLOCK();
429
430    fg->glyph_out = (FT_BitmapGlyph)fg->glyph;
431    /* This '+ 200' is just an estimation of how much memory freetype will use
432     * on it's size. This value is not really used anywhere in code - it's
433     * only for statistics. */
434    size = sizeof(RGBA_Font_Glyph) + sizeof(Eina_List) +
435     (fg->glyph_out->bitmap.width * fg->glyph_out->bitmap.rows) + 200;
436    fi->usage += size;
437    if (fi->inuse) evas_common_font_int_use_increase(size);
438
439    return EINA_TRUE;
440 }
441
442 typedef struct _Font_Char_Index Font_Char_Index;
443 struct _Font_Char_Index
444 {
445    FT_UInt index;
446    Eina_Unicode gl;
447 };
448
449 EAPI FT_UInt
450 evas_common_get_char_index(RGBA_Font_Int* fi, Eina_Unicode gl)
451 {
452    Font_Char_Index result;
453    //FT_UInt ret;
454
455 #ifdef HAVE_PTHREAD
456 ///   pthread_mutex_lock(&fi->ft_mutex);
457 #endif
458
459 //   result = eina_hash_find(fi->indexes, &gl);
460 //   if (result) goto on_correct;
461 //
462 //   result = malloc(sizeof (Font_Char_Index));
463 //   if (!result)
464 //     {
465 //#ifdef HAVE_PTHREAD
466 //      pthread_mutex_unlock(&fi->ft_mutex);
467 //#endif
468 //      return FT_Get_Char_Index(fi->src->ft.face, gl);
469 //     }
470
471    evas_common_font_int_reload(fi);
472    FTLOCK();
473    result.index = FT_Get_Char_Index(fi->src->ft.face, gl);
474    FTUNLOCK();
475    result.gl = gl;
476
477 //   eina_hash_direct_add(fi->indexes, &result->gl, result);
478 //
479 // on_correct:
480 #ifdef HAVE_PTHREAD
481 //   pthread_mutex_unlock(&fi->ft_mutex);
482 #endif
483    return result.index;
484 }
485
486 EAPI int
487 evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, Eina_Unicode gl)
488 {
489    Eina_List *l;
490
491    if (fn->fash)
492      {
493         Fash_Item_Index_Map *fm = _fash_int_find(fn->fash, gl);
494         if (fm)
495           {
496              if (fm->fint)
497                {
498                   *fi_ret = fm->fint;
499                   return fm->index;
500                }
501              else if (fm->index == -1) return 0;
502           }
503      }
504
505    for (l = fn->fonts; l; l = l->next)
506      {
507         RGBA_Font_Int *fi;
508         int idx;
509
510         fi = l->data;
511
512 #if 0 /* FIXME: charmap user is disabled and use a deprecated data type. */
513 /*        
514         if (fi->src->charmap) // Charmap loaded, FI/FS blank
515           {
516              idx = evas_array_hash_search(fi->src->charmap, gl);
517              if (idx != 0)
518                {
519                   evas_common_font_source_load_complete(fi->src);
520                   evas_common_font_int_load_complete(fi);
521
522                   evas_array_hash_free(fi->src->charmap);
523                   fi->src->charmap = NULL;
524
525                   *fi_ret = fi;
526                   return idx;
527                }
528            }
529         else
530 */
531 #endif
532         if (!fi->src->ft.face) /* Charmap not loaded, FI/FS blank */
533           {
534              evas_common_font_int_reload(fi);
535           }
536         if (fi->src->ft.face)
537           {
538              idx = evas_common_get_char_index(fi, gl);
539              if (idx != 0)
540                {
541                   if (!fi->ft.size)
542                     evas_common_font_int_load_complete(fi);
543                   if (!fn->fash) fn->fash = _fash_int_new();
544                   if (fn->fash) _fash_int_add(fn->fash, gl, fi, idx);
545                   *fi_ret = fi;
546                   return idx;
547                }
548              else
549                {
550                   if (!fn->fash) fn->fash = _fash_int_new();
551                   if (fn->fash) _fash_int_add(fn->fash, gl, NULL, -1);
552                }
553           }
554      }
555    *fi_ret = NULL;
556    return 0;
557 }