1/* FriBidi
2 * fribidi.c - Unicode bidirectional and Arabic joining/shaping algorithms
3 *
4 * Authors:
5 * Behdad Esfahbod, 2001, 2002, 2004
6 * Dov Grobgeld, 1999, 2000
7 *
8 * Copyright (C) 2004 Sharif FarsiWeb, Inc
9 * Copyright (C) 2001,2002 Behdad Esfahbod
10 * Copyright (C) 1999,2000 Dov Grobgeld
11 *
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
16 *
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public License
23 * along with this library, in a file named COPYING; if not, write to the
24 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 * Boston, MA 02110-1301, USA
26 *
27 * For licensing issues, contact <fribidi.license@gmail.com>.
28 */
29
30#include "common.h"
31
32#include <fribidi.h>
33
34#ifdef DEBUG
35static int flag_debug = false;
36#endif
37
38FRIBIDI_ENTRY fribidi_boolean
39fribidi_debug_status (
40 void
41)
42{
43#ifdef DEBUG
44 return flag_debug;
45#else
46 return false;
47#endif
48}
49
50FRIBIDI_ENTRY fribidi_boolean
51fribidi_set_debug (
52 /* input */
53 fribidi_boolean state
54)
55{
56#ifdef DEBUG
57 return flag_debug = state;
58#else
59 return false;
60#endif
61}
62
63FRIBIDI_ENTRY FriBidiStrIndex
64fribidi_remove_bidi_marks (
65 FriBidiChar *str,
66 const FriBidiStrIndex len,
67 FriBidiStrIndex *positions_to_this,
68 FriBidiStrIndex *position_from_this_list,
69 FriBidiLevel *embedding_levels
70)
71{
72 register FriBidiStrIndex i, j = 0;
73 fribidi_boolean private_from_this = false;
74 fribidi_boolean status = false;
75
76 if UNLIKELY
77 (len == 0 || str == NULL)
78 {
79 status = true;
80 goto out;
81 }
82
83 DBG ("in fribidi_remove_bidi_marks");
84
85 fribidi_assert (str);
86
87 /* If to_this is not NULL, we must have from_this as well. If it is
88 not given by the caller, we have to make a private instance of it. */
89 if (positions_to_this && !position_from_this_list)
90 {
91 position_from_this_list = fribidi_malloc (size: sizeof
92 (position_from_this_list[0]) *
93 len);
94 if UNLIKELY
95 (!position_from_this_list) goto out;
96 private_from_this = true;
97 for (i = 0; i < len; i++)
98 position_from_this_list[positions_to_this[i]] = i;
99 }
100
101 for (i = 0; i < len; i++)
102 if (!FRIBIDI_IS_EXPLICIT_OR_BN (fribidi_get_bidi_type (str[i]))
103 && !FRIBIDI_IS_ISOLATE (fribidi_get_bidi_type (str[i]))
104 && str[i] != FRIBIDI_CHAR_LRM && str[i] != FRIBIDI_CHAR_RLM)
105 {
106 str[j] = str[i];
107 if (embedding_levels)
108 embedding_levels[j] = embedding_levels[i];
109 if (position_from_this_list)
110 position_from_this_list[j] = position_from_this_list[i];
111 j++;
112 }
113
114 /* Convert the from_this list to to_this */
115 if (positions_to_this)
116 {
117 for (i = 0; i < len; i++)
118 positions_to_this[i] = -1;
119 for (i = 0; i < len; i++)
120 positions_to_this[position_from_this_list[i]] = i;
121 }
122
123 status = true;
124
125out:
126
127 if (private_from_this)
128 fribidi_free (ptr: position_from_this_list);
129
130 return status ? j : -1;
131}
132
133/* Local array size, used for stack-based local arrays */
134#define LOCAL_LIST_SIZE 128
135static FriBidiFlags flags = FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC;
136
137
138FRIBIDI_ENTRY FriBidiLevel
139fribidi_log2vis (
140 /* input */
141 const FriBidiChar *str,
142 const FriBidiStrIndex len,
143 /* input and output */
144 FriBidiParType *pbase_dir,
145 /* output */
146 FriBidiChar *visual_str,
147 FriBidiStrIndex *positions_L_to_V,
148 FriBidiStrIndex *positions_V_to_L,
149 FriBidiLevel *embedding_levels
150)
151{
152 register FriBidiStrIndex i;
153 FriBidiLevel max_level = 0;
154 fribidi_boolean private_V_to_L = false;
155 fribidi_boolean private_embedding_levels = false;
156 fribidi_boolean status = false;
157 FriBidiArabicProp local_ar_props[LOCAL_LIST_SIZE];
158 FriBidiArabicProp *ar_props = NULL;
159 FriBidiLevel local_embedding_levels[LOCAL_LIST_SIZE];
160 FriBidiCharType local_bidi_types[LOCAL_LIST_SIZE];
161 FriBidiCharType *bidi_types = NULL;
162 FriBidiBracketType local_bracket_types[LOCAL_LIST_SIZE];
163 FriBidiBracketType *bracket_types = NULL;
164 FriBidiStrIndex local_positions_V_to_L[LOCAL_LIST_SIZE];
165
166 if UNLIKELY
167 (len == 0)
168 {
169 status = true;
170 goto out;
171 }
172
173 DBG ("in fribidi_log2vis");
174
175 fribidi_assert (str);
176 fribidi_assert (pbase_dir);
177
178 if (len < LOCAL_LIST_SIZE)
179 bidi_types = local_bidi_types;
180 else
181 bidi_types = fribidi_malloc (size: len * sizeof bidi_types[0]);
182 if (!bidi_types)
183 goto out;
184
185 fribidi_get_bidi_types (str, len, btypes: bidi_types);
186
187 if (len < LOCAL_LIST_SIZE)
188 bracket_types = local_bracket_types;
189 else
190 bracket_types = fribidi_malloc (size: len * sizeof bracket_types[0]);
191
192 if (!bracket_types)
193 goto out;
194
195 fribidi_get_bracket_types (str, len, types: bidi_types,
196 /* output */
197 btypes: bracket_types);
198 if (!embedding_levels)
199 {
200 if (len < LOCAL_LIST_SIZE)
201 embedding_levels = local_embedding_levels;
202 else
203 embedding_levels = fribidi_malloc (size: len * sizeof embedding_levels[0]);
204 if (!embedding_levels)
205 goto out;
206 private_embedding_levels = true;
207 }
208
209 max_level = fribidi_get_par_embedding_levels_ex (bidi_types,
210 bracket_types,
211 len,
212 pbase_dir,
213 embedding_levels) - 1;
214 if UNLIKELY
215 (max_level < 0) goto out;
216
217 /* If l2v is to be calculated we must have v2l as well. If it is not
218 given by the caller, we have to make a private instance of it. */
219 if (positions_L_to_V && !positions_V_to_L)
220 {
221 if (len < LOCAL_LIST_SIZE)
222 positions_V_to_L = local_positions_V_to_L;
223 else
224 positions_V_to_L =
225 (FriBidiStrIndex *) fribidi_malloc (size: sizeof (FriBidiStrIndex) * len);
226 if (!positions_V_to_L)
227 goto out;
228 private_V_to_L = true;
229 }
230
231 /* Set up the ordering array to identity order */
232 if (positions_V_to_L)
233 {
234 for (i = 0; i < len; i++)
235 positions_V_to_L[i] = i;
236 }
237
238
239 if (visual_str)
240 {
241 /* Using memcpy instead
242 for (i = len - 1; i >= 0; i--)
243 visual_str[i] = str[i];
244 */
245 memcpy (dest: visual_str, src: str, n: len * sizeof (*visual_str));
246
247 /* Arabic joining */
248 if (len < LOCAL_LIST_SIZE)
249 ar_props = local_ar_props;
250 else
251 ar_props = fribidi_malloc (size: len * sizeof ar_props[0]);
252 fribidi_get_joining_types (str, len, jtypes: ar_props);
253 fribidi_join_arabic (bidi_types, len, embedding_levels, ar_props);
254
255 fribidi_shape (flags, embedding_levels, len, ar_props, str: visual_str);
256 }
257
258 /* line breaking goes here, but we assume one line in this function */
259
260 /* and this should be called once per line, but again, we assume one
261 * line in this deprecated function */
262 status =
263 fribidi_reorder_line (flags, bidi_types, len, off: 0, base_dir: *pbase_dir,
264 embedding_levels, visual_str,
265 map: positions_V_to_L);
266
267 /* Convert the v2l list to l2v */
268 if (positions_L_to_V)
269 {
270 for (i = 0; i < len; i++)
271 positions_L_to_V[i] = -1;
272 for (i = 0; i < len; i++)
273 positions_L_to_V[positions_V_to_L[i]] = i;
274 }
275
276out:
277
278 if (private_V_to_L && positions_V_to_L != local_positions_V_to_L)
279 fribidi_free (ptr: positions_V_to_L);
280
281 if (private_embedding_levels && embedding_levels != local_embedding_levels)
282 fribidi_free (ptr: embedding_levels);
283
284 if (ar_props && ar_props != local_ar_props)
285 fribidi_free (ptr: ar_props);
286
287 if (bidi_types && bidi_types != local_bidi_types)
288 fribidi_free (ptr: bidi_types);
289
290 if (bracket_types && bracket_types != local_bracket_types)
291 fribidi_free (ptr: bracket_types);
292
293 return status ? max_level + 1 : 0;
294}
295
296const char *fribidi_unicode_version = FRIBIDI_UNICODE_VERSION;
297
298const char *fribidi_version_info =
299 "(" FRIBIDI_NAME ") " FRIBIDI_VERSION "\n"
300 "interface version " FRIBIDI_INTERFACE_VERSION_STRING ",\n"
301 "Unicode Character Database version " FRIBIDI_UNICODE_VERSION ",\n"
302 "Configure options"
303#ifdef DEBUG
304 " --enable-debug"
305#endif /* DEBUG */
306 ".\n\n"
307 "Copyright (C) 2004 Sharif FarsiWeb, Inc.\n"
308 "Copyright (C) 2001, 2002, 2004, 2005 Behdad Esfahbod\n"
309 "Copyright (C) 1999, 2000, 2017, 2018, 2019 Dov Grobgeld\n"
310 FRIBIDI_NAME " comes with NO WARRANTY, to the extent permitted by law.\n"
311 "You may redistribute copies of " FRIBIDI_NAME " under\n"
312 "the terms of the GNU Lesser General Public License.\n"
313 "For more information about these matters, see the file named COPYING.\n\n"
314 "Written by Behdad Esfahbod and Dov Grobgeld.\n";
315
316/* Editor directions:
317 * vim:textwidth=78:tabstop=8:shiftwidth=2:autoindent:cindent
318 */
319

source code of gtk/subprojects/fribidi/lib/fribidi.c