move around - flatter.
[profile/ivi/evas.git] / src / lib / engines / common / evas_font_query.c
1 #include "evas_common.h"
2
3 /* string extents */
4 EAPI void
5 evas_common_font_query_size(RGBA_Font *fn, const char *text, int *w, int *h)
6 {
7    int use_kerning;
8    int pen_x, pen_y;
9    int start_x, end_x;
10    int chr;
11    FT_UInt prev_index;
12    RGBA_Font_Int *fi;
13    FT_Face pface = NULL;
14
15    fi = fn->fonts->data;
16
17    start_x = 0;
18    end_x = 0;
19
20    pen_x = 0;
21    pen_y = 0;
22    evas_common_font_size_use(fn);
23    use_kerning = FT_HAS_KERNING(fi->src->ft.face);
24    prev_index = 0;
25    for (chr = 0; text[chr];)
26      {
27         FT_UInt index;
28         RGBA_Font_Glyph *fg;
29         int chr_x, chr_y, chr_w;
30         int gl, kern;
31
32         gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr);
33         if (gl == 0) break;
34         index = evas_common_font_glyph_search(fn, &fi, gl);
35         /* hmmm kerning means i can't sanely do my own cached metric tables! */
36         /* grrr - this means font face sharing is kinda... not an option if */
37         /* you want performance */
38         kern = 0;
39         if ((use_kerning) && (prev_index) && (index) &&
40             (pface == fi->src->ft.face))
41           {
42              FT_Vector delta;
43
44              if (FT_Get_Kerning(fi->src->ft.face, prev_index, index,
45                                 ft_kerning_default, &delta) == 0)
46                {
47                   kern = delta.x >> 6;
48                   pen_x += kern;
49                }
50           }
51         pface = fi->src->ft.face;
52         fg = evas_common_font_int_cache_glyph_get(fi, index);
53         if (!fg) continue;
54
55         if (kern < 0) kern = 0;
56         chr_x = ((pen_x - kern) + (fg->glyph_out->left));
57         chr_y = (pen_y + (fg->glyph_out->top));
58 //      chr_w = fg->glyph_out->bitmap.width;
59         chr_w = fg->glyph_out->bitmap.width + kern;
60           {
61              int advw;
62
63              advw = ((fg->glyph->advance.x + (kern << 16)) >> 16);
64              if (chr_w < advw) chr_w = advw;
65           }
66
67         if ((!prev_index) && (chr_x < 0))
68           start_x = chr_x;
69         if ((chr_x + chr_w) > end_x)
70           end_x = chr_x + chr_w;
71
72         pen_x += fg->glyph->advance.x >> 16;
73         prev_index = index;
74      }
75    if (w) *w = end_x - start_x;
76    if (h) *h = evas_common_font_max_ascent_get(fn) + evas_common_font_max_descent_get(fn);
77 }
78
79 /* text x inset */
80 EAPI int
81 evas_common_font_query_inset(RGBA_Font *fn, const char *text)
82 {
83    FT_UInt index;
84    RGBA_Font_Glyph *fg;
85    int chr;
86    int gl;
87    RGBA_Font_Int *fi;
88
89    fi = fn->fonts->data;
90
91    chr = 0;
92    if (!text[0]) return 0;
93    gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr);
94    if (gl == 0) return 0;
95    evas_common_font_size_use(fn);
96    index = evas_common_font_glyph_search(fn, &fi, gl);
97    fg = evas_common_font_int_cache_glyph_get(fi, index);
98    if (!fg) return 0;
99 /*   
100    printf("fg->glyph_out->left = %i\n"
101           "fi->src->ft.face->glyph->bitmap_left = %i\n"
102           "fi->src->ft.face->glyph->metrics.horiBearingX = %i\n"
103           "fi->src->ft.face->glyph->metrics.horiBearingY = %i\n"
104           "fi->src->ft.face->glyph->metrics.horiAdvance = %i\n"
105           ,
106           (int)fg->glyph_out->left, 
107           (int)fi->src->ft.face->glyph->bitmap_left,
108           (int)fi->src->ft.face->glyph->metrics.horiBearingX >> 6,
109           (int)fi->src->ft.face->glyph->metrics.horiBearingY >> 6,
110           (int)fi->src->ft.face->glyph->metrics.horiAdvance >> 6
111           );
112  */
113    return fg->glyph_out->left;
114 }
115
116 /* h & v advance */
117 EAPI void
118 evas_common_font_query_advance(RGBA_Font *fn, const char *text, int *h_adv, int *v_adv)
119 {
120    int use_kerning;
121    int pen_x, pen_y;
122    int start_x;
123    int chr;
124    FT_UInt prev_index;
125    RGBA_Font_Int *fi;
126    FT_Face pface = NULL;
127
128    fi = fn->fonts->data;
129
130    start_x = 0;
131    pen_x = 0;
132    pen_y = 0;
133    evas_common_font_size_use(fn);
134    use_kerning = FT_HAS_KERNING(fi->src->ft.face);
135    prev_index = 0;
136    for (chr = 0; text[chr];)
137      {
138         FT_UInt index;
139         RGBA_Font_Glyph *fg;
140         int chr_x, chr_y, chr_w;
141         int gl;
142
143         gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr);
144         if (gl == 0) break;
145         index = evas_common_font_glyph_search(fn, &fi, gl);
146         /* hmmm kerning means i can't sanely do my own cached metric tables! */
147         /* grrr - this means font face sharing is kinda... not an option if */
148         /* you want performance */
149         if ((use_kerning) && (prev_index) && (index) &&
150             (pface == fi->src->ft.face))
151           {
152              FT_Vector delta;
153
154              if (FT_Get_Kerning(fi->src->ft.face, prev_index, index,
155                                 ft_kerning_default, &delta) == 0)
156                pen_x += delta.x >> 6;
157           }
158         pface = fi->src->ft.face;
159         fg = evas_common_font_int_cache_glyph_get(fi, index);
160         if (!fg) continue;
161
162         chr_x = (pen_x + (fg->glyph_out->left));
163         chr_y = (pen_y + (fg->glyph_out->top));
164         chr_w = fg->glyph_out->bitmap.width;
165
166         pen_x += fg->glyph->advance.x >> 16;
167         prev_index = index;
168      }
169    if (v_adv) *v_adv = evas_common_font_get_line_advance(fn);
170    if (h_adv) *h_adv = pen_x - start_x;
171 }
172
173 /* x y w h for char at char pos */
174 EAPI int
175 evas_common_font_query_char_coords(RGBA_Font *fn, const char *text, int pos, int *cx, int *cy, int *cw, int *ch)
176 {
177    int use_kerning;
178    int pen_x, pen_y;
179    int prev_chr_end;
180    int chr;
181    int asc, desc;
182    FT_UInt prev_index;
183    RGBA_Font_Int *fi;
184    FT_Face pface = NULL;
185
186    fi = fn->fonts->data;
187
188    pen_x = 0;
189    pen_y = 0;
190    evas_common_font_size_use(fn);
191    use_kerning = FT_HAS_KERNING(fi->src->ft.face);
192    prev_index = 0;
193    prev_chr_end = 0;
194    asc = evas_common_font_max_ascent_get(fn);
195    desc = evas_common_font_max_descent_get(fn);
196    for (chr = 0; text[chr];)
197      {
198         int pchr;
199         FT_UInt index;
200         RGBA_Font_Glyph *fg;
201         int chr_x, chr_y, chr_w;
202         int gl, kern;
203
204         pchr = chr;
205         gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr);
206         if (gl == 0) break;
207         index = evas_common_font_glyph_search(fn, &fi, gl);
208         kern = 0;
209         /* hmmm kerning means i can't sanely do my own cached metric tables! */
210         /* grrr - this means font face sharing is kinda... not an option if */
211         /* you want performance */
212         if ((use_kerning) && (prev_index) && (index) &&
213             (pface == fi->src->ft.face))
214           {
215              FT_Vector delta;
216
217              if (FT_Get_Kerning(fi->src->ft.face, prev_index, index,
218                                 ft_kerning_default, &delta) == 0)
219                {
220                   kern = delta.x >> 6;
221                   pen_x += kern;
222                }
223           }
224         pface = fi->src->ft.face;
225         fg = evas_common_font_int_cache_glyph_get(fi, index);
226         if (!fg) continue;
227
228         if (kern < 0) kern = 0;
229         chr_x = ((pen_x - kern) + (fg->glyph_out->left));
230         chr_y = (pen_y + (fg->glyph_out->top));
231         chr_w = fg->glyph_out->bitmap.width + (kern);
232 /*      if (text[chr]) */
233           {
234              int advw;
235
236              advw = ((fg->glyph->advance.x + (kern << 16)) >> 16);
237              if (chr_w < advw) chr_w = advw;
238           }
239         if (chr_x > prev_chr_end)
240           {
241              chr_w += (chr_x - prev_chr_end);
242              chr_x = prev_chr_end;
243           }
244         if (pchr == pos)
245           {
246              if (cx) *cx = chr_x;
247              if (cy) *cy = -asc;
248              if (cw) *cw = chr_w;
249              if (ch) *ch = asc + desc;
250              return 1;
251           }
252         prev_chr_end = chr_x + chr_w;
253         pen_x += fg->glyph->advance.x >> 16;
254         prev_index = index;
255      }
256    return 0;
257 }
258
259 /* char pos of text at xy pos */
260 EAPI int
261 evas_common_font_query_text_at_pos(RGBA_Font *fn, const char *text, int x, int y, int *cx, int *cy, int *cw, int *ch)
262 {
263    int use_kerning;
264    int pen_x, pen_y;
265    int prev_chr_end;
266    int chr;
267    int asc, desc;
268    FT_UInt prev_index;
269    RGBA_Font_Int *fi;
270    FT_Face pface = NULL;
271
272    fi = fn->fonts->data;
273
274    pen_x = 0;
275    pen_y = 0;
276    evas_common_font_size_use(fn);
277    use_kerning = FT_HAS_KERNING(fi->src->ft.face);
278    prev_index = 0;
279    prev_chr_end = 0;
280    asc = evas_common_font_max_ascent_get(fn);
281    desc = evas_common_font_max_descent_get(fn);
282    for (chr = 0; text[chr];)
283      {
284         int pchr;
285         FT_UInt index;
286         RGBA_Font_Glyph *fg;
287         int chr_x, chr_y, chr_w;
288         int gl, kern;
289
290         pchr = chr;
291         gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr);
292         if (gl == 0) break;
293         index = evas_common_font_glyph_search(fn, &fi, gl);
294         kern = 0;
295         /* hmmm kerning means i can't sanely do my own cached metric tables! */
296         /* grrr - this means font face sharing is kinda... not an option if */
297         /* you want performance */
298         if ((use_kerning) && (prev_index) && (index) &&
299             (pface == fi->src->ft.face))
300           {
301              FT_Vector delta;
302
303              if (FT_Get_Kerning(fi->src->ft.face, prev_index, index,
304                                 ft_kerning_default, &delta) == 0)
305                {
306                   kern = delta.x >> 6;
307                   pen_x += kern;
308                }
309           }
310         pface = fi->src->ft.face;
311         fg = evas_common_font_int_cache_glyph_get(fi, index);
312         if (!fg) continue;
313
314         if (kern < 0) kern = 0;
315         chr_x = ((pen_x - kern) + (fg->glyph_out->left));
316         chr_y = (pen_y + (fg->glyph_out->top));
317         chr_w = fg->glyph_out->bitmap.width + kern;
318 /*      if (text[chr]) */
319           {
320              int advw;
321
322              advw = ((fg->glyph->advance.x + (kern << 16)) >> 16);
323              if (chr_w < advw) chr_w = advw;
324           }
325         if (chr_x > prev_chr_end)
326           {
327              chr_w += (chr_x - prev_chr_end);
328              chr_x = prev_chr_end;
329           }
330         if ((x >= chr_x) && (x <= (chr_x + chr_w)) &&
331             (y >= -asc) && (y <= desc))
332           {
333              if (cx) *cx = chr_x;
334              if (cy) *cy = -asc;
335              if (cw) *cw = chr_w;
336              if (ch) *ch = asc + desc;
337              return pchr;
338           }
339         prev_chr_end = chr_x + chr_w;
340         pen_x += fg->glyph->advance.x >> 16;
341         prev_index = index;
342      }
343    return -1;
344 }