diff options
Diffstat (limited to 'libraries/evas/src/lib/engines/common/evas_font_ot.c')
-rw-r--r-- | libraries/evas/src/lib/engines/common/evas_font_ot.c | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/libraries/evas/src/lib/engines/common/evas_font_ot.c b/libraries/evas/src/lib/engines/common/evas_font_ot.c new file mode 100644 index 0000000..2912d55 --- /dev/null +++ b/libraries/evas/src/lib/engines/common/evas_font_ot.c | |||
@@ -0,0 +1,336 @@ | |||
1 | #include "evas_font_ot.h" | ||
2 | |||
3 | #ifdef USE_HARFBUZZ | ||
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 | #ifdef USE_HARFBUZZ | ||
14 | static const hb_script_t | ||
15 | _evas_script_to_harfbuzz[] = | ||
16 | { | ||
17 | HB_SCRIPT_COMMON, | ||
18 | HB_SCRIPT_INHERITED, | ||
19 | HB_SCRIPT_ARABIC, | ||
20 | HB_SCRIPT_ARMENIAN, | ||
21 | HB_SCRIPT_BENGALI, | ||
22 | HB_SCRIPT_BOPOMOFO, | ||
23 | HB_SCRIPT_CHEROKEE, | ||
24 | HB_SCRIPT_COPTIC, | ||
25 | HB_SCRIPT_CYRILLIC, | ||
26 | HB_SCRIPT_DESERET, | ||
27 | HB_SCRIPT_DEVANAGARI, | ||
28 | HB_SCRIPT_ETHIOPIC, | ||
29 | HB_SCRIPT_GEORGIAN, | ||
30 | HB_SCRIPT_GOTHIC, | ||
31 | HB_SCRIPT_GREEK, | ||
32 | HB_SCRIPT_GUJARATI, | ||
33 | HB_SCRIPT_GURMUKHI, | ||
34 | HB_SCRIPT_HAN, | ||
35 | HB_SCRIPT_HANGUL, | ||
36 | HB_SCRIPT_HEBREW, | ||
37 | HB_SCRIPT_HIRAGANA, | ||
38 | HB_SCRIPT_KANNADA, | ||
39 | HB_SCRIPT_KATAKANA, | ||
40 | HB_SCRIPT_KHMER, | ||
41 | HB_SCRIPT_LAO, | ||
42 | HB_SCRIPT_LATIN, | ||
43 | HB_SCRIPT_MALAYALAM, | ||
44 | HB_SCRIPT_MONGOLIAN, | ||
45 | HB_SCRIPT_MYANMAR, | ||
46 | HB_SCRIPT_OGHAM, | ||
47 | HB_SCRIPT_OLD_ITALIC, | ||
48 | HB_SCRIPT_ORIYA, | ||
49 | HB_SCRIPT_RUNIC, | ||
50 | HB_SCRIPT_SINHALA, | ||
51 | HB_SCRIPT_SYRIAC, | ||
52 | HB_SCRIPT_TAMIL, | ||
53 | HB_SCRIPT_TELUGU, | ||
54 | HB_SCRIPT_THAANA, | ||
55 | HB_SCRIPT_THAI, | ||
56 | HB_SCRIPT_TIBETAN, | ||
57 | HB_SCRIPT_CANADIAN_ABORIGINAL, | ||
58 | HB_SCRIPT_YI, | ||
59 | HB_SCRIPT_TAGALOG, | ||
60 | HB_SCRIPT_HANUNOO, | ||
61 | HB_SCRIPT_BUHID, | ||
62 | HB_SCRIPT_TAGBANWA, | ||
63 | |||
64 | /* Unicode-4.0 additions */ | ||
65 | HB_SCRIPT_BRAILLE, | ||
66 | HB_SCRIPT_CYPRIOT, | ||
67 | HB_SCRIPT_LIMBU, | ||
68 | HB_SCRIPT_OSMANYA, | ||
69 | HB_SCRIPT_SHAVIAN, | ||
70 | HB_SCRIPT_LINEAR_B, | ||
71 | HB_SCRIPT_TAI_LE, | ||
72 | HB_SCRIPT_UGARITIC, | ||
73 | |||
74 | /* Unicode-4.1 additions */ | ||
75 | HB_SCRIPT_NEW_TAI_LUE, | ||
76 | HB_SCRIPT_BUGINESE, | ||
77 | HB_SCRIPT_GLAGOLITIC, | ||
78 | HB_SCRIPT_TIFINAGH, | ||
79 | HB_SCRIPT_SYLOTI_NAGRI, | ||
80 | HB_SCRIPT_OLD_PERSIAN, | ||
81 | HB_SCRIPT_KHAROSHTHI, | ||
82 | |||
83 | /* Unicode-5.0 additions */ | ||
84 | HB_SCRIPT_UNKNOWN, | ||
85 | HB_SCRIPT_BALINESE, | ||
86 | HB_SCRIPT_CUNEIFORM, | ||
87 | HB_SCRIPT_PHOENICIAN, | ||
88 | HB_SCRIPT_PHAGS_PA, | ||
89 | HB_SCRIPT_NKO, | ||
90 | |||
91 | /* Unicode-5.1 additions */ | ||
92 | HB_SCRIPT_KAYAH_LI, | ||
93 | HB_SCRIPT_LEPCHA, | ||
94 | HB_SCRIPT_REJANG, | ||
95 | HB_SCRIPT_SUNDANESE, | ||
96 | HB_SCRIPT_SAURASHTRA, | ||
97 | HB_SCRIPT_CHAM, | ||
98 | HB_SCRIPT_OL_CHIKI, | ||
99 | HB_SCRIPT_VAI, | ||
100 | HB_SCRIPT_CARIAN, | ||
101 | HB_SCRIPT_LYCIAN, | ||
102 | HB_SCRIPT_LYDIAN, | ||
103 | |||
104 | /* Unicode-5.2 additions */ | ||
105 | HB_SCRIPT_AVESTAN, | ||
106 | HB_SCRIPT_BAMUM, | ||
107 | HB_SCRIPT_EGYPTIAN_HIEROGLYPHS, | ||
108 | HB_SCRIPT_IMPERIAL_ARAMAIC, | ||
109 | HB_SCRIPT_INSCRIPTIONAL_PAHLAVI, | ||
110 | HB_SCRIPT_INSCRIPTIONAL_PARTHIAN, | ||
111 | HB_SCRIPT_JAVANESE, | ||
112 | HB_SCRIPT_KAITHI, | ||
113 | HB_SCRIPT_TAI_THAM, | ||
114 | HB_SCRIPT_LISU, | ||
115 | HB_SCRIPT_MEETEI_MAYEK, | ||
116 | HB_SCRIPT_OLD_SOUTH_ARABIAN, | ||
117 | HB_SCRIPT_OLD_TURKIC, | ||
118 | HB_SCRIPT_SAMARITAN, | ||
119 | HB_SCRIPT_TAI_VIET, | ||
120 | |||
121 | /* Unicode-6.0 additions */ | ||
122 | HB_SCRIPT_BATAK, | ||
123 | HB_SCRIPT_BRAHMI, | ||
124 | HB_SCRIPT_MANDAIC | ||
125 | }; | ||
126 | #endif | ||
127 | |||
128 | #ifdef OT_SUPPORT | ||
129 | /* FIXME: doc. returns #items */ | ||
130 | EAPI int | ||
131 | evas_common_font_ot_cluster_size_get(const Evas_Text_Props *props, size_t char_index) | ||
132 | { | ||
133 | int i; | ||
134 | int items; | ||
135 | int left_bound, right_bound; | ||
136 | size_t base_cluster; | ||
137 | char_index += props->start; | ||
138 | base_cluster = EVAS_FONT_OT_POS_GET(props->info->ot[char_index]); | ||
139 | for (i = (int) char_index ; | ||
140 | (i >= (int) props->start) && | ||
141 | (EVAS_FONT_OT_POS_GET(props->info->ot[i]) == base_cluster) ; | ||
142 | i--) | ||
143 | ; | ||
144 | left_bound = i; | ||
145 | for (i = (int) char_index + 1; | ||
146 | (i < (int) (props->start + props->len)) && | ||
147 | (EVAS_FONT_OT_POS_GET(props->info->ot[i]) == base_cluster) ; | ||
148 | i++) | ||
149 | ; | ||
150 | right_bound = i; | ||
151 | |||
152 | if (right_bound == left_bound) | ||
153 | { | ||
154 | items = 1; | ||
155 | } | ||
156 | else if (props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) | ||
157 | { | ||
158 | if (left_bound < 0) | ||
159 | { | ||
160 | items = props->text_offset + props->text_len - base_cluster; | ||
161 | } | ||
162 | else | ||
163 | { | ||
164 | items = props->info->ot[left_bound].source_cluster - base_cluster; | ||
165 | } | ||
166 | } | ||
167 | else | ||
168 | { | ||
169 | if (right_bound >= (int) (props->text_offset + props->text_len)) | ||
170 | { | ||
171 | items = props->text_offset + props->text_len - base_cluster; | ||
172 | } | ||
173 | else | ||
174 | { | ||
175 | items = props->info->ot[right_bound].source_cluster - base_cluster; | ||
176 | } | ||
177 | } | ||
178 | return (items > 0) ? items : 1; | ||
179 | } | ||
180 | |||
181 | /* Harfbuzz font functions */ | ||
182 | |||
183 | static hb_position_t | ||
184 | _evas_common_font_ot_hb_get_glyph_advance(hb_font_t *font, | ||
185 | void *font_data, hb_codepoint_t glyph, | ||
186 | void *user_data) | ||
187 | { | ||
188 | /* Use our cache*/ | ||
189 | RGBA_Font_Int *fi = (RGBA_Font_Int *) font_data; | ||
190 | RGBA_Font_Glyph *fg; | ||
191 | (void) font; | ||
192 | (void) user_data; | ||
193 | fg = evas_common_font_int_cache_glyph_get(fi, glyph); | ||
194 | if (fg) | ||
195 | { | ||
196 | return fg->glyph->advance.x >> 10; | ||
197 | } | ||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | static hb_position_t | ||
202 | _evas_common_font_ot_hb_get_kerning(hb_font_t *font, void *font_data, | ||
203 | hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, void *user_data) | ||
204 | { | ||
205 | RGBA_Font_Int *fi = (RGBA_Font_Int *) font_data; | ||
206 | int kern; | ||
207 | (void) font; | ||
208 | (void) user_data; | ||
209 | if (evas_common_font_query_kerning(fi, first_glyph, second_glyph, &kern)) | ||
210 | return kern; | ||
211 | |||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | /* End of harfbuzz font funcs */ | ||
216 | |||
217 | static inline hb_font_funcs_t * | ||
218 | _evas_common_font_ot_font_funcs_get(void) | ||
219 | { | ||
220 | static hb_font_funcs_t *font_funcs = NULL; | ||
221 | if (!font_funcs) | ||
222 | { | ||
223 | font_funcs = hb_font_funcs_create(); | ||
224 | hb_font_funcs_set_glyph_h_advance_func(font_funcs, | ||
225 | _evas_common_font_ot_hb_get_glyph_advance, NULL, NULL); | ||
226 | hb_font_funcs_set_glyph_h_kerning_func(font_funcs, | ||
227 | _evas_common_font_ot_hb_get_kerning, NULL, NULL); | ||
228 | } | ||
229 | |||
230 | return font_funcs; | ||
231 | } | ||
232 | |||
233 | static inline hb_unicode_funcs_t * | ||
234 | _evas_common_font_ot_unicode_funcs_get(void) | ||
235 | { | ||
236 | static hb_unicode_funcs_t *unicode_funcs = NULL; | ||
237 | if (!unicode_funcs) | ||
238 | { | ||
239 | unicode_funcs = hb_unicode_funcs_get_default(); | ||
240 | } | ||
241 | |||
242 | return unicode_funcs; | ||
243 | } | ||
244 | |||
245 | static void | ||
246 | _evas_common_font_ot_shape(hb_buffer_t *buffer, RGBA_Font_Int *fi) | ||
247 | { | ||
248 | /* Create hb_font if not previously created */ | ||
249 | if (!fi->ft.hb_font) | ||
250 | { | ||
251 | hb_font_t *hb_ft_font; | ||
252 | |||
253 | hb_ft_font = hb_ft_font_create(fi->src->ft.face, NULL); | ||
254 | fi->ft.hb_font = hb_font_create_sub_font(hb_ft_font); | ||
255 | hb_font_destroy(hb_ft_font); | ||
256 | |||
257 | hb_font_set_funcs(fi->ft.hb_font, | ||
258 | _evas_common_font_ot_font_funcs_get(), fi, NULL); | ||
259 | } | ||
260 | |||
261 | hb_shape(fi->ft.hb_font, buffer, NULL, 0); | ||
262 | } | ||
263 | |||
264 | EAPI Eina_Bool | ||
265 | evas_common_font_ot_populate_text_props(const Eina_Unicode *text, | ||
266 | Evas_Text_Props *props, int len) | ||
267 | { | ||
268 | RGBA_Font_Int *fi; | ||
269 | hb_buffer_t *buffer; | ||
270 | hb_glyph_position_t *positions; | ||
271 | hb_glyph_info_t *infos; | ||
272 | int slen; | ||
273 | unsigned int i; | ||
274 | Evas_Font_Glyph_Info *gl_itr; | ||
275 | Evas_Font_OT_Info *ot_itr; | ||
276 | Evas_Coord pen_x = 0; | ||
277 | |||
278 | fi = props->font_instance; | ||
279 | |||
280 | if (len < 0) | ||
281 | { | ||
282 | slen = eina_unicode_strlen(text); | ||
283 | } | ||
284 | else | ||
285 | { | ||
286 | slen = len; | ||
287 | } | ||
288 | |||
289 | buffer = hb_buffer_create(); | ||
290 | hb_buffer_set_unicode_funcs(buffer, _evas_common_font_ot_unicode_funcs_get()); | ||
291 | hb_buffer_set_language(buffer, hb_language_from_string( | ||
292 | evas_common_language_from_locale_get(), -1)); | ||
293 | hb_buffer_set_script(buffer, _evas_script_to_harfbuzz[props->script]); | ||
294 | hb_buffer_set_direction(buffer, | ||
295 | (props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) ? | ||
296 | HB_DIRECTION_RTL : HB_DIRECTION_LTR); | ||
297 | /* FIXME: add run-time conversions if needed, which is very unlikely */ | ||
298 | hb_buffer_add_utf32(buffer, (const uint32_t *) text, slen, 0, slen); | ||
299 | |||
300 | _evas_common_font_ot_shape(buffer, fi); | ||
301 | |||
302 | props->len = hb_buffer_get_length(buffer); | ||
303 | props->info->ot = calloc(props->len, | ||
304 | sizeof(Evas_Font_OT_Info)); | ||
305 | props->info->glyph = calloc(props->len, | ||
306 | sizeof(Evas_Font_Glyph_Info)); | ||
307 | positions = hb_buffer_get_glyph_positions(buffer, NULL); | ||
308 | infos = hb_buffer_get_glyph_infos(buffer, NULL); | ||
309 | gl_itr = props->info->glyph; | ||
310 | ot_itr = props->info->ot; | ||
311 | for (i = 0 ; i < props->len ; i++) | ||
312 | { | ||
313 | Evas_Coord adv; | ||
314 | ot_itr->source_cluster = infos->cluster; | ||
315 | ot_itr->x_offset = positions->x_offset; | ||
316 | ot_itr->y_offset = positions->y_offset; | ||
317 | gl_itr->index = infos->codepoint; | ||
318 | adv = positions->x_advance; | ||
319 | |||
320 | pen_x += adv; | ||
321 | gl_itr->pen_after = EVAS_FONT_ROUND_26_6_TO_INT(pen_x); | ||
322 | |||
323 | ot_itr++; | ||
324 | gl_itr++; | ||
325 | infos++; | ||
326 | positions++; | ||
327 | } | ||
328 | |||
329 | hb_buffer_destroy(buffer); | ||
330 | evas_common_font_int_use_trim(); | ||
331 | |||
332 | return EINA_FALSE; | ||
333 | } | ||
334 | |||
335 | #endif | ||
336 | |||