Evas: Multiple changes that all relate to the Harfbuzz integration:
[framework/uifw/evas.git] / src / lib / engines / common / evas_font_ot.c
1 #include "evas_font_ot.h"
2
3 #ifdef OT_SUPPORT
4 # include <hb.h>
5 # include <hb-ft.h>
6 #endif
7
8 #include "evas_common.h"
9
10 #include <Eina.h>
11 #include "evas_font_private.h"
12
13 EAPI Eina_Bool
14 evas_common_font_ot_is_enabled(void)
15 {
16 #ifdef OT_SUPPORT
17    static int ret = -1;
18    const char *env;
19    if (ret != -1)
20      {
21         return ret;
22      }
23
24    env = getenv("EVAS_USE_OT");
25    if (env && atoi(env))
26      {
27         ret = EINA_TRUE;
28         return ret;
29      }
30 #endif
31    return EINA_FALSE;
32 }
33
34
35 #ifdef OT_SUPPORT
36 static void
37 _evas_common_font_ot_shape(hb_buffer_t *buffer, FT_Face face)
38 {
39    hb_face_t   *hb_face;
40    hb_font_t   *hb_font;
41
42    hb_face = hb_ft_face_create(face, NULL);
43    hb_font = hb_ft_font_create(face, NULL);
44
45    hb_shape(hb_font, hb_face, buffer, NULL, 0);
46    hb_font_destroy(hb_font);
47    hb_face_destroy(hb_face);
48 }
49
50 EAPI Eina_Bool
51 evas_common_font_ot_populate_text_props(void *_fn, const Eina_Unicode *text,
52       Evas_Text_Props *props, int len)
53 {
54    RGBA_Font *fn = (RGBA_Font *) _fn;
55    RGBA_Font_Int *fi;
56    hb_buffer_t *buffer;
57    hb_glyph_position_t *positions;
58    hb_glyph_info_t *infos;
59    int slen;
60    unsigned int i;
61    if (!evas_common_font_ot_is_enabled()) return EINA_TRUE;
62    if (props->ot_data)
63      {
64         evas_common_font_ot_props_unref(props->ot_data);
65      }
66    props->ot_data = calloc(1, sizeof(Evas_Font_OT_Data));
67    props->ot_data->refcount = 1;
68
69    fi = fn->fonts->data;
70    if (fi->src->current_size != fi->size)
71      {
72         FTLOCK();
73         FT_Activate_Size(fi->ft.size);
74         FTUNLOCK();
75         fi->src->current_size = fi->size;
76      }
77    /* Load the font needed for this script */
78    evas_common_font_glyph_search(fn, &fi, *text);
79
80    if (len < 0)
81      {
82         slen = eina_unicode_strlen(text);
83      }
84    else
85      {
86         slen = len;
87      }
88
89    buffer = hb_buffer_create(slen);
90    hb_buffer_set_unicode_funcs(buffer, evas_common_language_unicode_funcs_get());
91    hb_buffer_set_language(buffer, hb_language_from_string(
92             evas_common_language_from_locale_get()));
93    hb_buffer_set_script(buffer, props->script);
94    hb_buffer_set_direction(buffer,
95          (props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) ?
96          HB_DIRECTION_RTL : HB_DIRECTION_LTR);
97    /* FIXME: add run-time conversions if needed, which is very unlikely */
98    hb_buffer_add_utf32(buffer, (const uint32_t *) text, slen, 0, slen);
99
100    _evas_common_font_ot_shape(buffer, fi->src->ft.face);
101
102    props->ot_data->len = hb_buffer_get_length(buffer);
103    props->ot_data->items = calloc(props->ot_data->len,
104          sizeof(Evas_Font_OT_Data_Item));
105    positions = hb_buffer_get_glyph_positions(buffer);
106    infos = hb_buffer_get_glyph_infos(buffer);
107    for (i = 0 ; i < props->ot_data->len ; i++)
108      {
109         props->ot_data->items[i].index = infos[i].codepoint;
110         props->ot_data->items[i].source_pos = infos[i].cluster;
111         props->ot_data->items[i].x_advance = positions[i].x_advance;
112         props->ot_data->items[i].x_offset = positions[i].x_offset;
113         props->ot_data->items[i].y_offset = positions[i].y_offset;
114      }
115
116    hb_buffer_destroy(buffer);
117
118    return EINA_FALSE;
119 }
120
121 EAPI void
122 evas_common_font_ot_props_ref(Evas_Font_OT_Data *data)
123 {
124    data->refcount++;
125 }
126
127 EAPI void
128 evas_common_font_ot_props_unref(Evas_Font_OT_Data *data)
129 {
130    OTLOCK();
131    if (--data->refcount == 0)
132      {
133         if (data->items)
134           free(data->items);
135         free(data);
136      }
137    OTUNLOCK();
138 }
139 #endif
140