diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/evas/src/lib/engines/common/language/evas_bidi_utils.c | 645 |
1 files changed, 0 insertions, 645 deletions
diff --git a/libraries/evas/src/lib/engines/common/language/evas_bidi_utils.c b/libraries/evas/src/lib/engines/common/language/evas_bidi_utils.c deleted file mode 100644 index 002cfbe..0000000 --- a/libraries/evas/src/lib/engines/common/language/evas_bidi_utils.c +++ /dev/null | |||
@@ -1,645 +0,0 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include <config.h> | ||
3 | #endif | ||
4 | |||
5 | #include <string.h> | ||
6 | #include <stdlib.h> | ||
7 | |||
8 | #include "evas_common.h" | ||
9 | #include "evas_bidi_utils.h" | ||
10 | |||
11 | #include "evas_font_private.h" | ||
12 | |||
13 | #ifdef BIDI_SUPPORT | ||
14 | #include <fribidi/fribidi.h> | ||
15 | /** | ||
16 | * @internal | ||
17 | * @addtogroup Evas_Utils | ||
18 | * | ||
19 | * @{ | ||
20 | */ | ||
21 | /** | ||
22 | * @internal | ||
23 | * @addtogroup Evas_BiDi | ||
24 | * | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | /** | ||
29 | * @internal | ||
30 | * @def _SAFE_FREE(x) | ||
31 | * checks if x is not NULL, if it's not, it's freed and set to NULL. | ||
32 | */ | ||
33 | #define _SAFE_FREE(x) \ | ||
34 | do { \ | ||
35 | if (x) \ | ||
36 | { \ | ||
37 | free(x); \ | ||
38 | x = NULL; \ | ||
39 | } \ | ||
40 | } while(0) | ||
41 | |||
42 | #if SIZEOF_FRIBIDICHAR != SIZEOF_EINA_UNICODE | ||
43 | # define EVAS_FRIBIDI_EINA_UNICODE_UNEQUAL | ||
44 | #endif | ||
45 | |||
46 | #ifdef EVAS_FRIBIDI_EINA_UNICODE_UNEQUAL | ||
47 | /* Convert bidichar to eina_unicode assume both are valid pointers */ | ||
48 | static Eina_Unicode * | ||
49 | _evas_bidi_fribidichar_to_unicode(Eina_Unicode *dest, const FriBidiChar *src) | ||
50 | { | ||
51 | Eina_Unicode *ret = dest; | ||
52 | |||
53 | while (*src) | ||
54 | *dest++ = *src++; | ||
55 | *dest = 0; | ||
56 | return ret; | ||
57 | } | ||
58 | |||
59 | /* Convert eina_unicode to bidi_char assume both are valid pointers */ | ||
60 | static FriBidiChar * | ||
61 | _evas_bidi_unicode_to_fribidichar(FriBidiChar *dest, const Eina_Unicode *src) | ||
62 | { | ||
63 | FriBidiChar *ret = dest; | ||
64 | |||
65 | while (*src) | ||
66 | *dest++ = *src++; | ||
67 | *dest = 0; | ||
68 | return ret; | ||
69 | } | ||
70 | #endif | ||
71 | |||
72 | /** | ||
73 | * @internal | ||
74 | * Checks if the string has RTL characters. | ||
75 | * | ||
76 | * @param str The string to be checked | ||
77 | * @return #EINA_TRUE if true, #EINA_FALSE otherwise. | ||
78 | */ | ||
79 | Eina_Bool | ||
80 | evas_bidi_is_rtl_str(const Eina_Unicode *str) | ||
81 | { | ||
82 | EvasBiDiCharType type; | ||
83 | |||
84 | if (!str) | ||
85 | return EINA_FALSE; | ||
86 | |||
87 | for ( ; *str ; str++) | ||
88 | { | ||
89 | type = fribidi_get_bidi_type((FriBidiChar) *str); | ||
90 | if (FRIBIDI_IS_LETTER(type) && FRIBIDI_IS_RTL(type)) | ||
91 | { | ||
92 | return EINA_TRUE; | ||
93 | } | ||
94 | } | ||
95 | return EINA_FALSE; | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * @internal | ||
100 | * Shapes the string ustr according to the bidi properties. | ||
101 | * | ||
102 | * @param str The string to shape | ||
103 | * @param bidi_props the bidi props to shaped according. | ||
104 | * @param start the start of the string to shape (offset in bidi_props) | ||
105 | * @param len the length of th string. | ||
106 | * @return #EINA_TRUE on success, #EINA_FALSE otherwise. | ||
107 | */ | ||
108 | EAPI Eina_Bool | ||
109 | evas_bidi_shape_string(Eina_Unicode *eina_ustr, const Evas_BiDi_Paragraph_Props *bidi_props, size_t start, size_t len) | ||
110 | { | ||
111 | FriBidiChar *ustr, *base_ustr = NULL; | ||
112 | |||
113 | if (!bidi_props) | ||
114 | return EINA_FALSE; | ||
115 | |||
116 | /* The size of fribidichar is different than eina_unicode, convert */ | ||
117 | #ifdef EVAS_FRIBIDI_EINA_UNICODE_UNEQUAL | ||
118 | base_ustr = ustr = calloc(len + 1, sizeof(FriBidiChar)); | ||
119 | ustr = _evas_bidi_unicode_to_fribidichar(ustr, eina_ustr); | ||
120 | #else | ||
121 | (void) base_ustr; | ||
122 | ustr = (FriBidiChar *) eina_ustr; | ||
123 | #endif | ||
124 | |||
125 | |||
126 | EvasBiDiJoiningType *join_types = NULL; | ||
127 | join_types = (EvasBiDiJoiningType *) malloc(sizeof(EvasBiDiJoiningType) * len); | ||
128 | if (!join_types) | ||
129 | { | ||
130 | return EINA_FALSE; | ||
131 | } | ||
132 | fribidi_get_joining_types(ustr, len, join_types); | ||
133 | |||
134 | fribidi_join_arabic(bidi_props->char_types + start, len, | ||
135 | bidi_props->embedding_levels + start, join_types); | ||
136 | |||
137 | |||
138 | /* Actually modify the string */ | ||
139 | fribidi_shape(FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC, | ||
140 | bidi_props->embedding_levels + start, len, join_types, ustr); | ||
141 | |||
142 | if (join_types) free(join_types); | ||
143 | |||
144 | /* Convert back */ | ||
145 | #ifdef EVAS_FRIBIDI_EINA_UNICODE_UNEQUAL | ||
146 | eina_ustr = _evas_bidi_fribidichar_to_unicode(eina_ustr, ustr); | ||
147 | if (base_ustr) free(base_ustr); | ||
148 | #endif | ||
149 | return EINA_TRUE; | ||
150 | } | ||
151 | |||
152 | /** | ||
153 | * @internal | ||
154 | * Return a -1 terminated array of the indexes of the delimiters (passed in | ||
155 | * delim) found in the string. This result should be used with par_props_get. | ||
156 | * | ||
157 | * @param str The string to parse | ||
158 | * @param delim a list of delimiters to work with. | ||
159 | * @return returns a -1 terminated array of indexes according to positions of the delimiters found. NULL if there were none. | ||
160 | */ | ||
161 | int * | ||
162 | evas_bidi_segment_idxs_get(const Eina_Unicode *str, const char *delim) | ||
163 | { | ||
164 | Eina_Unicode *udelim; | ||
165 | const Eina_Unicode *str_base = str; | ||
166 | int *ret, *tmp_ret; | ||
167 | int ret_idx = 0, ret_len = 10; /* arbitrary choice */ | ||
168 | udelim = eina_unicode_utf8_to_unicode(delim, NULL); | ||
169 | ret = malloc(ret_len * sizeof(int)); | ||
170 | for ( ; *str ; str++) | ||
171 | { | ||
172 | const Eina_Unicode *del; | ||
173 | for (del = udelim ; *del ; del++) | ||
174 | { | ||
175 | if (*str == *del) | ||
176 | { | ||
177 | if (ret_idx >= ret_len) | ||
178 | { | ||
179 | /* arbitrary choice */ | ||
180 | ret_len += 20; | ||
181 | tmp_ret = realloc(ret, ret_len * sizeof(int)); | ||
182 | if (!tmp_ret) | ||
183 | { | ||
184 | free(ret); | ||
185 | return NULL; | ||
186 | } | ||
187 | } | ||
188 | ret[ret_idx++] = str - str_base; | ||
189 | break; | ||
190 | } | ||
191 | } | ||
192 | } | ||
193 | free(udelim); | ||
194 | |||
195 | /* If no indexes were found return NULL */ | ||
196 | if (ret_idx == 0) | ||
197 | { | ||
198 | free(ret); | ||
199 | return NULL; | ||
200 | } | ||
201 | |||
202 | ret[ret_idx] = -1; | ||
203 | tmp_ret = realloc(ret, (ret_idx + 1) * sizeof(int)); | ||
204 | |||
205 | return (tmp_ret) ? tmp_ret : ret; | ||
206 | } | ||
207 | |||
208 | /** | ||
209 | * @internal | ||
210 | * Allocates bidi properties according to ustr. First checks to see if the | ||
211 | * passed has rtl chars, if not, it returns NULL. | ||
212 | * | ||
213 | * Assumes all the segment_idxs are either -1 or legal, and > 0 indexes. | ||
214 | * Also assumes that the characters at the override points are of weak/neutral | ||
215 | * bidi type, otherwise unexpected results may occur. | ||
216 | * | ||
217 | * @param ustr The string to update according to. | ||
218 | * @param len The length of the string | ||
219 | * @param segment_idxs A -1 terminated array of points to start a new bidi analysis at (used for section high level bidi overrides). - NULL means none. | ||
220 | * @return returns allocated paragraph props on success, NULL otherwise. | ||
221 | */ | ||
222 | Evas_BiDi_Paragraph_Props * | ||
223 | evas_bidi_paragraph_props_get(const Eina_Unicode *eina_ustr, size_t len, | ||
224 | int *segment_idxs) | ||
225 | { | ||
226 | Evas_BiDi_Paragraph_Props *bidi_props = NULL; | ||
227 | EvasBiDiCharType *char_types = NULL; | ||
228 | EvasBiDiLevel *embedding_levels = NULL; | ||
229 | const FriBidiChar *ustr; | ||
230 | FriBidiChar *base_ustr = NULL; | ||
231 | |||
232 | if (!eina_ustr) | ||
233 | return NULL; | ||
234 | |||
235 | |||
236 | if (!evas_bidi_is_rtl_str(eina_ustr)) /* No need to handle bidi */ | ||
237 | { | ||
238 | len = -1; | ||
239 | goto cleanup; | ||
240 | } | ||
241 | |||
242 | len = eina_unicode_strlen(eina_ustr); | ||
243 | /* The size of fribidichar s different than eina_unicode, convert */ | ||
244 | #ifdef EVAS_FRIBIDI_EINA_UNICODE_UNEQUAL | ||
245 | base_ustr = calloc(len + 1, sizeof(FriBidiChar)); | ||
246 | base_ustr = _evas_bidi_unicode_to_fribidichar(base_ustr, eina_ustr); | ||
247 | ustr = base_ustr; | ||
248 | #else | ||
249 | ustr = (const FriBidiChar *) eina_ustr; | ||
250 | #endif | ||
251 | |||
252 | bidi_props = evas_bidi_paragraph_props_new(); | ||
253 | |||
254 | /* Prep work for reordering */ | ||
255 | char_types = (EvasBiDiCharType *) malloc(sizeof(EvasBiDiCharType) * len); | ||
256 | if (!char_types) | ||
257 | { | ||
258 | len = -2; | ||
259 | goto cleanup; | ||
260 | } | ||
261 | fribidi_get_bidi_types(ustr, len, char_types); | ||
262 | |||
263 | embedding_levels = (EvasBiDiLevel *)malloc(sizeof(EvasBiDiLevel) * len); | ||
264 | if (!embedding_levels) | ||
265 | { | ||
266 | len = -2; | ||
267 | goto cleanup; | ||
268 | } | ||
269 | |||
270 | if (segment_idxs) | ||
271 | { | ||
272 | size_t pos = 0; | ||
273 | int *itr; | ||
274 | EvasBiDiLevel base_level = 0; | ||
275 | EvasBiDiParType direction; | ||
276 | |||
277 | for (itr = segment_idxs ; *itr > 0 ; itr++) | ||
278 | { | ||
279 | direction = EVAS_BIDI_PARAGRAPH_NEUTRAL; | ||
280 | if (!fribidi_get_par_embedding_levels(char_types + pos, | ||
281 | *itr - pos, | ||
282 | &direction, | ||
283 | embedding_levels + pos)) | ||
284 | { | ||
285 | len = -2; | ||
286 | goto cleanup; | ||
287 | } | ||
288 | |||
289 | /* Only on the first run */ | ||
290 | if (itr == segment_idxs) | ||
291 | { | ||
292 | bidi_props->direction = direction; | ||
293 | /* adjust base_level to be 1 for rtl paragraphs, and 0 for | ||
294 | * ltr paragraphs. */ | ||
295 | base_level = | ||
296 | EVAS_BIDI_PARAGRAPH_DIRECTION_IS_RTL(bidi_props) ? 1 : 0; | ||
297 | } | ||
298 | |||
299 | /* We want those chars at the override points to be on the base | ||
300 | * level and we also remove -2 cause we later increment them, | ||
301 | * just for simpler code paths */ | ||
302 | embedding_levels[*itr] = base_level - 2; | ||
303 | pos = *itr + 1; | ||
304 | } | ||
305 | |||
306 | direction = EVAS_BIDI_PARAGRAPH_NEUTRAL; | ||
307 | if (!fribidi_get_par_embedding_levels(char_types + pos, | ||
308 | len - pos, | ||
309 | &direction, | ||
310 | embedding_levels + pos)) | ||
311 | { | ||
312 | len = -2; | ||
313 | goto cleanup; | ||
314 | } | ||
315 | |||
316 | /* Increment all levels by 2 to emulate embedding. */ | ||
317 | { | ||
318 | EvasBiDiLevel *bitr = embedding_levels, *end; | ||
319 | end = bitr + len; | ||
320 | for ( ; bitr < end ; bitr++) | ||
321 | { | ||
322 | *bitr += 2; | ||
323 | } | ||
324 | } | ||
325 | } | ||
326 | else | ||
327 | { | ||
328 | if (!fribidi_get_par_embedding_levels(char_types, len, | ||
329 | &bidi_props->direction, embedding_levels)) | ||
330 | { | ||
331 | len = -2; | ||
332 | goto cleanup; | ||
333 | } | ||
334 | } | ||
335 | |||
336 | |||
337 | /* clean up */ | ||
338 | if (bidi_props->embedding_levels) | ||
339 | { | ||
340 | free(bidi_props->embedding_levels); | ||
341 | } | ||
342 | bidi_props->embedding_levels = embedding_levels; | ||
343 | |||
344 | /* clean up */ | ||
345 | |||
346 | if (bidi_props->char_types) | ||
347 | { | ||
348 | free(bidi_props->char_types); | ||
349 | } | ||
350 | bidi_props->char_types = char_types; | ||
351 | |||
352 | if (base_ustr) free(base_ustr); | ||
353 | |||
354 | |||
355 | return bidi_props; | ||
356 | |||
357 | /* Cleanup */ | ||
358 | cleanup: | ||
359 | if (char_types) free(char_types); | ||
360 | if (embedding_levels) free(embedding_levels); | ||
361 | if (base_ustr) free(base_ustr); | ||
362 | if (bidi_props) evas_bidi_paragraph_props_unref(bidi_props); /* Clean up the bidi props */ | ||
363 | return NULL; | ||
364 | } | ||
365 | |||
366 | /** | ||
367 | * @internal | ||
368 | * Copies dst to src and refs (doesn't copy) the paragraph props. | ||
369 | * | ||
370 | * @param src the props to copy | ||
371 | * @param dst the props to copy to. | ||
372 | */ | ||
373 | void | ||
374 | evas_bidi_props_copy_and_ref(const Evas_BiDi_Props *src, Evas_BiDi_Props *dst) | ||
375 | { | ||
376 | dst->dir = src->dir; | ||
377 | } | ||
378 | |||
379 | /** | ||
380 | * @internal | ||
381 | * Reorders ustr according to the bidi props. | ||
382 | * | ||
383 | * @param ustr the string to reorder. - Null is ok, will just populate the map. | ||
384 | * @param start the start of the line | ||
385 | * @param len the length of the line | ||
386 | * @param props the paragraph props to reorder according to | ||
387 | * @param _v_to_l The visual to logical map to populate - if NULL it won't populate it. | ||
388 | * @return #EINA_FALSE on success, #EINA_TRUE on error. | ||
389 | */ | ||
390 | Eina_Bool | ||
391 | evas_bidi_props_reorder_line(Eina_Unicode *eina_ustr, size_t start, size_t len, const Evas_BiDi_Paragraph_Props *props, EvasBiDiStrIndex **_v_to_l) | ||
392 | { | ||
393 | EvasBiDiStrIndex *v_to_l = NULL; | ||
394 | FriBidiChar *ustr = NULL, *base_ustr = NULL; | ||
395 | |||
396 | if (!props) | ||
397 | return EINA_FALSE; | ||
398 | |||
399 | if (eina_ustr) | ||
400 | { | ||
401 | /* The size of fribidichar is different than eina_unicode, convert */ | ||
402 | #ifdef EVAS_FRIBIDI_EINA_UNICODE_UNEQUAL | ||
403 | base_ustr = ustr = calloc(len + 1, sizeof(FriBidiChar)); | ||
404 | ustr = _evas_bidi_unicode_to_fribidichar(ustr, eina_ustr); | ||
405 | #else | ||
406 | ustr = (FriBidiChar *) eina_ustr; | ||
407 | #endif | ||
408 | } | ||
409 | |||
410 | |||
411 | if (_v_to_l) { | ||
412 | size_t i; | ||
413 | v_to_l = *_v_to_l = calloc(len, sizeof(EvasBiDiStrIndex)); | ||
414 | if (!v_to_l) | ||
415 | { | ||
416 | goto error; | ||
417 | } | ||
418 | /* init the array for fribidi */ | ||
419 | for (i = 0 ; i < len ; i++) | ||
420 | { | ||
421 | v_to_l[i] = i; | ||
422 | } | ||
423 | } | ||
424 | |||
425 | { | ||
426 | EvasBiDiLevel *emb_lvl; | ||
427 | emb_lvl = malloc((start + len) * sizeof(EvasBiDiLevel)); | ||
428 | memcpy(emb_lvl, props->embedding_levels, | ||
429 | (start + len) * sizeof(EvasBiDiLevel)); | ||
430 | /* We pass v_to_l - start, because fribidi assumes start is the offset | ||
431 | * from the start of v_to_l as well, not just the props. */ | ||
432 | if (!fribidi_reorder_line (FRIBIDI_FLAGS_DEFAULT, props->char_types, | ||
433 | len, start, props->direction, emb_lvl, ustr, v_to_l - start)) | ||
434 | { | ||
435 | free(emb_lvl); | ||
436 | goto error; | ||
437 | } | ||
438 | free(emb_lvl); | ||
439 | } | ||
440 | |||
441 | |||
442 | /* The size of fribidichar is different than eina_unicode, convert */ | ||
443 | #ifdef EVAS_FRIBIDI_EINA_UNICODE_UNEQUAL | ||
444 | _evas_bidi_fribidichar_to_unicode(eina_ustr, base_ustr); | ||
445 | free(base_ustr); | ||
446 | #endif | ||
447 | return EINA_FALSE; | ||
448 | /* ERROR HANDLING */ | ||
449 | error: | ||
450 | if (base_ustr) free(base_ustr); | ||
451 | _SAFE_FREE(v_to_l); | ||
452 | return EINA_TRUE; | ||
453 | } | ||
454 | |||
455 | /** | ||
456 | * @internal | ||
457 | * Returns the end of the current run of text | ||
458 | * | ||
459 | * @param bidi_props the paragraph properties | ||
460 | * @param start where to start looking from | ||
461 | * @param len the length of the string | ||
462 | * @return the position of the end of the run (offset from | ||
463 | * bidi_props->props->start), 0 when there is no end (i.e all the text) | ||
464 | */ | ||
465 | int | ||
466 | evas_bidi_end_of_run_get(const Evas_BiDi_Paragraph_Props *bidi_props, | ||
467 | size_t start, int len) | ||
468 | { | ||
469 | EvasBiDiLevel *i; | ||
470 | EvasBiDiLevel base; | ||
471 | |||
472 | if (!bidi_props || (len <= 0)) | ||
473 | return 0; | ||
474 | |||
475 | i = bidi_props->embedding_levels + start; | ||
476 | base = *i; | ||
477 | for ( ; (len > 0) && (base == *i) ; len--, i++) | ||
478 | ; | ||
479 | |||
480 | if (len == 0) | ||
481 | { | ||
482 | return 0; | ||
483 | } | ||
484 | return i - (bidi_props->embedding_levels + start); | ||
485 | } | ||
486 | |||
487 | /** | ||
488 | * @internal | ||
489 | * Returns the visual string index from the logical string index. | ||
490 | * | ||
491 | * @param v_to_l the visual to logical map | ||
492 | * @param len the length of the map. | ||
493 | * @param position the position to convert. | ||
494 | * @return on success the visual position, on failure the same position. | ||
495 | */ | ||
496 | EvasBiDiStrIndex | ||
497 | evas_bidi_position_logical_to_visual(EvasBiDiStrIndex *v_to_l, int len, EvasBiDiStrIndex position) | ||
498 | { | ||
499 | int i; | ||
500 | EvasBiDiStrIndex *ind; | ||
501 | if (position >= len || !v_to_l) | ||
502 | return position; | ||
503 | |||
504 | for (i = 0, ind = v_to_l ; i < len ; i++, ind++) | ||
505 | { | ||
506 | if (*ind == position) | ||
507 | { | ||
508 | return i; | ||
509 | } | ||
510 | } | ||
511 | return position; | ||
512 | } | ||
513 | |||
514 | /** | ||
515 | * @internal | ||
516 | * Returns the reversed pos of the index. | ||
517 | * | ||
518 | * @param dir the direction of the string | ||
519 | * @param len the length of the map. | ||
520 | * @param position the position to convert. | ||
521 | * @return on success the visual position, on failure the same position. | ||
522 | */ | ||
523 | EvasBiDiStrIndex | ||
524 | evas_bidi_position_reverse(const Evas_BiDi_Props *props, int len, EvasBiDiStrIndex position) | ||
525 | { | ||
526 | if (!props || position >= len) | ||
527 | return position; | ||
528 | |||
529 | return (props->dir == EVAS_BIDI_DIRECTION_RTL) ? (len - 1) - position : position; | ||
530 | } | ||
531 | |||
532 | /** | ||
533 | * @internal | ||
534 | * Checks if the char is rtl oriented. I.e even a neutral char can become rtl | ||
535 | * if surrounded by rtl chars. | ||
536 | * | ||
537 | * @param bidi_props The bidi paragraph properties | ||
538 | * @param start the base position | ||
539 | * @param index the offset from the base position. | ||
540 | * @return #EINA_TRUE if true, #EINA_FALSE otherwise. | ||
541 | */ | ||
542 | Eina_Bool | ||
543 | evas_bidi_is_rtl_char(const Evas_BiDi_Paragraph_Props *bidi_props, size_t start, EvasBiDiStrIndex ind) | ||
544 | { | ||
545 | if(!bidi_props || ind < 0) | ||
546 | return EINA_FALSE; | ||
547 | return (FRIBIDI_IS_RTL( | ||
548 | bidi_props->embedding_levels[ind + start])) | ||
549 | ? EINA_TRUE : EINA_FALSE; | ||
550 | } | ||
551 | |||
552 | Evas_BiDi_Paragraph_Props * | ||
553 | evas_bidi_paragraph_props_new(void) | ||
554 | { | ||
555 | Evas_BiDi_Paragraph_Props *ret; | ||
556 | ret = calloc(1, sizeof(Evas_BiDi_Paragraph_Props)); | ||
557 | ret->direction = EVAS_BIDI_PARAGRAPH_NEUTRAL; | ||
558 | ret->refcount = 1; | ||
559 | |||
560 | return ret; | ||
561 | } | ||
562 | |||
563 | /** | ||
564 | * @internal | ||
565 | * Refs the bidi props. | ||
566 | * | ||
567 | * @param bidi_props the props to ref. | ||
568 | */ | ||
569 | Evas_BiDi_Paragraph_Props * | ||
570 | evas_bidi_paragraph_props_ref(Evas_BiDi_Paragraph_Props *bidi_props) | ||
571 | { | ||
572 | if (!bidi_props) return NULL; | ||
573 | BIDILOCK(); | ||
574 | |||
575 | bidi_props->refcount++; | ||
576 | BIDIUNLOCK(); | ||
577 | return bidi_props; | ||
578 | } | ||
579 | |||
580 | /** | ||
581 | * @internal | ||
582 | * Unrefs and potentially frees the props. | ||
583 | * | ||
584 | * @param bidi_props the properties to unref | ||
585 | */ | ||
586 | void | ||
587 | evas_bidi_paragraph_props_unref(Evas_BiDi_Paragraph_Props *bidi_props) | ||
588 | { | ||
589 | if (!bidi_props) return; | ||
590 | BIDILOCK(); | ||
591 | |||
592 | if (--bidi_props->refcount == 0) | ||
593 | { | ||
594 | evas_bidi_paragraph_props_clean(bidi_props); | ||
595 | free(bidi_props); | ||
596 | } | ||
597 | BIDIUNLOCK(); | ||
598 | } | ||
599 | |||
600 | |||
601 | /** | ||
602 | * @internal | ||
603 | * Cleans the paragraph properties. | ||
604 | * | ||
605 | * @param bidi_props the properties to clean. | ||
606 | */ | ||
607 | void | ||
608 | evas_bidi_paragraph_props_clean(Evas_BiDi_Paragraph_Props *bidi_props) | ||
609 | { | ||
610 | _SAFE_FREE(bidi_props->embedding_levels); | ||
611 | _SAFE_FREE(bidi_props->char_types); | ||
612 | } | ||
613 | |||
614 | /** | ||
615 | * @internal | ||
616 | * Cleans the bidi properties. | ||
617 | * | ||
618 | * @param bidi_props the properties to clean. | ||
619 | */ | ||
620 | void | ||
621 | evas_bidi_props_clean(Evas_BiDi_Props *bidi_props) | ||
622 | { | ||
623 | if (!bidi_props) return; | ||
624 | bidi_props->dir = EVAS_BIDI_DIRECTION_NEUTRAL; | ||
625 | } | ||
626 | /** | ||
627 | * @} | ||
628 | */ | ||
629 | /** | ||
630 | * @} | ||
631 | */ | ||
632 | #endif | ||
633 | |||
634 | #if 0 | ||
635 | /* Good for debugging */ | ||
636 | static void | ||
637 | dump_levels(Eina_Unicode *ustr, EvasBiDiLevel *emb) | ||
638 | { | ||
639 | for ( ; *ustr ; ustr++, emb++) | ||
640 | { | ||
641 | printf("%lc %d\n", *ustr, *emb); | ||
642 | } | ||
643 | } | ||
644 | #endif | ||
645 | |||