1 #include "evas_common.h"
2 #include "evas_private.h"
4 #include "evas_font_private.h"
10 FT_Library evas_ft_lib = 0;
11 static int initialised = 0;
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.
18 evas_common_font_init(void)
24 if (initialised != 1) return;
25 error = FT_Init_FreeType(&evas_ft_lib);
27 evas_common_font_load_init();
28 evas_common_font_draw_init();
29 s = getenv("EVAS_FONT_DPI");
34 if (dpi > 0) evas_common_font_dpi_set(dpi);
42 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 FT_Done_FreeType(evas_ft_lib);
61 evas_common_font_font_all_unload(void)
63 evas_common_font_all_clear();
67 evas_common_font_ascent_get(RGBA_Font *fn)
72 // evas_common_font_size_use(fn);
77 EINA_LIST_FOREACH(fn->fonts, l, fi)
79 if (!fi->src->ft.face) continue;
80 if (fi->src->current_size != fi->size)
83 FT_Activate_Size(fi->ft.size);
85 fi->src->current_size = fi->size;
87 val = (int)fi->src->ft.face->size->metrics.ascender;
88 if (fi->src->ft.face->units_per_EM == 0)
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);
97 evas_common_font_int_reload(fi);
98 if (fi->src->current_size != fi->size)
101 FT_Activate_Size(fi->ft.size);
103 fi->src->current_size = fi->size;
105 if (!FT_IS_SCALABLE(fi->src->ft.face))
107 WRN("NOT SCALABLE!");
109 val = (int)fi->src->ft.face->size->metrics.ascender;
111 // printf("%i | %i\n", val, val >> 6);
112 // if (fi->src->ft.face->units_per_EM == 0)
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);
120 evas_common_font_descent_get(RGBA_Font *fn)
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)
131 FT_Activate_Size(fi->ft.size);
133 fi->src->current_size = fi->size;
135 val = -(int)fi->src->ft.face->size->metrics.descender;
137 // if (fi->src->ft.face->units_per_EM == 0)
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);
145 evas_common_font_max_ascent_get(RGBA_Font *fn)
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)
157 FT_Activate_Size(fi->ft.size);
159 fi->src->current_size = fi->size;
161 val = (int)fi->src->ft.face->bbox.yMax;
162 if (fi->src->ft.face->units_per_EM == 0)
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);
170 evas_common_font_max_descent_get(RGBA_Font *fn)
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)
182 FT_Activate_Size(fi->ft.size);
184 fi->src->current_size = fi->size;
186 val = -(int)fi->src->ft.face->bbox.yMin;
187 if (fi->src->ft.face->units_per_EM == 0)
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);
195 evas_common_font_get_line_advance(RGBA_Font *fn)
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)
206 FT_Activate_Size(fi->ft.size);
208 fi->src->current_size = fi->size;
210 val = (int)fi->src->ft.face->size->metrics.height;
211 if (fi->src->ft.face->units_per_EM == 0)
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);
219 /* Set of common functions that are used in a couple of places. */
222 _fash_int2_free(Fash_Int_Map2 *fash)
226 for (i = 0; i < 256; i++) if (fash->bucket[i]) free(fash->bucket[i]);
231 _fash_int_free(Fash_Int *fash)
235 for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_int2_free(fash->bucket[i]);
242 Fash_Int *fash = calloc(1, sizeof(Fash_Int));
243 fash->freeme = _fash_int_free;
247 static Fash_Item_Index_Map *
248 _fash_int_find(Fash_Int *fash, int item)
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;
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]);
262 _fash_int_add(Fash_Int *fash, int item, RGBA_Font_Int *fint, int idx)
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;
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;
281 _fash_gl2_free(Fash_Glyph_Map2 *fash)
285 for (i = 0; i < 256; i++) if (fash->bucket[i]) free(fash->bucket[i]);
290 _fash_gl_free(Fash_Glyph *fash)
294 for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_gl2_free(fash->bucket[i]);
301 Fash_Glyph *fash = calloc(1, sizeof(Fash_Glyph));
302 fash->freeme = _fash_gl_free;
306 static RGBA_Font_Glyph *
307 _fash_gl_find(Fash_Glyph *fash, int item)
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;
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];
321 _fash_gl_add(Fash_Glyph *fash, int item, RGBA_Font_Glyph *glyph)
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;
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;
338 EAPI RGBA_Font_Glyph *
339 evas_common_font_int_cache_glyph_get(RGBA_Font_Int *fi, FT_UInt idx)
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.
347 evas_common_font_int_promote(fi);
350 fg = _fash_gl_find(fi->fash, idx);
351 if (fg == (void *)(-1)) return NULL;
352 else if (fg) return fg;
355 // fg = eina_hash_find(fi->glyphs, &hindex);
356 // if (fg) return fg;
358 evas_common_font_int_reload(fi);
360 error = FT_Load_Glyph(fi->src->ft.face, idx,
361 FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP |
362 hintflags[fi->hinting]);
366 if (!fi->fash) fi->fash = _fash_gl_new();
367 if (fi->fash) _fash_gl_add(fi->fash, idx, (void *)(-1));
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);
379 fg = malloc(sizeof(struct _RGBA_Font_Glyph));
380 if (!fg) return NULL;
381 memset(fg, 0, (sizeof(struct _RGBA_Font_Glyph)));
384 error = FT_Get_Glyph(fi->src->ft.face->glyph, &(fg->glyph));
389 if (!fi->fash) fi->fash = _fash_gl_new();
390 if (fi->fash) _fash_gl_add(fi->fash, idx, (void *)(-1));
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);
404 if (!fi->fash) fi->fash = _fash_gl_new();
405 if (fi->fash) _fash_gl_add(fi->fash, idx, fg);
407 // eina_hash_direct_add(fi->glyphs, &fg->index, fg);
412 evas_common_font_int_cache_glyph_render(RGBA_Font_Glyph *fg)
416 RGBA_Font_Int *fi = fg->fi;
418 error = FT_Glyph_To_Bitmap(&(fg->glyph), FT_RENDER_MODE_NORMAL, 0, 1);
421 FT_Done_Glyph(fg->glyph);
424 if (!fi->fash) fi->fash = _fash_gl_new();
425 if (fi->fash) _fash_gl_add(fi->fash, fg->index, (void *)(-1));
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;
437 if (fi->inuse) evas_common_font_int_use_increase(size);
442 typedef struct _Font_Char_Index Font_Char_Index;
443 struct _Font_Char_Index
450 evas_common_get_char_index(RGBA_Font_Int* fi, Eina_Unicode gl)
452 Font_Char_Index result;
456 /// pthread_mutex_lock(&fi->ft_mutex);
459 // result = eina_hash_find(fi->indexes, &gl);
460 // if (result) goto on_correct;
462 // result = malloc(sizeof (Font_Char_Index));
465 //#ifdef HAVE_PTHREAD
466 // pthread_mutex_unlock(&fi->ft_mutex);
468 // return FT_Get_Char_Index(fi->src->ft.face, gl);
471 evas_common_font_int_reload(fi);
473 result.index = FT_Get_Char_Index(fi->src->ft.face, gl);
477 // eina_hash_direct_add(fi->indexes, &result->gl, result);
481 // pthread_mutex_unlock(&fi->ft_mutex);
487 evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, Eina_Unicode gl)
493 Fash_Item_Index_Map *fm = _fash_int_find(fn->fash, gl);
501 else if (fm->index == -1) return 0;
505 for (l = fn->fonts; l; l = l->next)
512 #if 0 /* FIXME: charmap user is disabled and use a deprecated data type. */
514 if (fi->src->charmap) // Charmap loaded, FI/FS blank
516 idx = evas_array_hash_search(fi->src->charmap, gl);
519 evas_common_font_source_load_complete(fi->src);
520 evas_common_font_int_load_complete(fi);
522 evas_array_hash_free(fi->src->charmap);
523 fi->src->charmap = NULL;
532 if (!fi->src->ft.face) /* Charmap not loaded, FI/FS blank */
534 evas_common_font_int_reload(fi);
536 if (fi->src->ft.face)
538 idx = evas_common_get_char_index(fi, gl);
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);
550 if (!fn->fash) fn->fash = _fash_int_new();
551 if (fn->fash) _fash_int_add(fn->fash, gl, NULL, -1);