/src/fribidi/lib/fribidi-bidi.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* FriBidi |
2 | | * fribidi-bidi.c - bidirectional algorithm |
3 | | * |
4 | | * Authors: |
5 | | * Behdad Esfahbod, 2001, 2002, 2004 |
6 | | * Dov Grobgeld, 1999, 2000, 2017 |
7 | | * |
8 | | * Copyright (C) 2004 Sharif FarsiWeb, Inc |
9 | | * Copyright (C) 2001,2002 Behdad Esfahbod |
10 | | * Copyright (C) 1999,2000,2017 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-bidi.h> |
33 | | #include <fribidi-mirroring.h> |
34 | | #include <fribidi-brackets.h> |
35 | | #include <fribidi-unicode.h> |
36 | | |
37 | | #include "bidi-types.h" |
38 | | #include "run.h" |
39 | | |
40 | | /* |
41 | | * This file implements most of Unicode Standard Annex #9, Tracking Number 13. |
42 | | */ |
43 | | |
44 | | #ifndef MAX |
45 | | # define MAX(a,b) ((a) > (b) ? (a) : (b)) |
46 | | #endif /* !MAX */ |
47 | | |
48 | | /* Some convenience macros */ |
49 | 10.4G | #define RL_TYPE(list) ((list)->type) |
50 | 17.1M | #define RL_LEN(list) ((list)->len) |
51 | 613M | #define RL_LEVEL(list) ((list)->level) |
52 | | |
53 | | /* "Within this scope, bidirectional types EN and AN are treated as R" */ |
54 | 1.10G | #define RL_TYPE_AN_EN_AS_RTL(list) ( \ |
55 | 1.10G | (((list)->type == FRIBIDI_TYPE_AN) || ((list)->type == FRIBIDI_TYPE_EN) | ((list)->type == FRIBIDI_TYPE_RTL)) ? FRIBIDI_TYPE_RTL : (list)->type) |
56 | 23.5M | #define RL_BRACKET_TYPE(list) ((list)->bracket_type) |
57 | 74.7M | #define RL_ISOLATE_LEVEL(list) ((list)->isolate_level) |
58 | | |
59 | 36.7k | #define LOCAL_BRACKET_SIZE 16 |
60 | | |
61 | | /* Pairing nodes are used for holding a pair of open/close brackets as |
62 | | described in BD16. */ |
63 | | struct _FriBidiPairingNodeStruct { |
64 | | FriBidiRun *open; |
65 | | FriBidiRun *close; |
66 | | struct _FriBidiPairingNodeStruct *next; |
67 | | }; |
68 | | typedef struct _FriBidiPairingNodeStruct FriBidiPairingNode; |
69 | | |
70 | | static FriBidiRun * |
71 | | merge_with_prev ( |
72 | | FriBidiRun *second |
73 | | ) |
74 | 6.03M | { |
75 | 6.03M | FriBidiRun *first; |
76 | | |
77 | 6.03M | fribidi_assert (second); |
78 | 6.03M | fribidi_assert (second->next); |
79 | 6.03M | first = second->prev; |
80 | 6.03M | fribidi_assert (first); |
81 | | |
82 | 6.03M | first->next = second->next; |
83 | 6.03M | first->next->prev = first; |
84 | 6.03M | RL_LEN (first) += RL_LEN (second); |
85 | 6.03M | if (second->next_isolate) |
86 | 6.01M | second->next_isolate->prev_isolate = second->prev_isolate; |
87 | | /* The following edge case typically shouldn't happen, but fuzz |
88 | | testing shows it does, and the assignment protects against |
89 | | a dangling pointer. */ |
90 | 17.1k | else if (second->next->prev_isolate == second) |
91 | 0 | second->next->prev_isolate = second->prev_isolate; |
92 | 6.03M | if (second->prev_isolate) |
93 | 6.03M | second->prev_isolate->next_isolate = second->next_isolate; |
94 | 6.03M | first->next_isolate = second->next_isolate; |
95 | | |
96 | 6.03M | fribidi_free (second); |
97 | 6.03M | return first; |
98 | 6.03M | } |
99 | | static void |
100 | | compact_list ( |
101 | | FriBidiRun *list |
102 | | ) |
103 | 5.74k | { |
104 | 5.74k | fribidi_assert (list); |
105 | | |
106 | 5.74k | if (list->next) |
107 | 5.74k | for_run_list (list, list) |
108 | 7.70M | if (RL_TYPE (list->prev) == RL_TYPE (list) |
109 | 7.70M | && RL_LEVEL (list->prev) == RL_LEVEL (list) |
110 | 7.70M | && RL_ISOLATE_LEVEL (list->prev) == RL_ISOLATE_LEVEL (list) |
111 | | && RL_BRACKET_TYPE(list) == FRIBIDI_NO_BRACKET /* Don't join brackets! */ |
112 | 7.70M | && RL_BRACKET_TYPE(list->prev) == FRIBIDI_NO_BRACKET |
113 | 7.70M | ) |
114 | 2.94M | list = merge_with_prev (list); |
115 | 5.74k | } |
116 | | |
117 | | static void |
118 | | compact_neutrals ( |
119 | | FriBidiRun *list |
120 | | ) |
121 | 3.82k | { |
122 | 3.82k | fribidi_assert (list); |
123 | | |
124 | 3.82k | if (list->next) |
125 | 3.82k | { |
126 | 3.82k | for_run_list (list, list) |
127 | 7.98M | { |
128 | 7.98M | if (RL_LEVEL (list->prev) == RL_LEVEL (list) |
129 | 7.98M | && RL_ISOLATE_LEVEL (list->prev) == RL_ISOLATE_LEVEL (list) |
130 | 7.98M | && |
131 | 7.98M | ((RL_TYPE (list->prev) == RL_TYPE (list) |
132 | 7.73M | || (FRIBIDI_IS_NEUTRAL (RL_TYPE (list->prev)) |
133 | 1.73M | && FRIBIDI_IS_NEUTRAL (RL_TYPE (list))))) |
134 | | && RL_BRACKET_TYPE(list) == FRIBIDI_NO_BRACKET /* Don't join brackets! */ |
135 | 7.98M | && RL_BRACKET_TYPE(list->prev) == FRIBIDI_NO_BRACKET |
136 | 7.98M | ) |
137 | 3.08M | list = merge_with_prev (list); |
138 | 7.98M | } |
139 | 3.82k | } |
140 | 3.82k | } |
141 | | |
142 | | /* Search for an adjacent run in the forward or backward direction. |
143 | | It uses the next_isolate and prev_isolate run for short circuited searching. |
144 | | */ |
145 | | |
146 | | /* The static sentinel is used to signal the end of an isolating |
147 | | sequence */ |
148 | | static FriBidiRun sentinel = { NULL, NULL, 0,0, FRIBIDI_TYPE_SENTINEL, -1,-1,FRIBIDI_NO_BRACKET, NULL, NULL }; |
149 | | |
150 | | static FriBidiRun *get_adjacent_run(FriBidiRun *list, fribidi_boolean forward, fribidi_boolean skip_neutral) |
151 | 17.8M | { |
152 | 17.8M | FriBidiRun *ppp = forward ? list->next_isolate : list->prev_isolate; |
153 | 17.8M | if (!ppp) |
154 | 666k | return &sentinel; |
155 | | |
156 | 17.2M | while (ppp) |
157 | 17.2M | { |
158 | 17.2M | FriBidiCharType ppp_type = RL_TYPE (ppp); |
159 | | |
160 | 17.2M | if (ppp_type == FRIBIDI_TYPE_SENTINEL) |
161 | 6.75k | break; |
162 | | |
163 | | /* Note that when sweeping forward we continue one run |
164 | | beyond the PDI to see what lies behind. When looking |
165 | | backwards, this is not necessary as the leading isolate |
166 | | run has already been assigned the resolved level. */ |
167 | 17.2M | if (ppp->isolate_level > list->isolate_level /* <- How can this be true? */ |
168 | 17.2M | || (forward && ppp_type == FRIBIDI_TYPE_PDI) |
169 | 17.2M | || (skip_neutral && !FRIBIDI_IS_STRONG(ppp_type))) |
170 | 70.5k | { |
171 | 70.5k | ppp = forward ? ppp->next_isolate : ppp->prev_isolate; |
172 | 70.5k | if (!ppp) |
173 | 6.75k | ppp = &sentinel; |
174 | | |
175 | 70.5k | continue; |
176 | 70.5k | } |
177 | 17.2M | break; |
178 | 17.2M | } |
179 | | |
180 | 17.2M | return ppp; |
181 | 17.8M | } |
182 | | |
183 | | #ifdef DEBUG |
184 | | /*====================================================================== |
185 | | * For debugging, define some functions for printing the types and the |
186 | | * levels. |
187 | | *----------------------------------------------------------------------*/ |
188 | | |
189 | | static char char_from_level_array[] = { |
190 | | '$', /* -1 == FRIBIDI_SENTINEL, indicating |
191 | | * start or end of string. */ |
192 | | /* 0-61 == 0-9,a-z,A-Z are the the only valid levels before resolving |
193 | | * implicits. after that the level @ may be appear too. */ |
194 | | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', |
195 | | 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', |
196 | | 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', |
197 | | 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', |
198 | | 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', |
199 | | 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', |
200 | | 'Y', 'Z', |
201 | | |
202 | | /* TBD - insert another 125-64 levels */ |
203 | | |
204 | | '@', /* 62 == only must appear after resolving |
205 | | * implicits. */ |
206 | | |
207 | | '!', /* 63 == FRIBIDI_LEVEL_INVALID, internal error, |
208 | | * this level shouldn't be seen. */ |
209 | | |
210 | | '*', '*', '*', '*', '*' /* >= 64 == overflows, this levels and higher |
211 | | * levels show a real bug!. */ |
212 | | }; |
213 | | |
214 | | #define fribidi_char_from_level(level) char_from_level_array[(level) + 1] |
215 | | |
216 | | static void |
217 | | print_types_re ( |
218 | | const FriBidiRun *pp |
219 | | ) |
220 | 0 | { |
221 | 0 | fribidi_assert (pp); |
222 | |
|
223 | 0 | MSG (" Run types : "); |
224 | 0 | for_run_list (pp, pp) |
225 | 0 | { |
226 | 0 | MSG6 ("%d:%d(%s)[%d,%d] ", |
227 | 0 | pp->pos, pp->len, fribidi_get_bidi_type_name (pp->type), pp->level, pp->isolate_level); |
228 | 0 | } |
229 | 0 | MSG ("\n"); |
230 | 0 | } |
231 | | |
232 | | static void |
233 | | print_resolved_levels ( |
234 | | const FriBidiRun *pp |
235 | | ) |
236 | 0 | { |
237 | 0 | fribidi_assert (pp); |
238 | |
|
239 | 0 | MSG (" Res. levels: "); |
240 | 0 | for_run_list (pp, pp) |
241 | 0 | { |
242 | 0 | register FriBidiStrIndex i; |
243 | 0 | for (i = RL_LEN (pp); i; i--) |
244 | 0 | MSG2 ("%c", fribidi_char_from_level (RL_LEVEL (pp))); |
245 | 0 | } |
246 | 0 | MSG ("\n"); |
247 | 0 | } |
248 | | |
249 | | static void |
250 | | print_resolved_types ( |
251 | | const FriBidiRun *pp |
252 | | ) |
253 | 0 | { |
254 | 0 | fribidi_assert (pp); |
255 | |
|
256 | 0 | MSG (" Res. types : "); |
257 | 0 | for_run_list (pp, pp) |
258 | 0 | { |
259 | 0 | FriBidiStrIndex i; |
260 | 0 | for (i = RL_LEN (pp); i; i--) |
261 | 0 | MSG2 ("%s ", fribidi_get_bidi_type_name (pp->type)); |
262 | 0 | } |
263 | 0 | MSG ("\n"); |
264 | 0 | } |
265 | | |
266 | | static void |
267 | | print_bidi_string ( |
268 | | /* input */ |
269 | | const FriBidiCharType *bidi_types, |
270 | | const FriBidiStrIndex len |
271 | | ) |
272 | 0 | { |
273 | 0 | register FriBidiStrIndex i; |
274 | |
|
275 | 0 | fribidi_assert (bidi_types); |
276 | |
|
277 | 0 | MSG (" Org. types : "); |
278 | 0 | for (i = 0; i < len; i++) |
279 | 0 | MSG2 ("%s ", fribidi_get_bidi_type_name (bidi_types[i])); |
280 | 0 | MSG ("\n"); |
281 | 0 | } |
282 | | |
283 | | static void print_pairing_nodes(FriBidiPairingNode *nodes) |
284 | 0 | { |
285 | 0 | MSG ("Pairs: "); |
286 | 0 | while (nodes) |
287 | 0 | { |
288 | 0 | MSG3 ("(%d, %d) ", nodes->open->pos, nodes->close->pos); |
289 | 0 | nodes = nodes->next; |
290 | 0 | } |
291 | 0 | MSG ("\n"); |
292 | 0 | } |
293 | | #endif /* DEBUG */ |
294 | | |
295 | | |
296 | | /*========================================================================= |
297 | | * define macros for push and pop the status in to / out of the stack |
298 | | *-------------------------------------------------------------------------*/ |
299 | | |
300 | | /* There are a few little points in pushing into and popping from the status |
301 | | stack: |
302 | | 1. when the embedding level is not valid (more than |
303 | | FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL=125), you must reject it, and not to push |
304 | | into the stack, but when you see a PDF, you must find the matching code, |
305 | | and if it was pushed in the stack, pop it, it means you must pop if and |
306 | | only if you have pushed the matching code, the over_pushed var counts the |
307 | | number of rejected codes so far. |
308 | | |
309 | | 2. there's a more confusing point too, when the embedding level is exactly |
310 | | FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL-1=124, an LRO, LRE, or LRI is rejected |
311 | | because the new level would be FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL+1=126, that |
312 | | is invalid; but an RLO, RLE, or RLI is accepted because the new level is |
313 | | FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL=125, that is valid, so the rejected codes |
314 | | may be not continuous in the logical order, in fact there are at most two |
315 | | continuous intervals of codes, with an RLO, RLE, or RLI between them. To |
316 | | support this case, the first_interval var counts the number of rejected |
317 | | codes in the first interval, when it is 0, means that there is only one |
318 | | interval. |
319 | | |
320 | | */ |
321 | | |
322 | | /* a. If this new level would be valid, then this embedding code is valid. |
323 | | Remember (push) the current embedding level and override status. |
324 | | Reset current level to this new level, and reset the override status to |
325 | | new_override. |
326 | | b. If the new level would not be valid, then this code is invalid. Don't |
327 | | change the current level or override status. |
328 | | */ |
329 | | #define PUSH_STATUS \ |
330 | 966k | FRIBIDI_BEGIN_STMT \ |
331 | 966k | if LIKELY(over_pushed == 0 \ |
332 | 966k | && isolate_overflow == 0 \ |
333 | 966k | && new_level <= FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL) \ |
334 | 966k | { \ |
335 | 63.8k | if UNLIKELY(level == FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL - 1) \ |
336 | 63.8k | first_interval = over_pushed; \ |
337 | 63.8k | status_stack[stack_size].level = level; \ |
338 | 63.8k | status_stack[stack_size].isolate_level = isolate_level; \ |
339 | 63.8k | status_stack[stack_size].isolate = isolate; \ |
340 | 63.8k | status_stack[stack_size].override = override; \ |
341 | 63.8k | stack_size++; \ |
342 | 63.8k | level = new_level; \ |
343 | 63.8k | override = new_override; \ |
344 | 902k | } else if LIKELY(isolate_overflow == 0) \ |
345 | 902k | over_pushed++; \ |
346 | 966k | FRIBIDI_END_STMT |
347 | | |
348 | | /* If there was a valid matching code, restore (pop) the last remembered |
349 | | (pushed) embedding level and directional override. |
350 | | */ |
351 | | #define POP_STATUS \ |
352 | 115k | FRIBIDI_BEGIN_STMT \ |
353 | 115k | if (stack_size) \ |
354 | 115k | { \ |
355 | 53.1k | if UNLIKELY(over_pushed > first_interval) \ |
356 | 53.1k | over_pushed--; \ |
357 | 53.1k | else \ |
358 | 53.1k | { \ |
359 | 36.2k | if LIKELY(over_pushed == first_interval) \ |
360 | 36.2k | first_interval = 0; \ |
361 | 36.2k | stack_size--; \ |
362 | 36.2k | level = status_stack[stack_size].level; \ |
363 | 36.2k | override = status_stack[stack_size].override; \ |
364 | 36.2k | isolate = status_stack[stack_size].isolate; \ |
365 | 36.2k | isolate_level = status_stack[stack_size].isolate_level; \ |
366 | 36.2k | } \ |
367 | 53.1k | } \ |
368 | 115k | FRIBIDI_END_STMT |
369 | | |
370 | | |
371 | | /* Return the type of previous run or the SOR, if already at the start of |
372 | | a level run. */ |
373 | | #define PREV_TYPE_OR_SOR(pp) \ |
374 | 3.99M | ( \ |
375 | 3.99M | RL_LEVEL(pp->prev) == RL_LEVEL(pp) ? \ |
376 | 3.99M | RL_TYPE(pp->prev) : \ |
377 | 3.99M | FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(pp->prev), RL_LEVEL(pp))) \ |
378 | 3.99M | ) |
379 | | |
380 | | /* Return the type of next run or the EOR, if already at the end of |
381 | | a level run. */ |
382 | | #define NEXT_TYPE_OR_EOR(pp) \ |
383 | | ( \ |
384 | | RL_LEVEL(pp->next) == RL_LEVEL(pp) ? \ |
385 | | RL_TYPE(pp->next) : \ |
386 | | FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(pp->next), RL_LEVEL(pp))) \ |
387 | | ) |
388 | | |
389 | | |
390 | | /* Return the embedding direction of a link. */ |
391 | | #define FRIBIDI_EMBEDDING_DIRECTION(link) \ |
392 | 7.56k | FRIBIDI_LEVEL_TO_DIR(RL_LEVEL(link)) |
393 | | |
394 | | |
395 | | FRIBIDI_ENTRY FriBidiParType |
396 | | fribidi_get_par_direction ( |
397 | | /* input */ |
398 | | const FriBidiCharType *bidi_types, |
399 | | const FriBidiStrIndex len |
400 | | ) |
401 | 0 | { |
402 | 0 | int valid_isolate_count = 0; |
403 | 0 | register FriBidiStrIndex i; |
404 | |
|
405 | 0 | fribidi_assert (bidi_types); |
406 | |
|
407 | 0 | for (i = 0; i < len; i++) |
408 | 0 | { |
409 | 0 | if (bidi_types[i] == FRIBIDI_TYPE_PDI) |
410 | 0 | { |
411 | | /* Ignore if there is no matching isolate */ |
412 | 0 | if (valid_isolate_count>0) |
413 | 0 | valid_isolate_count--; |
414 | 0 | } |
415 | 0 | else if (FRIBIDI_IS_ISOLATE(bidi_types[i])) |
416 | 0 | valid_isolate_count++; |
417 | 0 | else if (valid_isolate_count==0 && FRIBIDI_IS_LETTER (bidi_types[i])) |
418 | 0 | return FRIBIDI_IS_RTL (bidi_types[i]) ? FRIBIDI_PAR_RTL : |
419 | 0 | FRIBIDI_PAR_LTR; |
420 | 0 | } |
421 | | |
422 | 0 | return FRIBIDI_PAR_ON; |
423 | 0 | } |
424 | | |
425 | | /* Push a new entry to the pairing linked list */ |
426 | | static FriBidiPairingNode * pairing_nodes_push(FriBidiPairingNode *nodes, |
427 | | FriBidiRun *open, |
428 | | FriBidiRun *close) |
429 | 1.43M | { |
430 | 1.43M | FriBidiPairingNode *node = fribidi_malloc(sizeof(FriBidiPairingNode)); |
431 | 1.43M | node->open = open; |
432 | 1.43M | node->close = close; |
433 | 1.43M | node->next = nodes; |
434 | 1.43M | nodes = node; |
435 | 1.43M | return nodes; |
436 | 1.43M | } |
437 | | |
438 | | /* Sort by merge sort */ |
439 | | static void pairing_nodes_front_back_split(FriBidiPairingNode *source, |
440 | | /* output */ |
441 | | FriBidiPairingNode **front, |
442 | | FriBidiPairingNode **back) |
443 | 1.43M | { |
444 | 1.43M | FriBidiPairingNode *pfast, *pslow; |
445 | 1.43M | if (!source || !source->next) |
446 | 0 | { |
447 | 0 | *front = source; |
448 | 0 | *back = NULL; |
449 | 0 | } |
450 | 1.43M | else |
451 | 1.43M | { |
452 | 1.43M | pslow = source; |
453 | 1.43M | pfast = source->next; |
454 | 12.2M | while (pfast) |
455 | 10.8M | { |
456 | 10.8M | pfast= pfast->next; |
457 | 10.8M | if (pfast) |
458 | 9.89M | { |
459 | 9.89M | pfast = pfast->next; |
460 | 9.89M | pslow = pslow->next; |
461 | 9.89M | } |
462 | 10.8M | } |
463 | 1.43M | *front = source; |
464 | 1.43M | *back = pslow->next; |
465 | 1.43M | pslow->next = NULL; |
466 | 1.43M | } |
467 | 1.43M | } |
468 | | |
469 | | static FriBidiPairingNode * |
470 | | pairing_nodes_sorted_merge(FriBidiPairingNode *nodes1, |
471 | | FriBidiPairingNode *nodes2) |
472 | 12.9M | { |
473 | 12.9M | FriBidiPairingNode *res = NULL; |
474 | 12.9M | if (!nodes1) |
475 | 132k | return nodes2; |
476 | 12.8M | if (!nodes2) |
477 | 1.30M | return nodes1; |
478 | | |
479 | 11.5M | if (nodes1->open->pos < nodes2->open->pos) |
480 | 1.02M | { |
481 | 1.02M | res = nodes1; |
482 | 1.02M | res->next = pairing_nodes_sorted_merge(nodes1->next, nodes2); |
483 | 1.02M | } |
484 | 10.5M | else |
485 | 10.5M | { |
486 | 10.5M | res = nodes2; |
487 | 10.5M | res->next = pairing_nodes_sorted_merge(nodes1, nodes2->next); |
488 | 10.5M | } |
489 | 11.5M | return res; |
490 | 12.8M | } |
491 | | |
492 | | static void sort_pairing_nodes(FriBidiPairingNode **nodes) |
493 | 2.86M | { |
494 | 2.86M | FriBidiPairingNode *front, *back; |
495 | | |
496 | | /* 0 or 1 node case */ |
497 | 2.86M | if (!*nodes || !(*nodes)->next) |
498 | 1.43M | return; |
499 | | |
500 | 1.43M | pairing_nodes_front_back_split(*nodes, &front, &back); |
501 | 1.43M | sort_pairing_nodes(&front); |
502 | 1.43M | sort_pairing_nodes(&back); |
503 | 1.43M | *nodes = pairing_nodes_sorted_merge(front, back); |
504 | 1.43M | } |
505 | | |
506 | | static void free_pairing_nodes(FriBidiPairingNode *nodes) |
507 | 1.91k | { |
508 | 1.43M | while (nodes) |
509 | 1.43M | { |
510 | 1.43M | FriBidiPairingNode *p = nodes; |
511 | 1.43M | nodes = nodes->next; |
512 | 1.43M | fribidi_free(p); |
513 | 1.43M | } |
514 | 1.91k | } |
515 | | |
516 | | FRIBIDI_ENTRY FriBidiLevel |
517 | | fribidi_get_par_embedding_levels_ex ( |
518 | | /* input */ |
519 | | const FriBidiCharType *bidi_types, |
520 | | const FriBidiBracketType *bracket_types, |
521 | | const FriBidiStrIndex len, |
522 | | /* input and output */ |
523 | | FriBidiParType *pbase_dir, |
524 | | /* output */ |
525 | | FriBidiLevel *embedding_levels |
526 | | ) |
527 | 1.91k | { |
528 | 1.91k | FriBidiLevel base_level, max_level = 0; |
529 | 1.91k | FriBidiParType base_dir; |
530 | 1.91k | FriBidiRun *main_run_list = NULL, *explicits_list = NULL, *pp; |
531 | 1.91k | fribidi_boolean status = false; |
532 | 1.91k | int max_iso_level = 0; |
533 | | |
534 | 1.91k | if UNLIKELY |
535 | 1.91k | (!len) |
536 | 1 | { |
537 | 1 | status = true; |
538 | 1 | goto out; |
539 | 1 | } |
540 | | |
541 | 1.91k | DBG ("in fribidi_get_par_embedding_levels"); |
542 | | |
543 | 1.91k | fribidi_assert (bidi_types); |
544 | 1.91k | fribidi_assert (pbase_dir); |
545 | 1.91k | fribidi_assert (embedding_levels); |
546 | | |
547 | | /* Determinate character types */ |
548 | 1.91k | { |
549 | | /* Get run-length encoded character types */ |
550 | 1.91k | main_run_list = run_list_encode_bidi_types (bidi_types, bracket_types, len); |
551 | 1.91k | if UNLIKELY |
552 | 1.91k | (!main_run_list) goto out; |
553 | 1.91k | } |
554 | | |
555 | | /* Find base level */ |
556 | | /* If no strong base_dir was found, resort to the weak direction |
557 | | that was passed on input. */ |
558 | 1.91k | base_level = FRIBIDI_DIR_TO_LEVEL (*pbase_dir); |
559 | 1.91k | if (!FRIBIDI_IS_STRONG (*pbase_dir)) |
560 | | /* P2. P3. Search for first strong character and use its direction as |
561 | | base direction */ |
562 | 1.91k | { |
563 | 1.91k | int valid_isolate_count = 0; |
564 | 1.91k | for_run_list (pp, main_run_list) |
565 | 1.94M | { |
566 | 1.94M | if (RL_TYPE(pp) == FRIBIDI_TYPE_PDI) |
567 | 17.5k | { |
568 | | /* Ignore if there is no matching isolate */ |
569 | 17.5k | if (valid_isolate_count>0) |
570 | 12.6k | valid_isolate_count--; |
571 | 17.5k | } |
572 | 1.92M | else if (FRIBIDI_IS_ISOLATE(RL_TYPE(pp))) |
573 | 1.45M | valid_isolate_count++; |
574 | 472k | else if (valid_isolate_count==0 && FRIBIDI_IS_LETTER (RL_TYPE (pp))) |
575 | 753 | { |
576 | 753 | base_level = FRIBIDI_DIR_TO_LEVEL (RL_TYPE (pp)); |
577 | 753 | *pbase_dir = FRIBIDI_LEVEL_TO_DIR (base_level); |
578 | 753 | break; |
579 | 753 | } |
580 | 1.94M | } |
581 | 1.91k | } |
582 | 1.91k | base_dir = FRIBIDI_LEVEL_TO_DIR (base_level); |
583 | 1.91k | DBG2 (" base level : %c", fribidi_char_from_level (base_level)); |
584 | 1.91k | DBG2 (" base dir : %s", fribidi_get_bidi_type_name (base_dir)); |
585 | | |
586 | 1.91k | # if DEBUG |
587 | 1.91k | if UNLIKELY |
588 | 1.91k | (fribidi_debug_status ()) |
589 | 0 | { |
590 | 0 | print_types_re (main_run_list); |
591 | 0 | } |
592 | 1.91k | # endif /* DEBUG */ |
593 | | |
594 | | /* Explicit Levels and Directions */ |
595 | 1.91k | DBG ("explicit levels and directions"); |
596 | 1.91k | { |
597 | 1.91k | FriBidiLevel level, new_level = 0; |
598 | 1.91k | int isolate_level = 0; |
599 | 1.91k | FriBidiCharType override, new_override; |
600 | 1.91k | FriBidiStrIndex i; |
601 | 1.91k | int stack_size, over_pushed, first_interval; |
602 | 1.91k | int valid_isolate_count = 0; |
603 | 1.91k | int isolate_overflow = 0; |
604 | 1.91k | int isolate = 0; /* The isolate status flag */ |
605 | 1.91k | struct |
606 | 1.91k | { |
607 | 1.91k | FriBidiCharType override; /* only LTR, RTL and ON are valid */ |
608 | 1.91k | FriBidiLevel level; |
609 | 1.91k | int isolate; |
610 | 1.91k | int isolate_level; |
611 | 1.91k | } status_stack[FRIBIDI_BIDI_MAX_RESOLVED_LEVELS]; |
612 | 1.91k | FriBidiRun temp_link; |
613 | 1.91k | FriBidiRun *run_per_isolate_level[FRIBIDI_BIDI_MAX_RESOLVED_LEVELS]; |
614 | 1.91k | int prev_isolate_level = 0; /* When running over the isolate levels, remember the previous level */ |
615 | | |
616 | 1.91k | memset(run_per_isolate_level, 0, sizeof(run_per_isolate_level[0]) |
617 | 1.91k | * FRIBIDI_BIDI_MAX_RESOLVED_LEVELS); |
618 | | |
619 | | /* explicits_list is a list like main_run_list, that holds the explicit |
620 | | codes that are removed from main_run_list, to reinsert them later by |
621 | | calling the shadow_run_list. |
622 | | */ |
623 | 1.91k | explicits_list = new_run_list (); |
624 | 1.91k | if UNLIKELY |
625 | 1.91k | (!explicits_list) goto out; |
626 | | |
627 | | /* X1. Begin by setting the current embedding level to the paragraph |
628 | | embedding level. Set the directional override status to neutral, |
629 | | and directional isolate status to false. |
630 | | |
631 | | Process each character iteratively, applying rules X2 through X8. |
632 | | Only embedding levels from 0 to 123 are valid in this phase. */ |
633 | | |
634 | 1.91k | level = base_level; |
635 | 1.91k | override = FRIBIDI_TYPE_ON; |
636 | | /* stack */ |
637 | 1.91k | stack_size = 0; |
638 | 1.91k | over_pushed = 0; |
639 | 1.91k | first_interval = 0; |
640 | 1.91k | valid_isolate_count = 0; |
641 | 1.91k | isolate_overflow = 0; |
642 | | |
643 | 1.91k | for_run_list (pp, main_run_list) |
644 | 6.10M | { |
645 | 6.10M | FriBidiCharType this_type = RL_TYPE (pp); |
646 | 6.10M | RL_ISOLATE_LEVEL (pp) = isolate_level; |
647 | | |
648 | 6.10M | if (FRIBIDI_IS_EXPLICIT_OR_BN (this_type)) |
649 | 201k | { |
650 | 201k | if (FRIBIDI_IS_STRONG (this_type)) |
651 | 35.7k | { /* LRE, RLE, LRO, RLO */ |
652 | | /* 1. Explicit Embeddings */ |
653 | | /* X2. With each RLE, compute the least greater odd |
654 | | embedding level. */ |
655 | | /* X3. With each LRE, compute the least greater even |
656 | | embedding level. */ |
657 | | /* 2. Explicit Overrides */ |
658 | | /* X4. With each RLO, compute the least greater odd |
659 | | embedding level. */ |
660 | | /* X5. With each LRO, compute the least greater even |
661 | | embedding level. */ |
662 | 35.7k | new_override = FRIBIDI_EXPLICIT_TO_OVERRIDE_DIR (this_type); |
663 | 904k | for (i = RL_LEN (pp); i; i--) |
664 | 868k | { |
665 | 868k | new_level = |
666 | 868k | ((level + FRIBIDI_DIR_TO_LEVEL (this_type) + 2) & ~1) - |
667 | 868k | FRIBIDI_DIR_TO_LEVEL (this_type); |
668 | 868k | isolate = 0; |
669 | 868k | PUSH_STATUS; |
670 | 868k | } |
671 | 35.7k | } |
672 | 165k | else if (this_type == FRIBIDI_TYPE_PDF) |
673 | 141k | { |
674 | | /* 3. Terminating Embeddings and overrides */ |
675 | | /* X7. With each PDF, determine the matching embedding or |
676 | | override code. */ |
677 | 164k | for (i = RL_LEN (pp); i; i--) |
678 | 152k | { |
679 | 152k | if (stack_size && status_stack[stack_size-1].isolate != 0) |
680 | 129k | break; |
681 | 152k | POP_STATUS; |
682 | 23.2k | } |
683 | 141k | } |
684 | | |
685 | | /* X9. Remove all RLE, LRE, RLO, LRO, PDF, and BN codes. */ |
686 | | /* Remove element and add it to explicits_list */ |
687 | 201k | RL_LEVEL (pp) = FRIBIDI_SENTINEL; |
688 | 201k | temp_link.next = pp->next; |
689 | 201k | move_node_before (pp, explicits_list); |
690 | 201k | pp = &temp_link; |
691 | 201k | } |
692 | 5.90M | else if (this_type == FRIBIDI_TYPE_PDI) |
693 | | /* X6a. pop the direction of the stack */ |
694 | 913k | { |
695 | 1.82M | for (i = RL_LEN (pp); i; i--) |
696 | 913k | { |
697 | 913k | if (isolate_overflow > 0) |
698 | 12.6k | { |
699 | 12.6k | isolate_overflow--; |
700 | 12.6k | RL_LEVEL (pp) = level; |
701 | 12.6k | } |
702 | | |
703 | 900k | else if (valid_isolate_count > 0) |
704 | 9.80k | { |
705 | | /* Pop away all LRE,RLE,LRO, RLO levels |
706 | | from the stack, as these are implicitly |
707 | | terminated by the PDI */ |
708 | 39.4k | while (stack_size && !status_stack[stack_size-1].isolate) |
709 | 29.6k | POP_STATUS; |
710 | 9.80k | over_pushed = 0; /* The PDI resets the overpushed! */ |
711 | 9.80k | POP_STATUS; |
712 | 9.80k | if (isolate_level>0) |
713 | 6.87k | isolate_level--; |
714 | 9.80k | valid_isolate_count--; |
715 | 9.80k | RL_LEVEL (pp) = level; |
716 | 9.80k | RL_ISOLATE_LEVEL (pp) = isolate_level; |
717 | 9.80k | } |
718 | 890k | else |
719 | 890k | { |
720 | | /* Ignore isolated PDI's by turning them into ON's */ |
721 | 890k | RL_TYPE (pp) = FRIBIDI_TYPE_ON; |
722 | 890k | RL_LEVEL (pp) = level; |
723 | 890k | } |
724 | 913k | } |
725 | 913k | } |
726 | 4.99M | else if (FRIBIDI_IS_ISOLATE(this_type)) |
727 | 1.47M | { |
728 | | /* TBD support RL_LEN > 1 */ |
729 | 1.47M | new_override = FRIBIDI_TYPE_ON; |
730 | 1.47M | isolate = 1; |
731 | 1.47M | if (this_type == FRIBIDI_TYPE_LRI) |
732 | 1.08M | new_level = level + 2 - (level%2); |
733 | 393k | else if (this_type == FRIBIDI_TYPE_RLI) |
734 | 7.48k | new_level = level + 1 + (level%2); |
735 | 386k | else if (this_type == FRIBIDI_TYPE_FSI) |
736 | 386k | { |
737 | | /* Search for a local strong character until we |
738 | | meet the corresponding PDI or the end of the |
739 | | paragraph */ |
740 | 386k | FriBidiRun *fsi_pp; |
741 | 386k | int isolate_count = 0; |
742 | 386k | int fsi_base_level = 0; |
743 | 386k | for_run_list (fsi_pp, pp) |
744 | 10.3G | { |
745 | 10.3G | if (RL_TYPE(fsi_pp) == FRIBIDI_TYPE_PDI) |
746 | 81.4M | { |
747 | 81.4M | isolate_count--; |
748 | 81.4M | if (valid_isolate_count < 0) |
749 | 0 | break; |
750 | 81.4M | } |
751 | 10.2G | else if (FRIBIDI_IS_ISOLATE(RL_TYPE(fsi_pp))) |
752 | 3.79G | isolate_count++; |
753 | 6.45G | else if (isolate_count==0 && FRIBIDI_IS_LETTER (RL_TYPE (fsi_pp))) |
754 | 17.0k | { |
755 | 17.0k | fsi_base_level = FRIBIDI_DIR_TO_LEVEL (RL_TYPE (fsi_pp)); |
756 | 17.0k | break; |
757 | 17.0k | } |
758 | 10.3G | } |
759 | | |
760 | | /* Same behavior like RLI and LRI above */ |
761 | 386k | if (FRIBIDI_LEVEL_IS_RTL (fsi_base_level)) |
762 | 814 | new_level = level + 1 + (level%2); |
763 | 385k | else |
764 | 385k | new_level = level + 2 - (level%2); |
765 | 386k | } |
766 | | |
767 | 1.47M | RL_LEVEL (pp) = level; |
768 | 1.47M | RL_ISOLATE_LEVEL (pp) = isolate_level; |
769 | 1.47M | if (isolate_level < FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL-1) |
770 | 113k | isolate_level++; |
771 | | |
772 | 1.47M | if (!FRIBIDI_IS_NEUTRAL (override)) |
773 | 102k | RL_TYPE (pp) = override; |
774 | | |
775 | 1.47M | if (new_level <= FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL) |
776 | 97.2k | { |
777 | 97.2k | valid_isolate_count++; |
778 | 97.2k | PUSH_STATUS; |
779 | 97.2k | level = new_level; |
780 | 97.2k | } |
781 | 1.38M | else |
782 | 1.38M | isolate_overflow += 1; |
783 | 1.47M | } |
784 | 3.51M | else if (this_type == FRIBIDI_TYPE_BS) |
785 | 336 | { |
786 | | /* X8. All explicit directional embeddings and overrides are |
787 | | completely terminated at the end of each paragraph. Paragraph |
788 | | separators are not included in the embedding. */ |
789 | 336 | break; |
790 | 336 | } |
791 | 3.51M | else |
792 | 3.51M | { |
793 | | /* X6. For all types besides RLE, LRE, RLO, LRO, and PDF: |
794 | | a. Set the level of the current character to the current |
795 | | embedding level. |
796 | | b. Whenever the directional override status is not neutral, |
797 | | reset the current character type to the directional override |
798 | | status. */ |
799 | 3.51M | RL_LEVEL (pp) = level; |
800 | 3.51M | if (!FRIBIDI_IS_NEUTRAL (override)) |
801 | 192k | RL_TYPE (pp) = override; |
802 | 3.51M | } |
803 | 6.10M | } |
804 | | |
805 | | /* Build the isolate_level connections */ |
806 | 1.91k | prev_isolate_level = 0; |
807 | 1.91k | for_run_list (pp, main_run_list) |
808 | 6.40M | { |
809 | 6.40M | int isolate_level = RL_ISOLATE_LEVEL (pp); |
810 | 6.40M | int i; |
811 | | |
812 | | /* When going from an upper to a lower level, zero out all higher levels |
813 | | in order not erroneous connections! */ |
814 | 6.40M | if (isolate_level<prev_isolate_level) |
815 | 96.8k | for (i=isolate_level+1; i<=prev_isolate_level; i++) |
816 | 85.9k | run_per_isolate_level[i]=0; |
817 | 6.40M | prev_isolate_level = isolate_level; |
818 | | |
819 | 6.40M | if (run_per_isolate_level[isolate_level]) |
820 | 6.29M | { |
821 | 6.29M | run_per_isolate_level[isolate_level]->next_isolate = pp; |
822 | 6.29M | pp->prev_isolate = run_per_isolate_level[isolate_level]; |
823 | 6.29M | } |
824 | 6.40M | run_per_isolate_level[isolate_level] = pp; |
825 | 6.40M | } |
826 | | |
827 | | /* Implementing X8. It has no effect on a single paragraph! */ |
828 | 1.91k | level = base_level; |
829 | 1.91k | override = FRIBIDI_TYPE_ON; |
830 | 1.91k | stack_size = 0; |
831 | 1.91k | over_pushed = 0; |
832 | 1.91k | } |
833 | | /* X10. The remaining rules are applied to each run of characters at the |
834 | | same level. For each run, determine the start-of-level-run (sor) and |
835 | | end-of-level-run (eor) type, either L or R. This depends on the |
836 | | higher of the two levels on either side of the boundary (at the start |
837 | | or end of the paragraph, the level of the 'other' run is the base |
838 | | embedding level). If the higher level is odd, the type is R, otherwise |
839 | | it is L. */ |
840 | | /* Resolving Implicit Levels can be done out of X10 loop, so only change |
841 | | of Resolving Weak Types and Resolving Neutral Types is needed. */ |
842 | | |
843 | 0 | compact_list (main_run_list); |
844 | | |
845 | 1.91k | # if DEBUG |
846 | 1.91k | if UNLIKELY |
847 | 1.91k | (fribidi_debug_status ()) |
848 | 0 | { |
849 | 0 | print_types_re (main_run_list); |
850 | 0 | print_bidi_string (bidi_types, len); |
851 | 0 | print_resolved_levels (main_run_list); |
852 | 0 | print_resolved_types (main_run_list); |
853 | 0 | } |
854 | 1.91k | # endif /* DEBUG */ |
855 | | |
856 | | /* 4. Resolving weak types. Also calculate the maximum isolate level */ |
857 | 1.91k | max_iso_level = 0; |
858 | 1.91k | DBG ("4a. resolving weak types"); |
859 | 1.91k | { |
860 | 1.91k | int last_strong_stack[FRIBIDI_BIDI_MAX_RESOLVED_LEVELS]; |
861 | 1.91k | FriBidiCharType prev_type_orig; |
862 | 1.91k | fribidi_boolean w4; |
863 | | |
864 | 1.91k | last_strong_stack[0] = base_dir; |
865 | | |
866 | 1.91k | for_run_list (pp, main_run_list) |
867 | 4.01M | { |
868 | 4.01M | register FriBidiCharType prev_type, this_type, next_type; |
869 | 4.01M | FriBidiRun *ppp_prev, *ppp_next; |
870 | 4.01M | int iso_level; |
871 | | |
872 | 4.01M | ppp_prev = get_adjacent_run(pp, false, false); |
873 | 4.01M | ppp_next = get_adjacent_run(pp, true, false); |
874 | | |
875 | 4.01M | this_type = RL_TYPE (pp); |
876 | 4.01M | iso_level = RL_ISOLATE_LEVEL(pp); |
877 | | |
878 | 4.01M | if (iso_level > max_iso_level) |
879 | 30.2k | max_iso_level = iso_level; |
880 | | |
881 | 4.01M | if (RL_LEVEL(ppp_prev) == RL_LEVEL(pp)) |
882 | 3.89M | prev_type = RL_TYPE(ppp_prev); |
883 | 120k | else |
884 | 120k | prev_type = FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(ppp_prev), RL_LEVEL(pp))); |
885 | | |
886 | 4.01M | if (RL_LEVEL(ppp_next) == RL_LEVEL(pp)) |
887 | 3.88M | next_type = RL_TYPE(ppp_next); |
888 | 122k | else |
889 | 122k | next_type = FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(ppp_next), RL_LEVEL(pp))); |
890 | | |
891 | 4.01M | if (FRIBIDI_IS_STRONG (prev_type)) |
892 | 630k | last_strong_stack[iso_level] = prev_type; |
893 | | |
894 | | /* W1. NSM |
895 | | Examine each non-spacing mark (NSM) in the level run, and change the |
896 | | type of the NSM to the type of the previous character. If the NSM |
897 | | is at the start of the level run, it will get the type of sor. */ |
898 | | /* Implementation note: it is important that if the previous character |
899 | | is not sor, then we should merge this run with the previous, |
900 | | because of rules like W5, that we assume all of a sequence of |
901 | | adjacent ETs are in one FriBidiRun. */ |
902 | 4.01M | if (this_type == FRIBIDI_TYPE_NSM) |
903 | 6.84k | { |
904 | | /* New rule in Unicode 6.3 */ |
905 | 6.84k | if (FRIBIDI_IS_ISOLATE (RL_TYPE (pp->prev))) |
906 | 1.36k | RL_TYPE(pp) = FRIBIDI_TYPE_ON; |
907 | | |
908 | 6.84k | if (RL_LEVEL (ppp_prev) == RL_LEVEL (pp)) |
909 | 6.27k | { |
910 | 6.27k | if (ppp_prev == pp->prev) |
911 | 5.99k | pp = merge_with_prev (pp); |
912 | 6.27k | } |
913 | 572 | else |
914 | 572 | RL_TYPE (pp) = prev_type; |
915 | | |
916 | 6.84k | if (prev_type == next_type && RL_LEVEL (pp) == RL_LEVEL (pp->next)) |
917 | 3.99k | { |
918 | 3.99k | if (ppp_next == pp->next) |
919 | 3.40k | pp = merge_with_prev (pp->next); |
920 | 3.99k | } |
921 | 6.84k | continue; /* As we know the next condition cannot be true. */ |
922 | 6.84k | } |
923 | | |
924 | | /* W2: European numbers. */ |
925 | 4.00M | if (this_type == FRIBIDI_TYPE_EN && last_strong_stack[iso_level] == FRIBIDI_TYPE_AL) |
926 | 1.40k | { |
927 | 1.40k | RL_TYPE (pp) = FRIBIDI_TYPE_AN; |
928 | | |
929 | | /* Resolving dependency of loops for rules W1 and W2, so we |
930 | | can merge them in one loop. */ |
931 | 1.40k | if (next_type == FRIBIDI_TYPE_NSM) |
932 | 322 | RL_TYPE (ppp_next) = FRIBIDI_TYPE_AN; |
933 | 1.40k | } |
934 | 4.00M | } |
935 | | |
936 | 1.91k | # if DEBUG |
937 | 1.91k | if UNLIKELY |
938 | 1.91k | (fribidi_debug_status ()) |
939 | 0 | { |
940 | 0 | print_resolved_levels (main_run_list); |
941 | 0 | print_resolved_types (main_run_list); |
942 | 0 | } |
943 | 1.91k | # endif /* DEBUG */ |
944 | | |
945 | | /* The last iso level is used to invalidate the the last strong values when going from |
946 | | a higher to a lower iso level. When this occur, all "last_strong" values are |
947 | | set to the base_dir. */ |
948 | 1.91k | last_strong_stack[0] = base_dir; |
949 | | |
950 | 1.91k | DBG ("4b. resolving weak types. W4 and W5"); |
951 | | |
952 | | /* Resolving dependency of loops for rules W4 and W5, W5 may |
953 | | want to prevent W4 to take effect in the next turn, do this |
954 | | through "w4". */ |
955 | 1.91k | w4 = true; |
956 | | /* Resolving dependency of loops for rules W4 and W5 with W7, |
957 | | W7 may change an EN to L but it sets the prev_type_orig if needed, |
958 | | so W4 and W5 in next turn can still do their works. */ |
959 | 1.91k | prev_type_orig = FRIBIDI_TYPE_ON; |
960 | | |
961 | | /* Each isolate level has its own memory of the last strong character */ |
962 | 1.91k | for_run_list (pp, main_run_list) |
963 | 4.00M | { |
964 | 4.00M | register FriBidiCharType prev_type, this_type, next_type; |
965 | 4.00M | int iso_level; |
966 | 4.00M | FriBidiRun *ppp_prev, *ppp_next; |
967 | | |
968 | 4.00M | this_type = RL_TYPE (pp); |
969 | 4.00M | iso_level = RL_ISOLATE_LEVEL(pp); |
970 | | |
971 | 4.00M | ppp_prev = get_adjacent_run(pp, false, false); |
972 | 4.00M | ppp_next = get_adjacent_run(pp, true, false); |
973 | | |
974 | 4.00M | if (RL_LEVEL(ppp_prev) == RL_LEVEL(pp)) |
975 | 3.88M | prev_type = RL_TYPE(ppp_prev); |
976 | 120k | else |
977 | 120k | prev_type = FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(ppp_prev), RL_LEVEL(pp))); |
978 | | |
979 | 4.00M | if (RL_LEVEL(ppp_next) == RL_LEVEL(pp)) |
980 | 3.88M | next_type = RL_TYPE(ppp_next); |
981 | 122k | else |
982 | 122k | next_type = FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(ppp_next), RL_LEVEL(pp))); |
983 | | |
984 | 4.00M | if (FRIBIDI_IS_STRONG (prev_type)) |
985 | 632k | last_strong_stack[iso_level] = prev_type; |
986 | | |
987 | | /* W2 ??? */ |
988 | | |
989 | | /* W3: Change ALs to R. */ |
990 | 4.00M | if (this_type == FRIBIDI_TYPE_AL) |
991 | 1.44k | { |
992 | 1.44k | RL_TYPE (pp) = FRIBIDI_TYPE_RTL; |
993 | 1.44k | w4 = true; |
994 | 1.44k | prev_type_orig = FRIBIDI_TYPE_ON; |
995 | 1.44k | continue; |
996 | 1.44k | } |
997 | | |
998 | | /* W4. A single european separator changes to a european number. |
999 | | A single common separator between two numbers of the same type |
1000 | | changes to that type. */ |
1001 | 4.00M | if (w4 |
1002 | 4.00M | && RL_LEN (pp) == 1 && FRIBIDI_IS_ES_OR_CS (this_type) |
1003 | 4.00M | && FRIBIDI_IS_NUMBER (prev_type_orig) |
1004 | 4.00M | && prev_type_orig == next_type |
1005 | 4.00M | && (prev_type_orig == FRIBIDI_TYPE_EN |
1006 | 1.42k | || this_type == FRIBIDI_TYPE_CS)) |
1007 | 1.08k | { |
1008 | 1.08k | RL_TYPE (pp) = prev_type; |
1009 | 1.08k | this_type = RL_TYPE (pp); |
1010 | 1.08k | } |
1011 | 4.00M | w4 = true; |
1012 | | |
1013 | | /* W5. A sequence of European terminators adjacent to European |
1014 | | numbers changes to All European numbers. */ |
1015 | 4.00M | if (this_type == FRIBIDI_TYPE_ET |
1016 | 4.00M | && (prev_type_orig == FRIBIDI_TYPE_EN |
1017 | 3.67k | || next_type == FRIBIDI_TYPE_EN)) |
1018 | 2.67k | { |
1019 | 2.67k | RL_TYPE (pp) = FRIBIDI_TYPE_EN; |
1020 | 2.67k | w4 = false; |
1021 | 2.67k | this_type = RL_TYPE (pp); |
1022 | 2.67k | } |
1023 | | |
1024 | | /* W6. Otherwise change separators and terminators to other neutral. */ |
1025 | 4.00M | if (FRIBIDI_IS_NUMBER_SEPARATOR_OR_TERMINATOR (this_type)) |
1026 | 5.54k | RL_TYPE (pp) = FRIBIDI_TYPE_ON; |
1027 | | |
1028 | | /* W7. Change european numbers to L. */ |
1029 | 4.00M | if (this_type == FRIBIDI_TYPE_EN && last_strong_stack[iso_level] == FRIBIDI_TYPE_LTR) |
1030 | 6.24k | { |
1031 | 6.24k | RL_TYPE (pp) = FRIBIDI_TYPE_LTR; |
1032 | 6.24k | prev_type_orig = (RL_LEVEL (pp) == RL_LEVEL (pp->next) ? |
1033 | 6.15k | FRIBIDI_TYPE_EN : FRIBIDI_TYPE_ON); |
1034 | 6.24k | } |
1035 | 3.99M | else |
1036 | 3.99M | prev_type_orig = PREV_TYPE_OR_SOR (pp->next); |
1037 | 4.00M | } |
1038 | 1.91k | } |
1039 | | |
1040 | 1.91k | compact_neutrals (main_run_list); |
1041 | | |
1042 | 1.91k | # if DEBUG |
1043 | 1.91k | if UNLIKELY |
1044 | 1.91k | (fribidi_debug_status ()) |
1045 | 0 | { |
1046 | 0 | print_resolved_levels (main_run_list); |
1047 | 0 | print_resolved_types (main_run_list); |
1048 | 0 | } |
1049 | 1.91k | # endif /* DEBUG */ |
1050 | | |
1051 | | /* 5. Resolving Neutral Types */ |
1052 | | |
1053 | 1.91k | DBG ("5. resolving neutral types - N0"); |
1054 | 1.91k | { |
1055 | | /* BD16 - Build list of all pairs*/ |
1056 | 1.91k | int num_iso_levels = max_iso_level + 1; |
1057 | 1.91k | FriBidiPairingNode *pairing_nodes = NULL; |
1058 | 1.91k | FriBidiRun *local_bracket_stack[FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL][LOCAL_BRACKET_SIZE]; |
1059 | 1.91k | FriBidiRun **bracket_stack[FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL]; |
1060 | 1.91k | int bracket_stack_size[FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL]; |
1061 | 1.91k | int last_level = RL_LEVEL(main_run_list); |
1062 | 1.91k | int last_iso_level = 0; |
1063 | | |
1064 | 1.91k | memset(bracket_stack, 0, sizeof(bracket_stack[0])*num_iso_levels); |
1065 | 1.91k | memset(bracket_stack_size, 0, sizeof(bracket_stack_size[0])*num_iso_levels); |
1066 | | |
1067 | | /* populate the bracket_size. The first LOCAL_BRACKET_SIZE entries |
1068 | | of the stack are one the stack. Allocate the rest of the entries. |
1069 | | */ |
1070 | 1.91k | { |
1071 | 1.91k | int iso_level; |
1072 | 32.5k | for (iso_level=0; iso_level < LOCAL_BRACKET_SIZE; iso_level++) |
1073 | 30.6k | bracket_stack[iso_level] = local_bracket_stack[iso_level]; |
1074 | | |
1075 | 25.0k | for (iso_level=LOCAL_BRACKET_SIZE; iso_level < num_iso_levels; iso_level++) |
1076 | 23.1k | bracket_stack[iso_level] = fribidi_malloc (sizeof (bracket_stack[0]) |
1077 | 23.1k | * FRIBIDI_BIDI_MAX_NESTED_BRACKET_PAIRS); |
1078 | 1.91k | } |
1079 | | |
1080 | | /* Build the bd16 pair stack. */ |
1081 | 1.91k | for_run_list (pp, main_run_list) |
1082 | 3.80M | { |
1083 | 3.80M | int level = RL_LEVEL(pp); |
1084 | 3.80M | int iso_level = RL_ISOLATE_LEVEL(pp); |
1085 | 3.80M | FriBidiBracketType brack_prop = RL_BRACKET_TYPE(pp); |
1086 | | |
1087 | | /* Interpret the isolating run sequence as such that they |
1088 | | end at a change in the level, unless the iso_level has been |
1089 | | raised. */ |
1090 | 3.80M | if (level != last_level && last_iso_level == iso_level) |
1091 | 6.05k | bracket_stack_size[last_iso_level] = 0; |
1092 | | |
1093 | 3.80M | if (brack_prop!= FRIBIDI_NO_BRACKET |
1094 | 3.80M | && RL_TYPE(pp)==FRIBIDI_TYPE_ON) |
1095 | 2.91M | { |
1096 | 2.91M | if (FRIBIDI_IS_BRACKET_OPEN(brack_prop)) |
1097 | 1.45M | { |
1098 | 1.45M | if (bracket_stack_size[iso_level]==FRIBIDI_BIDI_MAX_NESTED_BRACKET_PAIRS) |
1099 | 22 | break; |
1100 | | |
1101 | | /* push onto the pair stack */ |
1102 | 1.45M | bracket_stack[iso_level][bracket_stack_size[iso_level]++] = pp; |
1103 | 1.45M | } |
1104 | 1.46M | else |
1105 | 1.46M | { |
1106 | 1.46M | int stack_idx = bracket_stack_size[iso_level] - 1; |
1107 | 1.46M | while (stack_idx >= 0) |
1108 | 1.43M | { |
1109 | 1.43M | FriBidiBracketType se_brack_prop = RL_BRACKET_TYPE(bracket_stack[iso_level][stack_idx]); |
1110 | 1.43M | if (FRIBIDI_BRACKET_ID(se_brack_prop) == FRIBIDI_BRACKET_ID(brack_prop)) |
1111 | 1.43M | { |
1112 | 1.43M | bracket_stack_size[iso_level] = stack_idx; |
1113 | | |
1114 | 1.43M | pairing_nodes = pairing_nodes_push(pairing_nodes, |
1115 | 1.43M | bracket_stack[iso_level][stack_idx], |
1116 | 1.43M | pp); |
1117 | 1.43M | break; |
1118 | 1.43M | } |
1119 | 5.22k | stack_idx--; |
1120 | 5.22k | } |
1121 | 1.46M | } |
1122 | 2.91M | } |
1123 | 3.80M | last_level = level; |
1124 | 3.80M | last_iso_level = iso_level; |
1125 | 3.80M | } |
1126 | | |
1127 | | /* The list must now be sorted for the next algo to work! */ |
1128 | 1.91k | sort_pairing_nodes(&pairing_nodes); |
1129 | | |
1130 | 1.91k | # if DEBUG |
1131 | 1.91k | if UNLIKELY |
1132 | 1.91k | (fribidi_debug_status ()) |
1133 | 0 | { |
1134 | 0 | print_pairing_nodes (pairing_nodes); |
1135 | 0 | } |
1136 | 1.91k | # endif /* DEBUG */ |
1137 | | |
1138 | | /* Start the N0 */ |
1139 | 1.91k | { |
1140 | 1.91k | FriBidiPairingNode *ppairs = pairing_nodes; |
1141 | 1.43M | while (ppairs) |
1142 | 1.43M | { |
1143 | 1.43M | int embedding_level = ppairs->open->level; |
1144 | | |
1145 | | /* Find matching strong. */ |
1146 | 1.43M | fribidi_boolean found = false; |
1147 | 1.43M | FriBidiRun *ppn; |
1148 | 514M | for (ppn = ppairs->open; ppn!= ppairs->close; ppn = ppn->next) |
1149 | 513M | { |
1150 | 513M | FriBidiCharType this_type = RL_TYPE_AN_EN_AS_RTL(ppn); |
1151 | | |
1152 | | /* Calculate level like in resolve implicit levels below to prevent |
1153 | | embedded levels not to match the base_level */ |
1154 | 513M | int this_level = RL_LEVEL (ppn) + |
1155 | 513M | (FRIBIDI_LEVEL_IS_RTL (RL_LEVEL(ppn)) ^ FRIBIDI_DIR_TO_LEVEL (this_type)); |
1156 | | |
1157 | | /* N0b */ |
1158 | 513M | if (FRIBIDI_IS_STRONG (this_type) && this_level == embedding_level) |
1159 | 124k | { |
1160 | 124k | RL_TYPE(ppairs->open) = RL_TYPE(ppairs->close) = this_level%2 ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR; |
1161 | 124k | found = true; |
1162 | 124k | break; |
1163 | 124k | } |
1164 | 513M | } |
1165 | | |
1166 | | /* N0c */ |
1167 | | /* Search for any strong type preceding and within the bracket pair */ |
1168 | 1.43M | if (!found) |
1169 | 1.30M | { |
1170 | | /* Search for a preceding strong */ |
1171 | 1.30M | int prec_strong_level = embedding_level; /* TBDov! Extract from Isolate level in effect */ |
1172 | 1.30M | int iso_level = RL_ISOLATE_LEVEL(ppairs->open); |
1173 | 475M | for (ppn = ppairs->open->prev; ppn->type != FRIBIDI_TYPE_SENTINEL; ppn=ppn->prev) |
1174 | 475M | { |
1175 | 475M | FriBidiCharType this_type = RL_TYPE_AN_EN_AS_RTL(ppn); |
1176 | 475M | if (FRIBIDI_IS_STRONG (this_type) && RL_ISOLATE_LEVEL(ppn) == iso_level) |
1177 | 1.30M | { |
1178 | 1.30M | prec_strong_level = RL_LEVEL (ppn) + |
1179 | 1.30M | (FRIBIDI_LEVEL_IS_RTL (RL_LEVEL(ppn)) ^ FRIBIDI_DIR_TO_LEVEL (this_type)); |
1180 | | |
1181 | 1.30M | break; |
1182 | 1.30M | } |
1183 | 475M | } |
1184 | | |
1185 | 117M | for (ppn = ppairs->open; ppn!= ppairs->close; ppn = ppn->next) |
1186 | 116M | { |
1187 | 116M | FriBidiCharType this_type = RL_TYPE_AN_EN_AS_RTL(ppn); |
1188 | 116M | if (FRIBIDI_IS_STRONG (this_type) && RL_ISOLATE_LEVEL(ppn) == iso_level) |
1189 | 4.05k | { |
1190 | | /* By constraint this is opposite the embedding direction, |
1191 | | since we did not match the N0b rule. We must now |
1192 | | compare with the preceding strong to establish whether |
1193 | | to apply N0c1 (opposite) or N0c2 embedding */ |
1194 | 4.05k | RL_TYPE(ppairs->open) = RL_TYPE(ppairs->close) = prec_strong_level % 2 ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR; |
1195 | 4.05k | found = true; |
1196 | 4.05k | break; |
1197 | 4.05k | } |
1198 | 116M | } |
1199 | 1.30M | } |
1200 | | |
1201 | 1.43M | ppairs = ppairs->next; |
1202 | 1.43M | } |
1203 | | |
1204 | 1.91k | free_pairing_nodes(pairing_nodes); |
1205 | | |
1206 | 1.91k | if (num_iso_levels >= LOCAL_BRACKET_SIZE) |
1207 | 396 | { |
1208 | 396 | int i; |
1209 | | /* Only need to free the non static members */ |
1210 | 23.4k | for (i=LOCAL_BRACKET_SIZE; i<num_iso_levels; i++) |
1211 | 23.1k | fribidi_free(bracket_stack[i]); |
1212 | 396 | } |
1213 | | |
1214 | | /* Remove the bracket property and re-compact */ |
1215 | 1.91k | { |
1216 | 1.91k | const FriBidiBracketType NoBracket = FRIBIDI_NO_BRACKET; |
1217 | 1.91k | for_run_list (pp, main_run_list) |
1218 | 3.98M | pp->bracket_type = NoBracket; |
1219 | 1.91k | compact_neutrals (main_run_list); |
1220 | 1.91k | } |
1221 | 1.91k | } |
1222 | | |
1223 | 1.91k | # if DEBUG |
1224 | 1.91k | if UNLIKELY |
1225 | 1.91k | (fribidi_debug_status ()) |
1226 | 0 | { |
1227 | 0 | print_resolved_levels (main_run_list); |
1228 | 0 | print_resolved_types (main_run_list); |
1229 | 0 | } |
1230 | 1.91k | # endif /* DEBUG */ |
1231 | 1.91k | } |
1232 | | |
1233 | 1.91k | DBG ("resolving neutral types - N1+N2"); |
1234 | 1.91k | { |
1235 | 1.91k | for_run_list (pp, main_run_list) |
1236 | 921k | { |
1237 | 921k | FriBidiCharType prev_type, this_type, next_type; |
1238 | 921k | FriBidiRun *ppp_prev, *ppp_next; |
1239 | | |
1240 | 921k | ppp_prev = get_adjacent_run(pp, false, false); |
1241 | 921k | ppp_next = get_adjacent_run(pp, true, false); |
1242 | | |
1243 | | /* "European and Arabic numbers are treated as though they were R" |
1244 | | FRIBIDI_CHANGE_NUMBER_TO_RTL does this. */ |
1245 | 921k | this_type = FRIBIDI_CHANGE_NUMBER_TO_RTL (RL_TYPE (pp)); |
1246 | | |
1247 | 921k | if (RL_LEVEL(ppp_prev) == RL_LEVEL(pp)) |
1248 | 801k | prev_type = FRIBIDI_CHANGE_NUMBER_TO_RTL (RL_TYPE(ppp_prev)); |
1249 | 120k | else |
1250 | 120k | prev_type = FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(ppp_prev), RL_LEVEL(pp))); |
1251 | | |
1252 | 921k | if (RL_LEVEL(ppp_next) == RL_LEVEL(pp)) |
1253 | 799k | next_type = FRIBIDI_CHANGE_NUMBER_TO_RTL (RL_TYPE(ppp_next)); |
1254 | 122k | else |
1255 | 122k | next_type = FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(ppp_next), RL_LEVEL(pp))); |
1256 | | |
1257 | 921k | if (FRIBIDI_IS_NEUTRAL (this_type)) |
1258 | 315k | RL_TYPE (pp) = (prev_type == next_type) ? |
1259 | 308k | /* N1. */ prev_type : |
1260 | 315k | /* N2. */ FRIBIDI_EMBEDDING_DIRECTION (pp); |
1261 | 921k | } |
1262 | 1.91k | } |
1263 | | |
1264 | 1.91k | compact_list (main_run_list); |
1265 | | |
1266 | 1.91k | # if DEBUG |
1267 | 1.91k | if UNLIKELY |
1268 | 1.91k | (fribidi_debug_status ()) |
1269 | 0 | { |
1270 | 0 | print_resolved_levels (main_run_list); |
1271 | 0 | print_resolved_types (main_run_list); |
1272 | 0 | } |
1273 | 1.91k | # endif /* DEBUG */ |
1274 | | |
1275 | | /* 6. Resolving implicit levels */ |
1276 | 1.91k | DBG ("resolving implicit levels"); |
1277 | 1.91k | { |
1278 | 1.91k | max_level = base_level; |
1279 | | |
1280 | 1.91k | for_run_list (pp, main_run_list) |
1281 | 371k | { |
1282 | 371k | FriBidiCharType this_type; |
1283 | 371k | int level; |
1284 | | |
1285 | 371k | this_type = RL_TYPE (pp); |
1286 | 371k | level = RL_LEVEL (pp); |
1287 | | |
1288 | | /* I1. Even */ |
1289 | | /* I2. Odd */ |
1290 | 371k | if (FRIBIDI_IS_NUMBER (this_type)) |
1291 | 2.32k | RL_LEVEL (pp) = (level + 2) & ~1; |
1292 | 369k | else |
1293 | 369k | RL_LEVEL (pp) = |
1294 | 369k | level + |
1295 | 369k | (FRIBIDI_LEVEL_IS_RTL (level) ^ FRIBIDI_DIR_TO_LEVEL (this_type)); |
1296 | | |
1297 | 371k | if (RL_LEVEL (pp) > max_level) |
1298 | 20.9k | max_level = RL_LEVEL (pp); |
1299 | 371k | } |
1300 | 1.91k | } |
1301 | | |
1302 | 1.91k | compact_list (main_run_list); |
1303 | | |
1304 | 1.91k | # if DEBUG |
1305 | 1.91k | if UNLIKELY |
1306 | 1.91k | (fribidi_debug_status ()) |
1307 | 0 | { |
1308 | 0 | print_bidi_string (bidi_types, len); |
1309 | 0 | print_resolved_levels (main_run_list); |
1310 | 0 | print_resolved_types (main_run_list); |
1311 | 0 | } |
1312 | 1.91k | # endif /* DEBUG */ |
1313 | | |
1314 | | /* Reinsert the explicit codes & BN's that are already removed, from the |
1315 | | explicits_list to main_run_list. */ |
1316 | 1.91k | DBG ("reinserting explicit codes"); |
1317 | 1.91k | if UNLIKELY |
1318 | 1.91k | (explicits_list->next != explicits_list) |
1319 | 807 | { |
1320 | 807 | register FriBidiRun *p; |
1321 | 807 | register fribidi_boolean stat = |
1322 | 807 | shadow_run_list (main_run_list, explicits_list, true); |
1323 | 807 | explicits_list = NULL; |
1324 | 807 | if UNLIKELY |
1325 | 807 | (!stat) goto out; |
1326 | | |
1327 | | /* Set level of inserted explicit chars to that of their previous |
1328 | | * char, such that they do not affect reordering. */ |
1329 | 807 | p = main_run_list->next; |
1330 | 807 | if (p != main_run_list && p->level == FRIBIDI_SENTINEL) |
1331 | 369 | p->level = base_level; |
1332 | 479k | for_run_list (p, main_run_list) if (p->level == FRIBIDI_SENTINEL) |
1333 | 200k | p->level = p->prev->level; |
1334 | 807 | } |
1335 | | |
1336 | 1.91k | # if DEBUG |
1337 | 1.91k | if UNLIKELY |
1338 | 1.91k | (fribidi_debug_status ()) |
1339 | 0 | { |
1340 | 0 | print_types_re (main_run_list); |
1341 | 0 | print_resolved_levels (main_run_list); |
1342 | 0 | print_resolved_types (main_run_list); |
1343 | 0 | } |
1344 | 1.91k | # endif /* DEBUG */ |
1345 | | |
1346 | 1.91k | DBG ("reset the embedding levels, 1, 2, 3."); |
1347 | 1.91k | { |
1348 | 1.91k | register int j, state, pos; |
1349 | 1.91k | register FriBidiCharType char_type; |
1350 | 1.91k | register FriBidiRun *p, *q, *list; |
1351 | | |
1352 | | /* L1. Reset the embedding levels of some chars: |
1353 | | 1. segment separators, |
1354 | | 2. paragraph separators, |
1355 | | 3. any sequence of whitespace characters preceding a segment |
1356 | | separator or paragraph separator, and |
1357 | | 4. any sequence of whitespace characters and/or isolate formatting |
1358 | | characters at the end of the line. |
1359 | | ... (to be continued in fribidi_reorder_line()). */ |
1360 | 1.91k | list = new_run_list (); |
1361 | 1.91k | if UNLIKELY |
1362 | 1.91k | (!list) goto out; |
1363 | 1.91k | q = list; |
1364 | 1.91k | state = 1; |
1365 | 1.91k | pos = len - 1; |
1366 | 16.9M | for (j = len - 1; j >= -1; j--) |
1367 | 16.9M | { |
1368 | | /* close up the open link at the end */ |
1369 | 16.9M | if (j >= 0) |
1370 | 16.9M | char_type = bidi_types[j]; |
1371 | 1.91k | else |
1372 | 1.91k | char_type = FRIBIDI_TYPE_ON; |
1373 | 16.9M | if (!state && FRIBIDI_IS_SEPARATOR (char_type)) |
1374 | 50.8k | { |
1375 | 50.8k | state = 1; |
1376 | 50.8k | pos = j; |
1377 | 50.8k | } |
1378 | 16.8M | else if (state && |
1379 | 16.8M | !(FRIBIDI_IS_EXPLICIT_OR_SEPARATOR_OR_BN_OR_WS(char_type) |
1380 | 2.11M | || FRIBIDI_IS_ISOLATE(char_type))) |
1381 | 52.7k | { |
1382 | 52.7k | state = 0; |
1383 | 52.7k | p = new_run (); |
1384 | 52.7k | if UNLIKELY |
1385 | 52.7k | (!p) |
1386 | 0 | { |
1387 | 0 | free_run_list (list); |
1388 | 0 | goto out; |
1389 | 0 | } |
1390 | 52.7k | p->pos = j + 1; |
1391 | 52.7k | p->len = pos - j; |
1392 | 52.7k | p->type = base_dir; |
1393 | 52.7k | p->level = base_level; |
1394 | 52.7k | move_node_before (p, q); |
1395 | 52.7k | q = p; |
1396 | 52.7k | } |
1397 | 16.9M | } |
1398 | 1.91k | if UNLIKELY |
1399 | 1.91k | (!shadow_run_list (main_run_list, list, false)) goto out; |
1400 | 1.91k | } |
1401 | | |
1402 | 1.91k | # if DEBUG |
1403 | 1.91k | if UNLIKELY |
1404 | 1.91k | (fribidi_debug_status ()) |
1405 | 0 | { |
1406 | 0 | print_types_re (main_run_list); |
1407 | 0 | print_resolved_levels (main_run_list); |
1408 | 0 | print_resolved_types (main_run_list); |
1409 | 0 | } |
1410 | 1.91k | # endif /* DEBUG */ |
1411 | | |
1412 | 1.91k | { |
1413 | 1.91k | FriBidiStrIndex pos = 0; |
1414 | 1.91k | for_run_list (pp, main_run_list) |
1415 | 800k | { |
1416 | 800k | register FriBidiStrIndex l; |
1417 | 800k | register FriBidiLevel level = pp->level; |
1418 | 17.7M | for (l = pp->len; l; l--) |
1419 | 16.9M | embedding_levels[pos++] = level; |
1420 | 800k | } |
1421 | 1.91k | } |
1422 | | |
1423 | 1.91k | status = true; |
1424 | | |
1425 | 1.91k | out: |
1426 | 1.91k | DBG ("leaving fribidi_get_par_embedding_levels"); |
1427 | | |
1428 | 1.91k | if (main_run_list) |
1429 | 1.91k | free_run_list (main_run_list); |
1430 | 1.91k | if UNLIKELY |
1431 | 1.91k | (explicits_list) free_run_list (explicits_list); |
1432 | | |
1433 | 1.91k | return status ? max_level + 1 : 0; |
1434 | 1.91k | } |
1435 | | |
1436 | | |
1437 | | static void |
1438 | | bidi_string_reverse ( |
1439 | | FriBidiChar *str, |
1440 | | const FriBidiStrIndex len |
1441 | | ) |
1442 | 0 | { |
1443 | 0 | FriBidiStrIndex i; |
1444 | |
|
1445 | 0 | fribidi_assert (str); |
1446 | |
|
1447 | 0 | for (i = 0; i < len / 2; i++) |
1448 | 0 | { |
1449 | 0 | FriBidiChar tmp = str[i]; |
1450 | 0 | str[i] = str[len - 1 - i]; |
1451 | 0 | str[len - 1 - i] = tmp; |
1452 | 0 | } |
1453 | 0 | } |
1454 | | |
1455 | | static void |
1456 | | index_array_reverse ( |
1457 | | FriBidiStrIndex *arr, |
1458 | | const FriBidiStrIndex len |
1459 | | ) |
1460 | 0 | { |
1461 | 0 | FriBidiStrIndex i; |
1462 | |
|
1463 | 0 | fribidi_assert (arr); |
1464 | |
|
1465 | 0 | for (i = 0; i < len / 2; i++) |
1466 | 0 | { |
1467 | 0 | FriBidiStrIndex tmp = arr[i]; |
1468 | 0 | arr[i] = arr[len - 1 - i]; |
1469 | 0 | arr[len - 1 - i] = tmp; |
1470 | 0 | } |
1471 | 0 | } |
1472 | | |
1473 | | |
1474 | | FRIBIDI_ENTRY FriBidiLevel |
1475 | | fribidi_reorder_line ( |
1476 | | /* input */ |
1477 | | FriBidiFlags flags, /* reorder flags */ |
1478 | | const FriBidiCharType *bidi_types, |
1479 | | const FriBidiStrIndex len, |
1480 | | const FriBidiStrIndex off, |
1481 | | const FriBidiParType base_dir, |
1482 | | /* input and output */ |
1483 | | FriBidiLevel *embedding_levels, |
1484 | | FriBidiChar *visual_str, |
1485 | | /* output */ |
1486 | | FriBidiStrIndex *map |
1487 | | ) |
1488 | 0 | { |
1489 | 0 | fribidi_boolean status = false; |
1490 | 0 | FriBidiLevel max_level = 0; |
1491 | |
|
1492 | 0 | if UNLIKELY |
1493 | 0 | (len == 0) |
1494 | 0 | { |
1495 | 0 | status = true; |
1496 | 0 | goto out; |
1497 | 0 | } |
1498 | | |
1499 | 0 | DBG ("in fribidi_reorder_line"); |
1500 | |
|
1501 | 0 | fribidi_assert (bidi_types); |
1502 | 0 | fribidi_assert (embedding_levels); |
1503 | |
|
1504 | 0 | DBG ("reset the embedding levels, 4. whitespace at the end of line"); |
1505 | 0 | { |
1506 | 0 | register FriBidiStrIndex i; |
1507 | | |
1508 | | /* L1. Reset the embedding levels of some chars: |
1509 | | 4. any sequence of white space characters at the end of the line. */ |
1510 | 0 | for (i = off + len - 1; i >= off && |
1511 | 0 | FRIBIDI_IS_EXPLICIT_OR_BN_OR_WS (bidi_types[i]); i--) |
1512 | 0 | embedding_levels[i] = FRIBIDI_DIR_TO_LEVEL (base_dir); |
1513 | 0 | } |
1514 | | |
1515 | | /* 7. Reordering resolved levels */ |
1516 | 0 | { |
1517 | 0 | register FriBidiLevel level; |
1518 | 0 | register FriBidiStrIndex i; |
1519 | | |
1520 | | /* Reorder both the outstring and the order array */ |
1521 | 0 | { |
1522 | 0 | if (FRIBIDI_TEST_BITS (flags, FRIBIDI_FLAG_REORDER_NSM)) |
1523 | 0 | { |
1524 | | /* L3. Reorder NSMs. */ |
1525 | 0 | for (i = off + len - 1; i >= off; i--) |
1526 | 0 | if (FRIBIDI_LEVEL_IS_RTL (embedding_levels[i]) |
1527 | 0 | && bidi_types[i] == FRIBIDI_TYPE_NSM) |
1528 | 0 | { |
1529 | 0 | register FriBidiStrIndex seq_end = i; |
1530 | 0 | level = embedding_levels[i]; |
1531 | |
|
1532 | 0 | for (i--; i >= off && |
1533 | 0 | FRIBIDI_IS_EXPLICIT_OR_BN_OR_NSM (bidi_types[i]) |
1534 | 0 | && embedding_levels[i] == level; i--) |
1535 | 0 | ; |
1536 | |
|
1537 | 0 | if (i < off || embedding_levels[i] != level) |
1538 | 0 | { |
1539 | 0 | i++; |
1540 | 0 | DBG ("warning: NSM(s) at the beginning of level run"); |
1541 | 0 | } |
1542 | |
|
1543 | 0 | if (visual_str) |
1544 | 0 | { |
1545 | 0 | bidi_string_reverse (visual_str + i, seq_end - i + 1); |
1546 | 0 | } |
1547 | 0 | if (map) |
1548 | 0 | { |
1549 | 0 | index_array_reverse (map + i, seq_end - i + 1); |
1550 | 0 | } |
1551 | 0 | } |
1552 | 0 | } |
1553 | | |
1554 | | /* Find max_level of the line. We don't reuse the paragraph |
1555 | | * max_level, both for a cleaner API, and that the line max_level |
1556 | | * may be far less than paragraph max_level. */ |
1557 | 0 | for (i = off + len - 1; i >= off; i--) |
1558 | 0 | if (embedding_levels[i] > max_level) |
1559 | 0 | max_level = embedding_levels[i]; |
1560 | | |
1561 | | /* L2. Reorder. */ |
1562 | 0 | for (level = max_level; level > 0; level--) |
1563 | 0 | for (i = off + len - 1; i >= off; i--) |
1564 | 0 | if (embedding_levels[i] >= level) |
1565 | 0 | { |
1566 | | /* Find all stretches that are >= level_idx */ |
1567 | 0 | register FriBidiStrIndex seq_end = i; |
1568 | 0 | for (i--; i >= off && embedding_levels[i] >= level; i--) |
1569 | 0 | ; |
1570 | |
|
1571 | 0 | if (visual_str) |
1572 | 0 | bidi_string_reverse (visual_str + i + 1, seq_end - i); |
1573 | 0 | if (map) |
1574 | 0 | index_array_reverse (map + i + 1, seq_end - i); |
1575 | 0 | } |
1576 | 0 | } |
1577 | |
|
1578 | 0 | } |
1579 | |
|
1580 | 0 | status = true; |
1581 | |
|
1582 | 0 | out: |
1583 | |
|
1584 | 0 | return status ? max_level + 1 : 0; |
1585 | 0 | } |
1586 | | |
1587 | | /* Editor directions: |
1588 | | * vim:textwidth=78:tabstop=8:shiftwidth=2:autoindent:cindent |
1589 | | */ |