1 #include "evas_common.h"
2 #include "evas_private.h"
4 #include "evas_font_private.h"
8 FT_Library evas_ft_lib = 0;
9 static int initialised = 0;
11 LK(lock_font_draw); // for freetype2 API calls
12 LK(lock_bidi); // for evas bidi internal usage.
13 LK(lock_ot); // for evas bidi internal usage.
16 evas_common_font_init(void)
22 if (initialised != 1) return;
23 error = FT_Init_FreeType(&evas_ft_lib);
25 evas_common_font_load_init();
26 evas_common_font_draw_init();
27 s = getenv("EVAS_FONT_DPI");
32 if (dpi > 0) evas_common_font_dpi_set(dpi);
40 evas_common_font_shutdown(void)
44 if (initialised < 1) return;
46 if (initialised != 0) return;
52 evas_common_font_load_shutdown();
53 evas_common_font_cache_set(0);
54 evas_common_font_flush();
56 error = FT_Done_FreeType(evas_ft_lib);
57 #ifdef EVAS_FRAME_QUEUING
58 evas_common_font_draw_finish();
64 evas_common_font_font_all_unload(void)
66 evas_common_font_all_clear();
70 evas_common_font_ascent_get(RGBA_Font *fn)
75 // evas_common_font_size_use(fn);
80 EINA_LIST_FOREACH(fn->fonts, l, fi)
82 if (!fi->src->ft.face) continue;
83 if (fi->src->current_size != fi->size)
86 FT_Activate_Size(fi->ft.size);
88 fi->src->current_size = fi->size;
90 val = (int)fi->src->ft.face->size->metrics.ascender;
91 if (fi->src->ft.face->units_per_EM == 0)
93 dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
94 ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
95 printf(" ==== %p: %i\n", fi, ret);
100 evas_common_font_int_reload(fi);
101 if (fi->src->current_size != fi->size)
104 FT_Activate_Size(fi->ft.size);
106 fi->src->current_size = fi->size;
108 if (!FT_IS_SCALABLE(fi->src->ft.face))
110 WRN("NOT SCALABLE!");
112 val = (int)fi->src->ft.face->size->metrics.ascender;
114 // printf("%i | %i\n", val, val >> 6);
115 // if (fi->src->ft.face->units_per_EM == 0)
117 // dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
118 // ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
123 evas_common_font_descent_get(RGBA_Font *fn)
128 // evas_common_font_size_use(fn);
129 fi = fn->fonts->data;
130 evas_common_font_int_reload(fi);
131 if (fi->src->current_size != fi->size)
134 FT_Activate_Size(fi->ft.size);
136 fi->src->current_size = fi->size;
138 val = -(int)fi->src->ft.face->size->metrics.descender;
140 // if (fi->src->ft.face->units_per_EM == 0)
142 // dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
143 // ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
148 evas_common_font_max_ascent_get(RGBA_Font *fn)
154 // evas_common_font_size_use(fn);
155 fi = fn->fonts->data;
156 evas_common_font_int_reload(fi);
157 if (fi->src->current_size != fi->size)
160 FT_Activate_Size(fi->ft.size);
162 fi->src->current_size = fi->size;
164 val = (int)fi->src->ft.face->bbox.yMax;
165 if (fi->src->ft.face->units_per_EM == 0)
167 dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
168 ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
173 evas_common_font_max_descent_get(RGBA_Font *fn)
179 // evas_common_font_size_use(fn);
180 fi = fn->fonts->data;
181 evas_common_font_int_reload(fi);
182 if (fi->src->current_size != fi->size)
185 FT_Activate_Size(fi->ft.size);
187 fi->src->current_size = fi->size;
189 val = -(int)fi->src->ft.face->bbox.yMin;
190 if (fi->src->ft.face->units_per_EM == 0)
192 dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
193 ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
198 evas_common_font_get_line_advance(RGBA_Font *fn)
203 // evas_common_font_size_use(fn);
204 fi = fn->fonts->data;
205 evas_common_font_int_reload(fi);
206 if (fi->src->current_size != fi->size)
209 FT_Activate_Size(fi->ft.size);
211 fi->src->current_size = fi->size;
213 val = (int)fi->src->ft.face->size->metrics.height;
214 if (fi->src->ft.face->units_per_EM == 0)
217 // dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM;
218 // ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv);
222 /* Set of common functions that are used in a couple of places. */
225 _fash_int2_free(Fash_Int_Map2 *fash)
229 for (i = 0; i < 256; i++) if (fash->bucket[i]) free(fash->bucket[i]);
234 _fash_int_free(Fash_Int *fash)
238 for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_int2_free(fash->bucket[i]);
245 Fash_Int *fash = calloc(1, sizeof(Fash_Int));
246 fash->freeme = _fash_int_free;
250 static Fash_Item_Index_Map *
251 _fash_int_find(Fash_Int *fash, int item)
255 // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
256 grp = (item >> 16) & 0xff;
257 maj = (item >> 8) & 0xff;
259 if (!fash->bucket[grp]) return NULL;
260 if (!fash->bucket[grp]->bucket[maj]) return NULL;
261 return &(fash->bucket[grp]->bucket[maj]->item[min]);
265 _fash_int_add(Fash_Int *fash, int item, RGBA_Font_Int *fint, int idx)
269 // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
270 grp = (item >> 16) & 0xff;
271 maj = (item >> 8) & 0xff;
273 if (!fash->bucket[grp])
274 fash->bucket[grp] = calloc(1, sizeof(Fash_Int_Map2));
275 EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]);
276 if (!fash->bucket[grp]->bucket[maj])
277 fash->bucket[grp]->bucket[maj] = calloc(1, sizeof(Fash_Int_Map));
278 EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]->bucket[maj]);
279 fash->bucket[grp]->bucket[maj]->item[min].fint = fint;
280 fash->bucket[grp]->bucket[maj]->item[min].index = idx;
284 _fash_gl2_free(Fash_Glyph_Map2 *fash)
288 for (i = 0; i < 256; i++) if (fash->bucket[i]) free(fash->bucket[i]);
293 _fash_gl_free(Fash_Glyph *fash)
297 for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_gl2_free(fash->bucket[i]);
304 Fash_Glyph *fash = calloc(1, sizeof(Fash_Glyph));
305 fash->freeme = _fash_gl_free;
309 static RGBA_Font_Glyph *
310 _fash_gl_find(Fash_Glyph *fash, int item)
314 // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
315 grp = (item >> 16) & 0xff;
316 maj = (item >> 8) & 0xff;
318 if (!fash->bucket[grp]) return NULL;
319 if (!fash->bucket[grp]->bucket[maj]) return NULL;
320 return fash->bucket[grp]->bucket[maj]->item[min];
324 _fash_gl_add(Fash_Glyph *fash, int item, RGBA_Font_Glyph *glyph)
328 // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
329 grp = (item >> 16) & 0xff;
330 maj = (item >> 8) & 0xff;
332 if (!fash->bucket[grp])
333 fash->bucket[grp] = calloc(1, sizeof(Fash_Glyph_Map2));
334 EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]);
335 if (!fash->bucket[grp]->bucket[maj])
336 fash->bucket[grp]->bucket[maj] = calloc(1, sizeof(Fash_Glyph_Map));
337 EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]->bucket[maj]);
338 fash->bucket[grp]->bucket[maj]->item[min] = glyph;
341 EAPI RGBA_Font_Glyph *
342 evas_common_font_int_cache_glyph_get(RGBA_Font_Int *fi, FT_UInt idx)
348 const FT_Int32 hintflags[3] =
349 { FT_LOAD_NO_HINTING, FT_LOAD_FORCE_AUTOHINT, FT_LOAD_NO_AUTOHINT };
350 static FT_Matrix transform = {0x10000, 0x05000, 0x0000, 0x10000}; // about 12 degree.
352 evas_common_font_int_promote(fi);
355 fg = _fash_gl_find(fi->fash, idx);
356 if (fg == (void *)(-1)) return NULL;
357 else if (fg) return fg;
360 hindex = idx + (fi->hinting * 500000000);
362 // fg = eina_hash_find(fi->glyphs, &hindex);
363 // if (fg) return fg;
365 evas_common_font_int_reload(fi);
367 error = FT_Load_Glyph(fi->src->ft.face, idx,
368 FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP |
369 hintflags[fi->hinting]);
373 if (!fi->fash) fi->fash = _fash_gl_new();
374 if (fi->fash) _fash_gl_add(fi->fash, idx, (void *)(-1));
378 /* Transform the outline of Glyph according to runtime_rend. */
379 if (fi->runtime_rend & FONT_REND_SLANT)
380 FT_Outline_Transform(&fi->src->ft.face->glyph->outline, &transform);
381 /* Embolden the outline of Glyph according to rundtime_rend. */
382 if (fi->runtime_rend & FONT_REND_WEIGHT)
383 FT_Outline_Embolden(&fi->src->ft.face->glyph->outline,
384 (fi->src->ft.face->size->metrics.x_ppem * 5 * 64) / 100);
386 fg = malloc(sizeof(struct _RGBA_Font_Glyph));
387 if (!fg) return NULL;
388 memset(fg, 0, (sizeof(struct _RGBA_Font_Glyph)));
391 error = FT_Get_Glyph(fi->src->ft.face->glyph, &(fg->glyph));
396 if (!fi->fash) fi->fash = _fash_gl_new();
397 if (fi->fash) _fash_gl_add(fi->fash, idx, (void *)(-1));
402 error = FT_Glyph_To_Bitmap(&(fg->glyph), FT_RENDER_MODE_NORMAL, 0, 1);
405 FT_Done_Glyph(fg->glyph);
408 if (!fi->fash) fi->fash = _fash_gl_new();
409 if (fi->fash) _fash_gl_add(fi->fash, idx, (void *)(-1));
414 fg->glyph_out = (FT_BitmapGlyph)fg->glyph;
418 if (!fi->fash) fi->fash = _fash_gl_new();
419 if (fi->fash) _fash_gl_add(fi->fash, idx, fg);
420 /* This '+ 200' is just an estimation of how much memory freetype will use
421 * on it's size. This value is not really used anywhere in code - it's
422 * only for statistics. */
423 size = sizeof(RGBA_Font_Glyph) + sizeof(Eina_List) +
424 (fg->glyph_out->bitmap.width * fg->glyph_out->bitmap.rows) + 200;
426 if (fi->inuse) evas_common_font_int_use_increase(size);
428 // eina_hash_direct_add(fi->glyphs, &fg->index, fg);
432 typedef struct _Font_Char_Index Font_Char_Index;
433 struct _Font_Char_Index
440 evas_common_get_char_index(RGBA_Font_Int* fi, Eina_Unicode gl)
442 Font_Char_Index result;
446 /// pthread_mutex_lock(&fi->ft_mutex);
449 // result = eina_hash_find(fi->indexes, &gl);
450 // if (result) goto on_correct;
452 // result = malloc(sizeof (Font_Char_Index));
455 //#ifdef HAVE_PTHREAD
456 // pthread_mutex_unlock(&fi->ft_mutex);
458 // return FT_Get_Char_Index(fi->src->ft.face, gl);
461 evas_common_font_int_reload(fi);
463 result.index = FT_Get_Char_Index(fi->src->ft.face, gl);
467 // eina_hash_direct_add(fi->indexes, &result->gl, result);
471 // pthread_mutex_unlock(&fi->ft_mutex);
477 evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, Eina_Unicode gl)
483 Fash_Item_Index_Map *fm = _fash_int_find(fn->fash, gl);
491 else if (fm->index == -1) return 0;
495 for (l = fn->fonts; l; l = l->next)
502 #if 0 /* FIXME: charmap user is disabled and use a deprecated data type. */
504 if (fi->src->charmap) // Charmap loaded, FI/FS blank
506 idx = evas_array_hash_search(fi->src->charmap, gl);
509 evas_common_font_source_load_complete(fi->src);
510 evas_common_font_int_load_complete(fi);
512 evas_array_hash_free(fi->src->charmap);
513 fi->src->charmap = NULL;
522 if (!fi->src->ft.face) /* Charmap not loaded, FI/FS blank */
524 evas_common_font_int_reload(fi);
526 if (fi->src->ft.face)
528 idx = evas_common_get_char_index(fi, gl);
532 evas_common_font_int_load_complete(fi);
533 if (!fn->fash) fn->fash = _fash_int_new();
534 if (fn->fash) _fash_int_add(fn->fash, gl, fi, idx);
540 if (!fn->fash) fn->fash = _fash_int_new();
541 if (fn->fash) _fash_int_add(fn->fash, gl, NULL, -1);