big patch from Samsung SAIT (Advanced research group) for async multi-frame
[framework/uifw/evas.git] / src / lib / engines / common / evas_intl_utils.c
1 #include <string.h>
2 #include <stdlib.h>
3
4 #include "evas_common.h"
5 #include "evas_intl_utils.h"
6
7 #include "evas_font_private.h"
8
9 #ifdef INTERNATIONAL_SUPPORT
10 #include <fribidi/fribidi.h>
11
12 #define UTF8_BYTES_PER_CHAR 4
13
14 #ifdef BUILD_PTHREAD
15 static LK(fribidi_lock);
16 #endif
17
18 /* FIXME: fribidi_utf8_to_unicode should use char len and not byte len!*/
19 char *
20 evas_intl_utf8_to_visual(const char *text,
21                         int *ret_len,
22                         EvasIntlParType *direction,
23                         EvasIntlStrIndex **position_L_to_V_list,
24                         EvasIntlStrIndex **position_V_to_L_list,
25                         EvasIntlLevel **embedding_level_list)
26 {
27    FriBidiChar *unicode_in, *unicode_out;
28    EvasIntlStrIndex *tmp_L_to_V_list = NULL;
29    EvasIntlStrIndex *tmp_V_to_L_list = NULL;
30    EvasIntlLevel *tmp_level_list = NULL;
31    char *text_out;
32    size_t len;
33    size_t byte_len;
34
35    if (!text)
36      return NULL;
37
38    len = evas_string_char_len_get(text);
39
40    byte_len = strlen(text); /* we need the actual number of bytes, not number of chars */
41
42    unicode_in = (FriBidiChar *)alloca(sizeof(FriBidiChar) * (len + 1));
43    if (!unicode_in)
44      {
45         len = -1;
46         goto error1;
47      }
48
49    FBDLOCK();
50    len = fribidi_utf8_to_unicode(text, byte_len, unicode_in);
51    FBDUNLOCK();
52    unicode_in[len] = 0;
53
54    unicode_out = (FriBidiChar *)alloca(sizeof(FriBidiChar) * (len + 1));
55    if (!unicode_out)
56      {
57         len = -1;
58         goto error2;
59      }
60
61     if (embedding_level_list)
62        {
63           *embedding_level_list = (EvasIntlLevel *)malloc(sizeof(EvasIntlLevel) * len);
64           if (!*embedding_level_list)
65             {
66               len = -1;
67               goto error3;
68             }
69          tmp_level_list = *embedding_level_list;
70        }
71  
72      if (position_L_to_V_list)
73        {
74           *position_L_to_V_list = (EvasIntlStrIndex *)malloc(sizeof(EvasIntlStrIndex) * len);
75           if (!*position_L_to_V_list)
76             {
77               len = -1;
78               goto error4;
79             }
80          tmp_L_to_V_list = *position_L_to_V_list;
81        }
82  
83      if (position_V_to_L_list)
84        {
85           *position_V_to_L_list = (EvasIntlStrIndex *)malloc(sizeof(EvasIntlStrIndex) * len);
86           if (!*position_V_to_L_list)
87             {
88               len = -1;
89               goto error5;
90             }
91          tmp_V_to_L_list = *position_V_to_L_list;
92        }
93
94 #ifdef ARABIC_SUPPORT
95    /* fix arabic context */
96    evas_intl_arabic_to_context(unicode_in);
97 #endif
98    LKL(fribidi_lock);
99    if (!fribidi_log2vis(unicode_in, len, direction,
100          unicode_out, tmp_L_to_V_list, tmp_V_to_L_list, tmp_level_list))
101      {
102         LKU(fribidi_lock);
103         len = -2;
104         goto error5;
105      }
106    LKU(fribidi_lock);
107
108    text_out = malloc(UTF8_BYTES_PER_CHAR * len + 1);
109    if (!text_out)
110      {
111         len = -1;
112         goto error6;
113      }
114
115    fribidi_unicode_to_utf8(unicode_out, len, text_out);
116    FBDUNLOCK();
117    
118    *ret_len = len;
119    return text_out;
120
121 /* ERROR HANDLING */
122 error6:
123    free(unicode_out);
124 error5:
125    free(*position_V_to_L_list);
126    *position_V_to_L_list = NULL;
127 error4:
128    free(*position_L_to_V_list);
129    *position_L_to_V_list = NULL;
130 error3:
131    free(*embedding_level_list);
132    *embedding_level_list = NULL;
133 error2:
134    free(unicode_in);
135 error1:
136
137    *ret_len = len;
138    return NULL;
139 }
140
141 int
142 evas_intl_is_rtl_char(EvasIntlLevel *embedded_level_list, EvasIntlStrIndex i)
143 {
144    if(embedded_level_list || i < 0)
145      return 0;
146    return FRIBIDI_IS_RTL(embedded_level_list[i]);
147 }
148 #endif