diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/evas/src/lib/engines/common/evas_font_main.c | 545 |
1 files changed, 0 insertions, 545 deletions
diff --git a/libraries/evas/src/lib/engines/common/evas_font_main.c b/libraries/evas/src/lib/engines/common/evas_font_main.c deleted file mode 100644 index 7b3dabe..0000000 --- a/libraries/evas/src/lib/engines/common/evas_font_main.c +++ /dev/null | |||
@@ -1,545 +0,0 @@ | |||
1 | #include "evas_common.h" | ||
2 | #include "evas_private.h" | ||
3 | |||
4 | #include "evas_font_private.h" | ||
5 | |||
6 | #include FT_OUTLINE_H | ||
7 | |||
8 | FT_Library evas_ft_lib = 0; | ||
9 | static int initialised = 0; | ||
10 | |||
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. | ||
14 | |||
15 | EAPI void | ||
16 | evas_common_font_init(void) | ||
17 | { | ||
18 | int error; | ||
19 | const char *s; | ||
20 | |||
21 | initialised++; | ||
22 | if (initialised != 1) return; | ||
23 | error = FT_Init_FreeType(&evas_ft_lib); | ||
24 | if (error) return; | ||
25 | evas_common_font_load_init(); | ||
26 | evas_common_font_draw_init(); | ||
27 | s = getenv("EVAS_FONT_DPI"); | ||
28 | if (s) | ||
29 | { | ||
30 | int dpi = atoi(s); | ||
31 | |||
32 | if (dpi > 0) evas_common_font_dpi_set(dpi); | ||
33 | } | ||
34 | LKI(lock_font_draw); | ||
35 | LKI(lock_bidi); | ||
36 | LKI(lock_ot); | ||
37 | } | ||
38 | |||
39 | EAPI void | ||
40 | evas_common_font_shutdown(void) | ||
41 | { | ||
42 | if (initialised < 1) return; | ||
43 | initialised--; | ||
44 | if (initialised != 0) return; | ||
45 | |||
46 | LKD(lock_font_draw); | ||
47 | LKD(lock_bidi); | ||
48 | LKD(lock_ot); | ||
49 | |||
50 | evas_common_font_load_shutdown(); | ||
51 | evas_common_font_cache_set(0); | ||
52 | evas_common_font_flush(); | ||
53 | |||
54 | FT_Done_FreeType(evas_ft_lib); | ||
55 | #ifdef EVAS_FRAME_QUEUING | ||
56 | evas_common_font_draw_finish(); | ||
57 | #endif | ||
58 | evas_ft_lib = 0; | ||
59 | } | ||
60 | |||
61 | EAPI void | ||
62 | evas_common_font_font_all_unload(void) | ||
63 | { | ||
64 | evas_common_font_all_clear(); | ||
65 | } | ||
66 | |||
67 | EAPI int | ||
68 | evas_common_font_ascent_get(RGBA_Font *fn) | ||
69 | { | ||
70 | int val; | ||
71 | RGBA_Font_Int *fi; | ||
72 | |||
73 | // evas_common_font_size_use(fn); | ||
74 | #if 0 | ||
75 | { | ||
76 | Eina_List *l; | ||
77 | |||
78 | EINA_LIST_FOREACH(fn->fonts, l, fi) | ||
79 | { | ||
80 | if (!fi->src->ft.face) continue; | ||
81 | if (fi->src->current_size != fi->size) | ||
82 | { | ||
83 | FTLOCK(); | ||
84 | FT_Activate_Size(fi->ft.size); | ||
85 | FTUNLOCK(); | ||
86 | fi->src->current_size = fi->size; | ||
87 | } | ||
88 | val = (int)fi->src->ft.face->size->metrics.ascender; | ||
89 | if (fi->src->ft.face->units_per_EM == 0) | ||
90 | return val; | ||
91 | dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM; | ||
92 | ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv); | ||
93 | printf(" ==== %p: %i\n", fi, ret); | ||
94 | } | ||
95 | } | ||
96 | #endif | ||
97 | fi = fn->fonts->data; | ||
98 | evas_common_font_int_reload(fi); | ||
99 | if (fi->src->current_size != fi->size) | ||
100 | { | ||
101 | FTLOCK(); | ||
102 | FT_Activate_Size(fi->ft.size); | ||
103 | FTUNLOCK(); | ||
104 | fi->src->current_size = fi->size; | ||
105 | } | ||
106 | if (!FT_IS_SCALABLE(fi->src->ft.face)) | ||
107 | { | ||
108 | WRN("NOT SCALABLE!"); | ||
109 | } | ||
110 | val = (int)fi->src->ft.face->size->metrics.ascender; | ||
111 | return val >> 6; | ||
112 | // printf("%i | %i\n", val, val >> 6); | ||
113 | // if (fi->src->ft.face->units_per_EM == 0) | ||
114 | // return val; | ||
115 | // dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM; | ||
116 | // ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv); | ||
117 | // return ret; | ||
118 | } | ||
119 | |||
120 | EAPI int | ||
121 | evas_common_font_descent_get(RGBA_Font *fn) | ||
122 | { | ||
123 | int val; | ||
124 | RGBA_Font_Int *fi; | ||
125 | |||
126 | // evas_common_font_size_use(fn); | ||
127 | fi = fn->fonts->data; | ||
128 | evas_common_font_int_reload(fi); | ||
129 | if (fi->src->current_size != fi->size) | ||
130 | { | ||
131 | FTLOCK(); | ||
132 | FT_Activate_Size(fi->ft.size); | ||
133 | FTUNLOCK(); | ||
134 | fi->src->current_size = fi->size; | ||
135 | } | ||
136 | val = -(int)fi->src->ft.face->size->metrics.descender; | ||
137 | return val >> 6; | ||
138 | // if (fi->src->ft.face->units_per_EM == 0) | ||
139 | // return val; | ||
140 | // dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM; | ||
141 | // ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv); | ||
142 | // return ret; | ||
143 | } | ||
144 | |||
145 | EAPI int | ||
146 | evas_common_font_max_ascent_get(RGBA_Font *fn) | ||
147 | { | ||
148 | int val, dv; | ||
149 | int ret; | ||
150 | RGBA_Font_Int *fi; | ||
151 | |||
152 | // evas_common_font_size_use(fn); | ||
153 | fi = fn->fonts->data; | ||
154 | evas_common_font_int_reload(fi); | ||
155 | if (fi->src->current_size != fi->size) | ||
156 | { | ||
157 | FTLOCK(); | ||
158 | FT_Activate_Size(fi->ft.size); | ||
159 | FTUNLOCK(); | ||
160 | fi->src->current_size = fi->size; | ||
161 | } | ||
162 | val = (int)fi->src->ft.face->bbox.yMax; | ||
163 | if (fi->src->ft.face->units_per_EM == 0) | ||
164 | return val; | ||
165 | dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM; | ||
166 | ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv); | ||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | EAPI int | ||
171 | evas_common_font_max_descent_get(RGBA_Font *fn) | ||
172 | { | ||
173 | int val, dv; | ||
174 | int ret; | ||
175 | RGBA_Font_Int *fi; | ||
176 | |||
177 | // evas_common_font_size_use(fn); | ||
178 | fi = fn->fonts->data; | ||
179 | evas_common_font_int_reload(fi); | ||
180 | if (fi->src->current_size != fi->size) | ||
181 | { | ||
182 | FTLOCK(); | ||
183 | FT_Activate_Size(fi->ft.size); | ||
184 | FTUNLOCK(); | ||
185 | fi->src->current_size = fi->size; | ||
186 | } | ||
187 | val = -(int)fi->src->ft.face->bbox.yMin; | ||
188 | if (fi->src->ft.face->units_per_EM == 0) | ||
189 | return val; | ||
190 | dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM; | ||
191 | ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv); | ||
192 | return ret; | ||
193 | } | ||
194 | |||
195 | EAPI int | ||
196 | evas_common_font_get_line_advance(RGBA_Font *fn) | ||
197 | { | ||
198 | int val; | ||
199 | RGBA_Font_Int *fi; | ||
200 | |||
201 | // evas_common_font_size_use(fn); | ||
202 | fi = fn->fonts->data; | ||
203 | evas_common_font_int_reload(fi); | ||
204 | if (fi->src->current_size != fi->size) | ||
205 | { | ||
206 | FTLOCK(); | ||
207 | FT_Activate_Size(fi->ft.size); | ||
208 | FTUNLOCK(); | ||
209 | fi->src->current_size = fi->size; | ||
210 | } | ||
211 | val = (int)fi->src->ft.face->size->metrics.height; | ||
212 | if (fi->src->ft.face->units_per_EM == 0) | ||
213 | return val; | ||
214 | return val >> 6; | ||
215 | // dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM; | ||
216 | // ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv); | ||
217 | // return ret; | ||
218 | } | ||
219 | |||
220 | /* Set of common functions that are used in a couple of places. */ | ||
221 | |||
222 | static void | ||
223 | _fash_int2_free(Fash_Int_Map2 *fash) | ||
224 | { | ||
225 | int i; | ||
226 | |||
227 | for (i = 0; i < 256; i++) if (fash->bucket[i]) free(fash->bucket[i]); | ||
228 | free(fash); | ||
229 | } | ||
230 | |||
231 | static void | ||
232 | _fash_int_free(Fash_Int *fash) | ||
233 | { | ||
234 | int i; | ||
235 | |||
236 | for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_int2_free(fash->bucket[i]); | ||
237 | free(fash); | ||
238 | } | ||
239 | |||
240 | static Fash_Int * | ||
241 | _fash_int_new(void) | ||
242 | { | ||
243 | Fash_Int *fash = calloc(1, sizeof(Fash_Int)); | ||
244 | fash->freeme = _fash_int_free; | ||
245 | return fash; | ||
246 | } | ||
247 | |||
248 | static Fash_Item_Index_Map * | ||
249 | _fash_int_find(Fash_Int *fash, int item) | ||
250 | { | ||
251 | int grp, maj, min; | ||
252 | |||
253 | // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16) | ||
254 | grp = (item >> 16) & 0xff; | ||
255 | maj = (item >> 8) & 0xff; | ||
256 | min = item & 0xff; | ||
257 | if (!fash->bucket[grp]) return NULL; | ||
258 | if (!fash->bucket[grp]->bucket[maj]) return NULL; | ||
259 | return &(fash->bucket[grp]->bucket[maj]->item[min]); | ||
260 | } | ||
261 | |||
262 | static void | ||
263 | _fash_int_add(Fash_Int *fash, int item, RGBA_Font_Int *fint, int idx) | ||
264 | { | ||
265 | int grp, maj, min; | ||
266 | |||
267 | // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16) | ||
268 | grp = (item >> 16) & 0xff; | ||
269 | maj = (item >> 8) & 0xff; | ||
270 | min = item & 0xff; | ||
271 | if (!fash->bucket[grp]) | ||
272 | fash->bucket[grp] = calloc(1, sizeof(Fash_Int_Map2)); | ||
273 | EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]); | ||
274 | if (!fash->bucket[grp]->bucket[maj]) | ||
275 | fash->bucket[grp]->bucket[maj] = calloc(1, sizeof(Fash_Int_Map)); | ||
276 | EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]->bucket[maj]); | ||
277 | fash->bucket[grp]->bucket[maj]->item[min].fint = fint; | ||
278 | fash->bucket[grp]->bucket[maj]->item[min].index = idx; | ||
279 | } | ||
280 | |||
281 | static void | ||
282 | _fash_gl2_free(Fash_Glyph_Map2 *fash) | ||
283 | { | ||
284 | int i; | ||
285 | |||
286 | for (i = 0; i < 256; i++) if (fash->bucket[i]) free(fash->bucket[i]); | ||
287 | free(fash); | ||
288 | } | ||
289 | |||
290 | static void | ||
291 | _fash_gl_free(Fash_Glyph *fash) | ||
292 | { | ||
293 | int i; | ||
294 | |||
295 | for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_gl2_free(fash->bucket[i]); | ||
296 | free(fash); | ||
297 | } | ||
298 | |||
299 | static Fash_Glyph * | ||
300 | _fash_gl_new(void) | ||
301 | { | ||
302 | Fash_Glyph *fash = calloc(1, sizeof(Fash_Glyph)); | ||
303 | fash->freeme = _fash_gl_free; | ||
304 | return fash; | ||
305 | } | ||
306 | |||
307 | static RGBA_Font_Glyph * | ||
308 | _fash_gl_find(Fash_Glyph *fash, int item) | ||
309 | { | ||
310 | int grp, maj, min; | ||
311 | |||
312 | // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16) | ||
313 | grp = (item >> 16) & 0xff; | ||
314 | maj = (item >> 8) & 0xff; | ||
315 | min = item & 0xff; | ||
316 | if (!fash->bucket[grp]) return NULL; | ||
317 | if (!fash->bucket[grp]->bucket[maj]) return NULL; | ||
318 | return fash->bucket[grp]->bucket[maj]->item[min]; | ||
319 | } | ||
320 | |||
321 | static void | ||
322 | _fash_gl_add(Fash_Glyph *fash, int item, RGBA_Font_Glyph *glyph) | ||
323 | { | ||
324 | int grp, maj, min; | ||
325 | |||
326 | // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16) | ||
327 | grp = (item >> 16) & 0xff; | ||
328 | maj = (item >> 8) & 0xff; | ||
329 | min = item & 0xff; | ||
330 | if (!fash->bucket[grp]) | ||
331 | fash->bucket[grp] = calloc(1, sizeof(Fash_Glyph_Map2)); | ||
332 | EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]); | ||
333 | if (!fash->bucket[grp]->bucket[maj]) | ||
334 | fash->bucket[grp]->bucket[maj] = calloc(1, sizeof(Fash_Glyph_Map)); | ||
335 | EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]->bucket[maj]); | ||
336 | fash->bucket[grp]->bucket[maj]->item[min] = glyph; | ||
337 | } | ||
338 | |||
339 | EAPI RGBA_Font_Glyph * | ||
340 | evas_common_font_int_cache_glyph_get(RGBA_Font_Int *fi, FT_UInt idx) | ||
341 | { | ||
342 | RGBA_Font_Glyph *fg; | ||
343 | FT_UInt hindex; | ||
344 | FT_Error error; | ||
345 | int size; | ||
346 | const FT_Int32 hintflags[3] = | ||
347 | { FT_LOAD_NO_HINTING, FT_LOAD_FORCE_AUTOHINT, FT_LOAD_NO_AUTOHINT }; | ||
348 | static FT_Matrix transform = {0x10000, 0x05000, 0x0000, 0x10000}; // about 12 degree. | ||
349 | |||
350 | evas_common_font_int_promote(fi); | ||
351 | if (fi->fash) | ||
352 | { | ||
353 | fg = _fash_gl_find(fi->fash, idx); | ||
354 | if (fg == (void *)(-1)) return NULL; | ||
355 | else if (fg) return fg; | ||
356 | } | ||
357 | |||
358 | hindex = idx + (fi->hinting * 500000000); | ||
359 | |||
360 | // fg = eina_hash_find(fi->glyphs, &hindex); | ||
361 | // if (fg) return fg; | ||
362 | |||
363 | evas_common_font_int_reload(fi); | ||
364 | FTLOCK(); | ||
365 | error = FT_Load_Glyph(fi->src->ft.face, idx, | ||
366 | FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP | | ||
367 | hintflags[fi->hinting]); | ||
368 | FTUNLOCK(); | ||
369 | if (error) | ||
370 | { | ||
371 | if (!fi->fash) fi->fash = _fash_gl_new(); | ||
372 | if (fi->fash) _fash_gl_add(fi->fash, idx, (void *)(-1)); | ||
373 | return NULL; | ||
374 | } | ||
375 | |||
376 | /* Transform the outline of Glyph according to runtime_rend. */ | ||
377 | if (fi->runtime_rend & FONT_REND_SLANT) | ||
378 | FT_Outline_Transform(&fi->src->ft.face->glyph->outline, &transform); | ||
379 | /* Embolden the outline of Glyph according to rundtime_rend. */ | ||
380 | if (fi->runtime_rend & FONT_REND_WEIGHT) | ||
381 | FT_Outline_Embolden(&fi->src->ft.face->glyph->outline, | ||
382 | (fi->src->ft.face->size->metrics.x_ppem * 5 * 64) / 100); | ||
383 | |||
384 | fg = malloc(sizeof(struct _RGBA_Font_Glyph)); | ||
385 | if (!fg) return NULL; | ||
386 | memset(fg, 0, (sizeof(struct _RGBA_Font_Glyph))); | ||
387 | |||
388 | FTLOCK(); | ||
389 | error = FT_Get_Glyph(fi->src->ft.face->glyph, &(fg->glyph)); | ||
390 | FTUNLOCK(); | ||
391 | if (error) | ||
392 | { | ||
393 | free(fg); | ||
394 | if (!fi->fash) fi->fash = _fash_gl_new(); | ||
395 | if (fi->fash) _fash_gl_add(fi->fash, idx, (void *)(-1)); | ||
396 | return NULL; | ||
397 | } | ||
398 | |||
399 | FTLOCK(); | ||
400 | error = FT_Glyph_To_Bitmap(&(fg->glyph), FT_RENDER_MODE_NORMAL, 0, 1); | ||
401 | if (error) | ||
402 | { | ||
403 | FT_Done_Glyph(fg->glyph); | ||
404 | FTUNLOCK(); | ||
405 | free(fg); | ||
406 | if (!fi->fash) fi->fash = _fash_gl_new(); | ||
407 | if (fi->fash) _fash_gl_add(fi->fash, idx, (void *)(-1)); | ||
408 | return NULL; | ||
409 | } | ||
410 | FTUNLOCK(); | ||
411 | |||
412 | fg->glyph_out = (FT_BitmapGlyph)fg->glyph; | ||
413 | fg->index = hindex; | ||
414 | fg->fi = fi; | ||
415 | |||
416 | if (!fi->fash) fi->fash = _fash_gl_new(); | ||
417 | if (fi->fash) _fash_gl_add(fi->fash, idx, fg); | ||
418 | /* This '+ 200' is just an estimation of how much memory freetype will use | ||
419 | * on it's size. This value is not really used anywhere in code - it's | ||
420 | * only for statistics. */ | ||
421 | size = sizeof(RGBA_Font_Glyph) + sizeof(Eina_List) + | ||
422 | (fg->glyph_out->bitmap.width * fg->glyph_out->bitmap.rows) + 200; | ||
423 | fi->usage += size; | ||
424 | if (fi->inuse) evas_common_font_int_use_increase(size); | ||
425 | |||
426 | // eina_hash_direct_add(fi->glyphs, &fg->index, fg); | ||
427 | return fg; | ||
428 | } | ||
429 | |||
430 | typedef struct _Font_Char_Index Font_Char_Index; | ||
431 | struct _Font_Char_Index | ||
432 | { | ||
433 | FT_UInt index; | ||
434 | Eina_Unicode gl; | ||
435 | }; | ||
436 | |||
437 | EAPI FT_UInt | ||
438 | evas_common_get_char_index(RGBA_Font_Int* fi, Eina_Unicode gl) | ||
439 | { | ||
440 | Font_Char_Index result; | ||
441 | //FT_UInt ret; | ||
442 | |||
443 | #ifdef HAVE_PTHREAD | ||
444 | /// pthread_mutex_lock(&fi->ft_mutex); | ||
445 | #endif | ||
446 | |||
447 | // result = eina_hash_find(fi->indexes, &gl); | ||
448 | // if (result) goto on_correct; | ||
449 | // | ||
450 | // result = malloc(sizeof (Font_Char_Index)); | ||
451 | // if (!result) | ||
452 | // { | ||
453 | //#ifdef HAVE_PTHREAD | ||
454 | // pthread_mutex_unlock(&fi->ft_mutex); | ||
455 | //#endif | ||
456 | // return FT_Get_Char_Index(fi->src->ft.face, gl); | ||
457 | // } | ||
458 | |||
459 | evas_common_font_int_reload(fi); | ||
460 | FTLOCK(); | ||
461 | result.index = FT_Get_Char_Index(fi->src->ft.face, gl); | ||
462 | FTUNLOCK(); | ||
463 | result.gl = gl; | ||
464 | |||
465 | // eina_hash_direct_add(fi->indexes, &result->gl, result); | ||
466 | // | ||
467 | // on_correct: | ||
468 | #ifdef HAVE_PTHREAD | ||
469 | // pthread_mutex_unlock(&fi->ft_mutex); | ||
470 | #endif | ||
471 | return result.index; | ||
472 | } | ||
473 | |||
474 | EAPI int | ||
475 | evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, Eina_Unicode gl) | ||
476 | { | ||
477 | Eina_List *l; | ||
478 | |||
479 | if (fn->fash) | ||
480 | { | ||
481 | Fash_Item_Index_Map *fm = _fash_int_find(fn->fash, gl); | ||
482 | if (fm) | ||
483 | { | ||
484 | if (fm->fint) | ||
485 | { | ||
486 | *fi_ret = fm->fint; | ||
487 | return fm->index; | ||
488 | } | ||
489 | else if (fm->index == -1) return 0; | ||
490 | } | ||
491 | } | ||
492 | |||
493 | for (l = fn->fonts; l; l = l->next) | ||
494 | { | ||
495 | RGBA_Font_Int *fi; | ||
496 | int idx; | ||
497 | |||
498 | fi = l->data; | ||
499 | |||
500 | #if 0 /* FIXME: charmap user is disabled and use a deprecated data type. */ | ||
501 | /* | ||
502 | if (fi->src->charmap) // Charmap loaded, FI/FS blank | ||
503 | { | ||
504 | idx = evas_array_hash_search(fi->src->charmap, gl); | ||
505 | if (idx != 0) | ||
506 | { | ||
507 | evas_common_font_source_load_complete(fi->src); | ||
508 | evas_common_font_int_load_complete(fi); | ||
509 | |||
510 | evas_array_hash_free(fi->src->charmap); | ||
511 | fi->src->charmap = NULL; | ||
512 | |||
513 | *fi_ret = fi; | ||
514 | return idx; | ||
515 | } | ||
516 | } | ||
517 | else | ||
518 | */ | ||
519 | #endif | ||
520 | if (!fi->src->ft.face) /* Charmap not loaded, FI/FS blank */ | ||
521 | { | ||
522 | evas_common_font_int_reload(fi); | ||
523 | } | ||
524 | if (fi->src->ft.face) | ||
525 | { | ||
526 | idx = evas_common_get_char_index(fi, gl); | ||
527 | if (idx != 0) | ||
528 | { | ||
529 | if (!fi->ft.size) | ||
530 | evas_common_font_int_load_complete(fi); | ||
531 | if (!fn->fash) fn->fash = _fash_int_new(); | ||
532 | if (fn->fash) _fash_int_add(fn->fash, gl, fi, idx); | ||
533 | *fi_ret = fi; | ||
534 | return idx; | ||
535 | } | ||
536 | else | ||
537 | { | ||
538 | if (!fn->fash) fn->fash = _fash_int_new(); | ||
539 | if (fn->fash) _fash_int_add(fn->fash, gl, NULL, -1); | ||
540 | } | ||
541 | } | ||
542 | } | ||
543 | *fi_ret = NULL; | ||
544 | return 0; | ||
545 | } | ||