Coverage Report

Created: 2026-01-09 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fribidi/lib/fribidi-bidi.c
Line
Count
Source
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
7.59G
#define RL_TYPE(list) ((list)->type)
50
17.5M
#define RL_LEN(list) ((list)->len)
51
668M
#define RL_LEVEL(list) ((list)->level)
52
53
/* "Within this scope, bidirectional types EN and AN are treated as R" */
54
1.12G
#define RL_TYPE_AN_EN_AS_RTL(list) ( \
55
1.12G
 (((list)->type == FRIBIDI_TYPE_AN) || ((list)->type == FRIBIDI_TYPE_EN) | ((list)->type == FRIBIDI_TYPE_RTL)) ? FRIBIDI_TYPE_RTL : (list)->type)
56
25.4M
#define RL_BRACKET_TYPE(list) ((list)->bracket_type)
57
84.9M
#define RL_ISOLATE_LEVEL(list) ((list)->isolate_level)
58
59
35.2k
#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
5.92M
{
75
5.92M
  FriBidiRun *first;
76
77
5.92M
  fribidi_assert (second);
78
5.92M
  fribidi_assert (second->next);
79
5.92M
  first = second->prev;
80
5.92M
  fribidi_assert (first);
81
82
5.92M
  first->next = second->next;
83
5.92M
  first->next->prev = first;
84
5.92M
  RL_LEN (first) += RL_LEN (second);
85
5.92M
  if (second->next_isolate)
86
5.90M
    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.4k
  else if (second->next->prev_isolate == second)
91
0
    second->next->prev_isolate = second->prev_isolate;  
92
5.92M
  if (second->prev_isolate)
93
5.92M
    second->prev_isolate->next_isolate = second->next_isolate;
94
5.92M
  first->next_isolate = second->next_isolate;
95
96
5.92M
  fribidi_free (second);
97
5.92M
  return first;
98
5.92M
}
99
static void
100
compact_list (
101
  FriBidiRun *list
102
)
103
5.50k
{
104
5.50k
  fribidi_assert (list);
105
106
5.50k
  if (list->next)
107
5.50k
    for_run_list (list, list)
108
9.21M
      if (RL_TYPE (list->prev) == RL_TYPE (list)
109
6.14M
    && RL_LEVEL (list->prev) == RL_LEVEL (list)
110
5.93M
          && RL_ISOLATE_LEVEL (list->prev) == RL_ISOLATE_LEVEL (list)
111
5.90M
          && RL_BRACKET_TYPE(list) == FRIBIDI_NO_BRACKET /* Don't join brackets! */
112
2.41M
          && RL_BRACKET_TYPE(list->prev) == FRIBIDI_NO_BRACKET
113
9.21M
          )
114
2.40M
      list = merge_with_prev (list);
115
5.50k
}
116
117
static void
118
compact_neutrals (
119
  FriBidiRun *list
120
)
121
3.66k
{
122
3.66k
  fribidi_assert (list);
123
124
3.66k
  if (list->next)
125
3.66k
    {
126
3.66k
      for_run_list (list, list)
127
10.0M
      {
128
10.0M
  if (RL_LEVEL (list->prev) == RL_LEVEL (list)
129
9.88M
            && RL_ISOLATE_LEVEL (list->prev) == RL_ISOLATE_LEVEL (list)
130
9.85M
      &&
131
9.85M
      ((RL_TYPE (list->prev) == RL_TYPE (list)
132
3.20M
        || (FRIBIDI_IS_NEUTRAL (RL_TYPE (list->prev))
133
1.02M
      && FRIBIDI_IS_NEUTRAL (RL_TYPE (list)))))
134
7.01M
            && RL_BRACKET_TYPE(list) == FRIBIDI_NO_BRACKET /* Don't join brackets! */
135
3.51M
            && RL_BRACKET_TYPE(list->prev) == FRIBIDI_NO_BRACKET
136
10.0M
            )
137
3.49M
    list = merge_with_prev (list);
138
10.0M
      }
139
3.66k
    }
140
3.66k
}
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
23.2M
{
152
23.2M
  FriBidiRun *ppp = forward ? list->next_isolate : list->prev_isolate;
153
23.2M
  if (!ppp)
154
457k
    return &sentinel;
155
156
22.8M
  while (ppp)
157
22.8M
    {
158
22.8M
      FriBidiCharType ppp_type = RL_TYPE (ppp);
159
160
22.8M
      if (ppp_type == FRIBIDI_TYPE_SENTINEL)
161
8.80k
        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
22.8M
      if (ppp->isolate_level > list->isolate_level   /* <- How can this be true? */
168
22.8M
          || (forward && ppp_type == FRIBIDI_TYPE_PDI)
169
22.7M
          || (skip_neutral && !FRIBIDI_IS_STRONG(ppp_type)))
170
45.6k
        {
171
45.6k
          ppp = forward ? ppp->next_isolate : ppp->prev_isolate;
172
45.6k
          if (!ppp)
173
8.80k
            ppp = &sentinel;
174
175
45.6k
          continue;
176
45.6k
        }
177
22.7M
      break;
178
22.8M
    }
179
180
22.7M
  return ppp;
181
23.2M
}
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
1.36M
    FRIBIDI_BEGIN_STMT \
331
1.36M
      if LIKELY(over_pushed == 0 \
332
1.36M
                && isolate_overflow == 0 \
333
1.36M
                && new_level <= FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL)   \
334
1.36M
        { \
335
64.8k
          if UNLIKELY(level == FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL - 1) \
336
64.8k
            first_interval = over_pushed; \
337
64.8k
          status_stack[stack_size].level = level; \
338
64.8k
          status_stack[stack_size].isolate_level = isolate_level; \
339
64.8k
          status_stack[stack_size].isolate = isolate; \
340
64.8k
          status_stack[stack_size].override = override; \
341
64.8k
          stack_size++; \
342
64.8k
          level = new_level; \
343
64.8k
          override = new_override; \
344
1.30M
        } else if LIKELY(isolate_overflow == 0) \
345
1.30M
    over_pushed++; \
346
1.36M
    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
1.10M
    FRIBIDI_BEGIN_STMT \
353
1.10M
      if (stack_size) \
354
1.10M
      { \
355
490k
        if UNLIKELY(over_pushed > first_interval) \
356
490k
          over_pushed--; \
357
490k
        else \
358
490k
          { \
359
37.3k
            if LIKELY(over_pushed == first_interval) \
360
37.3k
              first_interval = 0; \
361
37.3k
            stack_size--; \
362
37.3k
            level = status_stack[stack_size].level; \
363
37.3k
            override = status_stack[stack_size].override; \
364
37.3k
            isolate = status_stack[stack_size].isolate; \
365
37.3k
            isolate_level = status_stack[stack_size].isolate_level; \
366
37.3k
          } \
367
490k
      } \
368
1.10M
    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
5.01M
    ( \
375
5.01M
      RL_LEVEL(pp->prev) == RL_LEVEL(pp) ? \
376
5.01M
        RL_TYPE(pp->prev) : \
377
5.01M
        FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(pp->prev), RL_LEVEL(pp))) \
378
5.01M
    )
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
17.3k
    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.64M
{
430
1.64M
  FriBidiPairingNode *node = fribidi_malloc(sizeof(FriBidiPairingNode));
431
1.64M
  node->open = open;
432
1.64M
  node->close = close;
433
1.64M
  node->next = nodes;
434
1.64M
  nodes = node;
435
1.64M
  return nodes;
436
1.64M
}
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.64M
{
444
1.64M
  FriBidiPairingNode *pfast, *pslow;
445
1.64M
  if (!source || !source->next)
446
0
    {
447
0
      *front = source;
448
0
      *back = NULL;
449
0
    }
450
1.64M
  else
451
1.64M
    {
452
1.64M
      pslow = source;
453
1.64M
      pfast = source->next;
454
14.0M
      while (pfast)
455
12.4M
        {
456
12.4M
          pfast= pfast->next;
457
12.4M
          if (pfast)
458
11.2M
            {
459
11.2M
              pfast = pfast->next;
460
11.2M
              pslow = pslow->next;
461
11.2M
            }
462
12.4M
        }
463
1.64M
      *front = source;
464
1.64M
      *back = pslow->next;
465
1.64M
      pslow->next = NULL;
466
1.64M
    }
467
1.64M
}
468
469
static FriBidiPairingNode *
470
pairing_nodes_sorted_merge(FriBidiPairingNode *nodes1,
471
                           FriBidiPairingNode *nodes2)
472
14.7M
{
473
14.7M
  FriBidiPairingNode *res = NULL;
474
14.7M
  if (!nodes1)
475
135k
    return nodes2;
476
14.6M
  if (!nodes2)
477
1.50M
    return nodes1;
478
479
13.1M
  if (nodes1->open->pos < nodes2->open->pos)
480
1.06M
    {
481
1.06M
      res = nodes1;
482
1.06M
      res->next = pairing_nodes_sorted_merge(nodes1->next, nodes2);
483
1.06M
    }
484
12.0M
  else
485
12.0M
    {
486
12.0M
      res = nodes2;
487
12.0M
      res->next = pairing_nodes_sorted_merge(nodes1, nodes2->next);
488
12.0M
    }
489
13.1M
  return res;
490
14.6M
}
491
492
static void sort_pairing_nodes(FriBidiPairingNode **nodes)
493
3.28M
{
494
3.28M
  FriBidiPairingNode *front, *back;
495
496
  /* 0 or 1 node case */
497
3.28M
  if (!*nodes || !(*nodes)->next)
498
1.64M
    return;
499
500
1.64M
  pairing_nodes_front_back_split(*nodes, &front, &back);
501
1.64M
  sort_pairing_nodes(&front);
502
1.64M
  sort_pairing_nodes(&back);
503
1.64M
  *nodes = pairing_nodes_sorted_merge(front, back);
504
1.64M
}
505
506
static void free_pairing_nodes(FriBidiPairingNode *nodes)
507
1.83k
{
508
1.64M
  while (nodes)
509
1.64M
    {
510
1.64M
      FriBidiPairingNode *p = nodes;
511
1.64M
      nodes = nodes->next;
512
1.64M
      fribidi_free(p);
513
1.64M
    }
514
1.83k
}
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.83k
{
528
1.83k
  FriBidiLevel base_level, max_level = 0;
529
1.83k
  FriBidiParType base_dir;
530
1.83k
  FriBidiRun *main_run_list = NULL, *explicits_list = NULL, *pp;
531
1.83k
  fribidi_boolean status = false;
532
1.83k
  int max_iso_level = 0;
533
534
1.83k
  if UNLIKELY
535
1.83k
    (!len)
536
1
    {
537
1
      status = true;
538
1
      goto out;
539
1
    }
540
541
1.83k
  DBG ("in fribidi_get_par_embedding_levels");
542
543
1.83k
  fribidi_assert (bidi_types);
544
1.83k
  fribidi_assert (pbase_dir);
545
1.83k
  fribidi_assert (embedding_levels);
546
547
  /* Determinate character types */
548
1.83k
  {
549
    /* Get run-length encoded character types */
550
1.83k
    main_run_list = run_list_encode_bidi_types (bidi_types, bracket_types, len);
551
1.83k
    if UNLIKELY
552
1.83k
      (!main_run_list) goto out;
553
1.83k
  }
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.83k
  base_level = FRIBIDI_DIR_TO_LEVEL (*pbase_dir);
559
1.83k
  if (!FRIBIDI_IS_STRONG (*pbase_dir))
560
    /* P2. P3. Search for first strong character and use its direction as
561
       base direction */
562
1.83k
    {
563
1.83k
      int valid_isolate_count = 0;
564
1.83k
      for_run_list (pp, main_run_list)
565
1.43M
        {
566
1.43M
          if (RL_TYPE(pp) == FRIBIDI_TYPE_PDI)
567
20.7k
            {
568
              /* Ignore if there is no matching isolate */
569
20.7k
              if (valid_isolate_count>0)
570
13.5k
                valid_isolate_count--;
571
20.7k
            }
572
1.40M
          else if (FRIBIDI_IS_ISOLATE(RL_TYPE(pp)))
573
936k
            valid_isolate_count++;
574
473k
          else if (valid_isolate_count==0 && FRIBIDI_IS_LETTER (RL_TYPE (pp)))
575
763
            {
576
763
              base_level = FRIBIDI_DIR_TO_LEVEL (RL_TYPE (pp));
577
763
              *pbase_dir = FRIBIDI_LEVEL_TO_DIR (base_level);
578
763
              break;
579
763
            }
580
1.43M
        }
581
1.83k
    }
582
1.83k
  base_dir = FRIBIDI_LEVEL_TO_DIR (base_level);
583
1.83k
  DBG2 ("  base level : %c", fribidi_char_from_level (base_level));
584
1.83k
  DBG2 ("  base dir   : %s", fribidi_get_bidi_type_name (base_dir));
585
586
1.83k
# if DEBUG
587
1.83k
  if UNLIKELY
588
1.83k
    (fribidi_debug_status ())
589
0
    {
590
0
      print_types_re (main_run_list);
591
0
    }
592
1.83k
# endif /* DEBUG */
593
594
  /* Explicit Levels and Directions */
595
1.83k
  DBG ("explicit levels and directions");
596
1.83k
  {
597
1.83k
    FriBidiLevel level, new_level = 0;
598
1.83k
    int isolate_level = 0;
599
1.83k
    FriBidiCharType override, new_override;
600
1.83k
    FriBidiStrIndex i;
601
1.83k
    int stack_size, over_pushed, first_interval;
602
1.83k
    int valid_isolate_count = 0;
603
1.83k
    int isolate_overflow = 0;
604
1.83k
    int isolate = 0; /* The isolate status flag */
605
1.83k
    struct
606
1.83k
    {
607
1.83k
      FriBidiCharType override; /* only LTR, RTL and ON are valid */
608
1.83k
      FriBidiLevel level;
609
1.83k
      int isolate;
610
1.83k
      int isolate_level;
611
1.83k
    } status_stack[FRIBIDI_BIDI_MAX_RESOLVED_LEVELS];
612
1.83k
    FriBidiRun temp_link;
613
1.83k
    FriBidiRun *run_per_isolate_level[FRIBIDI_BIDI_MAX_RESOLVED_LEVELS];
614
1.83k
    int prev_isolate_level = 0; /* When running over the isolate levels, remember the previous level */
615
616
1.83k
    memset(run_per_isolate_level, 0, sizeof(run_per_isolate_level[0])
617
1.83k
           * 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.83k
    explicits_list = new_run_list ();
624
1.83k
    if UNLIKELY
625
1.83k
      (!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.83k
    level = base_level;
635
1.83k
    override = FRIBIDI_TYPE_ON;
636
    /* stack */
637
1.83k
    stack_size = 0;
638
1.83k
    over_pushed = 0;
639
1.83k
    first_interval = 0;
640
1.83k
    valid_isolate_count = 0;
641
1.83k
    isolate_overflow = 0;
642
643
1.83k
    for_run_list (pp, main_run_list)
644
5.82M
    {
645
5.82M
      FriBidiCharType this_type = RL_TYPE (pp);
646
5.82M
      RL_ISOLATE_LEVEL (pp) = isolate_level;
647
648
5.82M
      if (FRIBIDI_IS_EXPLICIT_OR_BN (this_type))
649
193k
  {
650
193k
    if (FRIBIDI_IS_STRONG (this_type))
651
29.1k
      {     /* 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
29.1k
        new_override = FRIBIDI_EXPLICIT_TO_OVERRIDE_DIR (this_type);
663
1.33M
        for (i = RL_LEN (pp); i; i--)
664
1.30M
    {
665
1.30M
      new_level =
666
1.30M
        ((level + FRIBIDI_DIR_TO_LEVEL (this_type) + 2) & ~1) -
667
1.30M
        FRIBIDI_DIR_TO_LEVEL (this_type);
668
1.30M
                  isolate = 0;
669
1.30M
      PUSH_STATUS;
670
1.30M
    }
671
29.1k
      }
672
164k
    else if (this_type == FRIBIDI_TYPE_PDF)
673
127k
      {
674
        /* 3. Terminating Embeddings and overrides */
675
        /*   X7. With each PDF, determine the matching embedding or
676
           override code. */
677
206k
              for (i = RL_LEN (pp); i; i--)
678
195k
                {
679
195k
                  if (stack_size && status_stack[stack_size-1].isolate != 0)
680
117k
                    break;
681
195k
                  POP_STATUS;
682
78.2k
                }
683
127k
      }
684
685
    /* X9. Remove all RLE, LRE, RLO, LRO, PDF, and BN codes. */
686
    /* Remove element and add it to explicits_list */
687
193k
    RL_LEVEL (pp) = FRIBIDI_SENTINEL;
688
193k
    temp_link.next = pp->next;
689
193k
    move_node_before (pp, explicits_list);
690
193k
    pp = &temp_link;
691
193k
  }
692
5.62M
      else if (this_type == FRIBIDI_TYPE_PDI)
693
        /* X6a. pop the direction of the stack */
694
513k
        {
695
1.02M
          for (i = RL_LEN (pp); i; i--)
696
513k
            {
697
513k
              if (isolate_overflow > 0)
698
20.1k
                {
699
20.1k
                  isolate_overflow--;
700
20.1k
                  RL_LEVEL (pp) = level;
701
20.1k
                }
702
703
493k
              else if (valid_isolate_count > 0)
704
11.9k
                {
705
                  /* Pop away all LRE,RLE,LRO, RLO levels
706
                     from the stack, as these are implicitly
707
                     terminated by the PDI */
708
479k
                  while (stack_size && !status_stack[stack_size-1].isolate)
709
467k
                    POP_STATUS;
710
11.9k
                  over_pushed = 0; /* The PDI resets the overpushed! */
711
11.9k
                  POP_STATUS;
712
11.9k
                  if (isolate_level>0)
713
9.31k
                    isolate_level--;
714
11.9k
                  valid_isolate_count--;
715
11.9k
                  RL_LEVEL (pp) = level;
716
11.9k
                  RL_ISOLATE_LEVEL (pp) = isolate_level;
717
11.9k
                }
718
481k
              else
719
481k
                {
720
                  /* Ignore isolated PDI's by turning them into ON's */
721
481k
                  RL_TYPE (pp) = FRIBIDI_TYPE_ON;
722
481k
                  RL_LEVEL (pp) = level;
723
481k
                }
724
513k
            }
725
513k
        }
726
5.11M
      else if (FRIBIDI_IS_ISOLATE(this_type))
727
1.17M
        {
728
          /* TBD support RL_LEN > 1 */
729
1.17M
          new_override = FRIBIDI_TYPE_ON;
730
1.17M
          isolate = 1;
731
1.17M
          if (this_type == FRIBIDI_TYPE_LRI)
732
997k
            new_level = level + 2 - (level%2);
733
174k
          else if (this_type == FRIBIDI_TYPE_RLI)
734
15.2k
            new_level = level + 1 + (level%2);
735
159k
          else if (this_type == FRIBIDI_TYPE_FSI)
736
159k
            {
737
              /* Search for a local strong character until we
738
                 meet the corresponding PDI or the end of the
739
                 paragraph */
740
159k
              FriBidiRun *fsi_pp;
741
159k
              int isolate_count = 0;
742
159k
              int fsi_base_level = 0;
743
159k
              for_run_list (fsi_pp, pp)
744
7.46G
                {
745
7.46G
                  if (RL_TYPE(fsi_pp) == FRIBIDI_TYPE_PDI)
746
42.3M
                    {
747
42.3M
                      isolate_count--;
748
42.3M
                      if (valid_isolate_count < 0)
749
0
                        break;
750
42.3M
                    }
751
7.42G
                  else if (FRIBIDI_IS_ISOLATE(RL_TYPE(fsi_pp)))
752
1.29G
                    isolate_count++;
753
6.12G
                  else if (isolate_count==0 && FRIBIDI_IS_LETTER (RL_TYPE (fsi_pp)))
754
14.9k
                    {
755
14.9k
                      fsi_base_level = FRIBIDI_DIR_TO_LEVEL (RL_TYPE (fsi_pp));
756
14.9k
                      break;
757
14.9k
                    }
758
7.46G
                }
759
760
              /* Same behavior like RLI and LRI above */
761
159k
              if (FRIBIDI_LEVEL_IS_RTL (fsi_base_level))
762
992
                new_level = level + 1 + (level%2);
763
158k
              else
764
158k
                new_level = level + 2 - (level%2);
765
159k
            }
766
767
1.17M
    RL_LEVEL (pp) = level;
768
1.17M
          RL_ISOLATE_LEVEL (pp) = isolate_level;
769
1.17M
          if (isolate_level < FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL-1)
770
77.5k
              isolate_level++;
771
772
1.17M
    if (!FRIBIDI_IS_NEUTRAL (override))
773
43.2k
      RL_TYPE (pp) = override;
774
775
1.17M
          if (new_level <= FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL)
776
65.2k
            {
777
65.2k
              valid_isolate_count++;
778
65.2k
              PUSH_STATUS;
779
65.2k
              level = new_level;
780
65.2k
            }
781
1.10M
          else
782
1.10M
            isolate_overflow += 1;
783
1.17M
        }
784
3.94M
      else if (this_type == FRIBIDI_TYPE_BS)
785
288
  {
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
288
    break;
790
288
  }
791
3.94M
      else
792
3.94M
  {
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.94M
    RL_LEVEL (pp) = level;
800
3.94M
    if (!FRIBIDI_IS_NEUTRAL (override))
801
260k
      RL_TYPE (pp) = override;
802
3.94M
  }
803
5.82M
    }
804
805
    /* Build the isolate_level connections */
806
1.83k
    prev_isolate_level = 0;
807
1.83k
    for_run_list (pp, main_run_list)
808
6.79M
    {
809
6.79M
      int isolate_level = RL_ISOLATE_LEVEL (pp);
810
6.79M
      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.79M
      if (isolate_level<prev_isolate_level)
815
62.1k
        for (i=isolate_level+1; i<=prev_isolate_level; i++)
816
50.8k
          run_per_isolate_level[i]=0;
817
6.79M
      prev_isolate_level = isolate_level;
818
      
819
6.79M
      if (run_per_isolate_level[isolate_level])
820
6.72M
        {
821
6.72M
          run_per_isolate_level[isolate_level]->next_isolate = pp;
822
6.72M
          pp->prev_isolate = run_per_isolate_level[isolate_level];
823
6.72M
        }
824
6.79M
      run_per_isolate_level[isolate_level] = pp;
825
6.79M
    }
826
827
    /* Implementing X8. It has no effect on a single paragraph! */
828
1.83k
    level = base_level;
829
1.83k
    override = FRIBIDI_TYPE_ON;
830
1.83k
    stack_size = 0;
831
1.83k
    over_pushed = 0;
832
1.83k
  }
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.83k
# if DEBUG
846
1.83k
  if UNLIKELY
847
1.83k
    (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.83k
# endif /* DEBUG */
855
856
  /* 4. Resolving weak types. Also calculate the maximum isolate level */
857
1.83k
  max_iso_level = 0;
858
1.83k
  DBG ("4a. resolving weak types");
859
1.83k
  {
860
1.83k
    int last_strong_stack[FRIBIDI_BIDI_MAX_RESOLVED_LEVELS];
861
1.83k
    FriBidiCharType prev_type_orig;
862
1.83k
    fribidi_boolean w4;
863
864
1.83k
    last_strong_stack[0] = base_dir;
865
866
1.83k
    for_run_list (pp, main_run_list)
867
5.04M
    {
868
5.04M
      register FriBidiCharType prev_type, this_type, next_type;
869
5.04M
      FriBidiRun *ppp_prev, *ppp_next;
870
5.04M
      int iso_level;
871
872
5.04M
      ppp_prev = get_adjacent_run(pp, false, false);
873
5.04M
      ppp_next = get_adjacent_run(pp, true, false);
874
875
5.04M
      this_type = RL_TYPE (pp);
876
5.04M
      iso_level = RL_ISOLATE_LEVEL(pp);
877
878
5.04M
      if (iso_level > max_iso_level)
879
30.4k
        max_iso_level = iso_level;
880
881
5.04M
      if (RL_LEVEL(ppp_prev) == RL_LEVEL(pp))
882
4.96M
        prev_type = RL_TYPE(ppp_prev);
883
85.0k
      else
884
85.0k
        prev_type = FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(ppp_prev), RL_LEVEL(pp)));
885
886
5.04M
      if (RL_LEVEL(ppp_next) == RL_LEVEL(pp))
887
4.96M
        next_type = RL_TYPE(ppp_next);
888
87.8k
      else
889
87.8k
        next_type = FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(ppp_next), RL_LEVEL(pp)));
890
891
5.04M
      if (FRIBIDI_IS_STRONG (prev_type))
892
1.00M
  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
5.04M
      if (this_type == FRIBIDI_TYPE_NSM)
903
16.1k
  {
904
          /* New rule in Unicode 6.3 */
905
16.1k
          if (FRIBIDI_IS_ISOLATE (RL_TYPE (pp->prev)))
906
913
              RL_TYPE(pp) = FRIBIDI_TYPE_ON;
907
908
16.1k
    if (RL_LEVEL (ppp_prev) == RL_LEVEL (pp))
909
15.1k
            {
910
15.1k
              if (ppp_prev == pp->prev)
911
14.8k
                pp = merge_with_prev (pp);
912
15.1k
            }
913
1.07k
    else
914
1.07k
      RL_TYPE (pp) = prev_type;
915
916
16.1k
    if (prev_type == next_type && RL_LEVEL (pp) == RL_LEVEL (pp->next))
917
6.20k
      {
918
6.20k
              if (ppp_next == pp->next)
919
5.67k
                pp = merge_with_prev (pp->next);
920
6.20k
      }
921
16.1k
    continue;   /* As we know the next condition cannot be true. */
922
16.1k
  }
923
924
      /* W2: European numbers. */
925
5.03M
      if (this_type == FRIBIDI_TYPE_EN && last_strong_stack[iso_level] == FRIBIDI_TYPE_AL)
926
1.51k
  {
927
1.51k
    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.51k
    if (next_type == FRIBIDI_TYPE_NSM)
932
499
      RL_TYPE (ppp_next) = FRIBIDI_TYPE_AN;
933
1.51k
  }
934
5.03M
    }
935
936
1.83k
# if DEBUG
937
1.83k
  if UNLIKELY
938
1.83k
    (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.83k
# 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.83k
    last_strong_stack[0] = base_dir;
949
950
1.83k
    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.83k
    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.83k
    prev_type_orig = FRIBIDI_TYPE_ON;
960
961
    /* Each isolate level has its own memory of the last strong character */
962
1.83k
    for_run_list (pp, main_run_list)
963
5.03M
    {
964
5.03M
      register FriBidiCharType prev_type, this_type, next_type;
965
5.03M
      int iso_level;
966
5.03M
      FriBidiRun *ppp_prev, *ppp_next;
967
968
5.03M
      this_type = RL_TYPE (pp);
969
5.03M
      iso_level = RL_ISOLATE_LEVEL(pp);
970
971
5.03M
      ppp_prev = get_adjacent_run(pp, false, false);
972
5.03M
      ppp_next = get_adjacent_run(pp, true, false);
973
974
5.03M
      if (RL_LEVEL(ppp_prev) == RL_LEVEL(pp))
975
4.94M
        prev_type = RL_TYPE(ppp_prev);
976
85.0k
      else
977
85.0k
        prev_type = FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(ppp_prev), RL_LEVEL(pp)));
978
979
5.03M
      if (RL_LEVEL(ppp_next) == RL_LEVEL(pp))
980
4.94M
        next_type = RL_TYPE(ppp_next);
981
88.0k
      else
982
88.0k
        next_type = FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(ppp_next), RL_LEVEL(pp)));
983
984
5.03M
      if (FRIBIDI_IS_STRONG (prev_type))
985
1.00M
  last_strong_stack[iso_level] = prev_type;
986
987
      /* W2 ??? */
988
989
      /* W3: Change ALs to R. */
990
5.03M
      if (this_type == FRIBIDI_TYPE_AL)
991
3.80k
  {
992
3.80k
    RL_TYPE (pp) = FRIBIDI_TYPE_RTL;
993
3.80k
    w4 = true;
994
3.80k
    prev_type_orig = FRIBIDI_TYPE_ON;
995
3.80k
    continue;
996
3.80k
  }
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
5.03M
      if (w4
1002
5.02M
    && RL_LEN (pp) == 1 && FRIBIDI_IS_ES_OR_CS (this_type)
1003
9.09k
    && FRIBIDI_IS_NUMBER (prev_type_orig)
1004
1.93k
    && prev_type_orig == next_type
1005
1.21k
    && (prev_type_orig == FRIBIDI_TYPE_EN
1006
644
        || this_type == FRIBIDI_TYPE_CS))
1007
796
  {
1008
796
    RL_TYPE (pp) = prev_type;
1009
796
    this_type = RL_TYPE (pp);
1010
796
  }
1011
5.03M
      w4 = true;
1012
1013
      /* W5. A sequence of European terminators adjacent to European
1014
         numbers changes to All European numbers. */
1015
5.03M
      if (this_type == FRIBIDI_TYPE_ET
1016
5.70k
    && (prev_type_orig == FRIBIDI_TYPE_EN
1017
4.38k
        || next_type == FRIBIDI_TYPE_EN))
1018
1.89k
  {
1019
1.89k
    RL_TYPE (pp) = FRIBIDI_TYPE_EN;
1020
1.89k
    w4 = false;
1021
1.89k
    this_type = RL_TYPE (pp);
1022
1.89k
  }
1023
1024
      /* W6. Otherwise change separators and terminators to other neutral. */
1025
5.03M
      if (FRIBIDI_IS_NUMBER_SEPARATOR_OR_TERMINATOR (this_type))
1026
12.1k
  RL_TYPE (pp) = FRIBIDI_TYPE_ON;
1027
1028
      /* W7. Change european numbers to L. */
1029
5.03M
      if (this_type == FRIBIDI_TYPE_EN && last_strong_stack[iso_level] == FRIBIDI_TYPE_LTR)
1030
11.3k
  {
1031
11.3k
    RL_TYPE (pp) = FRIBIDI_TYPE_LTR;
1032
11.3k
    prev_type_orig = (RL_LEVEL (pp) == RL_LEVEL (pp->next) ?
1033
11.0k
          FRIBIDI_TYPE_EN : FRIBIDI_TYPE_ON);
1034
11.3k
  }
1035
5.01M
      else
1036
5.01M
  prev_type_orig = PREV_TYPE_OR_SOR (pp->next);
1037
5.03M
    }
1038
1.83k
  }
1039
1040
1.83k
  compact_neutrals (main_run_list);
1041
1042
1.83k
# if DEBUG
1043
1.83k
  if UNLIKELY
1044
1.83k
    (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.83k
# endif /* DEBUG */
1050
1051
  /* 5. Resolving Neutral Types */
1052
1053
1.83k
  DBG ("5. resolving neutral types - N0");
1054
1.83k
  {
1055
    /*  BD16 - Build list of all pairs*/
1056
1.83k
    int num_iso_levels = max_iso_level + 1;
1057
1.83k
    FriBidiPairingNode *pairing_nodes = NULL;
1058
1.83k
    FriBidiRun *local_bracket_stack[FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL][LOCAL_BRACKET_SIZE];
1059
1.83k
    FriBidiRun **bracket_stack[FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL];
1060
1.83k
    int bracket_stack_size[FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL];
1061
1.83k
    int last_level = RL_LEVEL(main_run_list);
1062
1.83k
    int last_iso_level = 0;
1063
1064
1.83k
    memset(bracket_stack, 0, sizeof(bracket_stack[0])*num_iso_levels);
1065
1.83k
    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.83k
    {
1071
1.83k
      int iso_level;
1072
31.1k
      for (iso_level=0; iso_level < LOCAL_BRACKET_SIZE; iso_level++)
1073
29.3k
        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.83k
    }
1079
1080
    /* Build the bd16 pair stack. */
1081
1.83k
    for_run_list (pp, main_run_list)
1082
4.92M
      {
1083
4.92M
        int level = RL_LEVEL(pp);
1084
4.92M
        int iso_level = RL_ISOLATE_LEVEL(pp);
1085
4.92M
        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
4.92M
        if (level != last_level && last_iso_level == iso_level)
1091
8.01k
          bracket_stack_size[last_iso_level] = 0;
1092
1093
4.92M
        if (brack_prop!= FRIBIDI_NO_BRACKET
1094
3.45M
            && RL_TYPE(pp)==FRIBIDI_TYPE_ON)
1095
3.34M
          {
1096
3.34M
            if (FRIBIDI_IS_BRACKET_OPEN(brack_prop))
1097
1.66M
              {
1098
1.66M
                if (bracket_stack_size[iso_level]==FRIBIDI_BIDI_MAX_NESTED_BRACKET_PAIRS)
1099
9
                  break;
1100
1101
                /* push onto the pair stack */
1102
1.66M
                bracket_stack[iso_level][bracket_stack_size[iso_level]++] = pp;
1103
1.66M
              }
1104
1.67M
            else
1105
1.67M
              {
1106
1.67M
                int stack_idx = bracket_stack_size[iso_level] - 1;
1107
1.68M
                while (stack_idx >= 0)
1108
1.64M
                  {
1109
1.64M
                    FriBidiBracketType se_brack_prop = RL_BRACKET_TYPE(bracket_stack[iso_level][stack_idx]);
1110
1.64M
                    if (FRIBIDI_BRACKET_ID(se_brack_prop) == FRIBIDI_BRACKET_ID(brack_prop))
1111
1.64M
                      {
1112
1.64M
                        bracket_stack_size[iso_level] = stack_idx;
1113
1114
1.64M
                        pairing_nodes = pairing_nodes_push(pairing_nodes,
1115
1.64M
                                                           bracket_stack[iso_level][stack_idx],
1116
1.64M
                                                           pp);
1117
1.64M
                        break;
1118
1.64M
                    }
1119
6.45k
                    stack_idx--;
1120
6.45k
                  }
1121
1.67M
              }
1122
3.34M
          }
1123
4.92M
        last_level = level;
1124
4.92M
        last_iso_level = iso_level;
1125
4.92M
      }
1126
1127
    /* The list must now be sorted for the next algo to work! */
1128
1.83k
    sort_pairing_nodes(&pairing_nodes);
1129
1130
1.83k
# if DEBUG
1131
1.83k
    if UNLIKELY
1132
1.83k
    (fribidi_debug_status ())
1133
0
      {
1134
0
        print_pairing_nodes (pairing_nodes);
1135
0
      }
1136
1.83k
# endif /* DEBUG */
1137
1138
    /* Start the N0 */
1139
1.83k
    {
1140
1.83k
      FriBidiPairingNode *ppairs = pairing_nodes;
1141
1.64M
      while (ppairs)
1142
1.64M
        {
1143
1.64M
          int embedding_level = ppairs->open->level; 
1144
1145
          /* Find matching strong. */
1146
1.64M
          fribidi_boolean found = false;
1147
1.64M
          FriBidiRun *ppn;
1148
546M
          for (ppn = ppairs->open; ppn!= ppairs->close; ppn = ppn->next)
1149
545M
            {
1150
545M
              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
545M
              int this_level = RL_LEVEL (ppn) +
1155
545M
                (FRIBIDI_LEVEL_IS_RTL (RL_LEVEL(ppn)) ^ FRIBIDI_DIR_TO_LEVEL (this_type));
1156
1157
              /* N0b */
1158
545M
              if (FRIBIDI_IS_STRONG (this_type) && this_level == embedding_level)
1159
126k
                {
1160
126k
                  RL_TYPE(ppairs->open) = RL_TYPE(ppairs->close) = this_level%2 ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR;
1161
126k
                  found = true;
1162
126k
                  break;
1163
126k
                }
1164
545M
            }
1165
1166
          /* N0c */
1167
          /* Search for any strong type preceding and within the bracket pair */
1168
1.64M
          if (!found)
1169
1.51M
            {
1170
              /* Search for a preceding strong */
1171
1.51M
              int prec_strong_level = embedding_level; /* TBDov! Extract from Isolate level in effect */
1172
1.51M
              int iso_level = RL_ISOLATE_LEVEL(ppairs->open);
1173
449M
              for (ppn = ppairs->open->prev; ppn->type != FRIBIDI_TYPE_SENTINEL; ppn=ppn->prev)
1174
449M
                {
1175
449M
                  FriBidiCharType this_type = RL_TYPE_AN_EN_AS_RTL(ppn);
1176
449M
                  if (FRIBIDI_IS_STRONG (this_type) && RL_ISOLATE_LEVEL(ppn) == iso_level)
1177
1.50M
                    {
1178
1.50M
                      prec_strong_level = RL_LEVEL (ppn) +
1179
1.50M
                        (FRIBIDI_LEVEL_IS_RTL (RL_LEVEL(ppn)) ^ FRIBIDI_DIR_TO_LEVEL (this_type));
1180
1181
1.50M
                      break;
1182
1.50M
                    }
1183
449M
                }
1184
1185
129M
              for (ppn = ppairs->open; ppn!= ppairs->close; ppn = ppn->next)
1186
127M
                {
1187
127M
                  FriBidiCharType this_type = RL_TYPE_AN_EN_AS_RTL(ppn);
1188
127M
                  if (FRIBIDI_IS_STRONG (this_type) && RL_ISOLATE_LEVEL(ppn) == iso_level)
1189
5.78k
                    {
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
5.78k
                      RL_TYPE(ppairs->open) = RL_TYPE(ppairs->close) = prec_strong_level % 2 ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR;
1195
5.78k
                      found = true;
1196
5.78k
                      break;
1197
5.78k
                    }
1198
127M
                }
1199
1.51M
            }
1200
1201
1.64M
          ppairs = ppairs->next;
1202
1.64M
        }
1203
1204
1.83k
      free_pairing_nodes(pairing_nodes);
1205
1206
1.83k
      if (num_iso_levels >= LOCAL_BRACKET_SIZE)
1207
408
        {
1208
408
          int i;
1209
          /* Only need to free the non static members */
1210
23.6k
          for (i=LOCAL_BRACKET_SIZE; i<num_iso_levels; i++)
1211
23.1k
            fribidi_free(bracket_stack[i]);
1212
408
        }
1213
1214
      /* Remove the bracket property and re-compact */
1215
1.83k
      {
1216
1.83k
        const FriBidiBracketType NoBracket = FRIBIDI_NO_BRACKET;
1217
1.83k
        for_run_list (pp, main_run_list)
1218
5.00M
          pp->bracket_type = NoBracket;
1219
1.83k
        compact_neutrals (main_run_list);
1220
1.83k
      }
1221
1.83k
    }
1222
1223
1.83k
# if DEBUG
1224
1.83k
  if UNLIKELY
1225
1.83k
    (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.83k
# endif /* DEBUG */
1231
1.83k
  }
1232
1233
1.83k
  DBG ("resolving neutral types - N1+N2");
1234
1.83k
  {
1235
1.83k
    for_run_list (pp, main_run_list)
1236
1.53M
    {
1237
1.53M
      FriBidiCharType prev_type, this_type, next_type;
1238
1.53M
      FriBidiRun *ppp_prev, *ppp_next;
1239
1240
1.53M
      ppp_prev = get_adjacent_run(pp, false, false);
1241
1.53M
      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
1.53M
      this_type = FRIBIDI_CHANGE_NUMBER_TO_RTL (RL_TYPE (pp));
1246
1247
1.53M
      if (RL_LEVEL(ppp_prev) == RL_LEVEL(pp))
1248
1.45M
        prev_type = FRIBIDI_CHANGE_NUMBER_TO_RTL (RL_TYPE(ppp_prev));
1249
85.0k
      else
1250
85.0k
        prev_type = FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(ppp_prev), RL_LEVEL(pp)));
1251
1252
1.53M
      if (RL_LEVEL(ppp_next) == RL_LEVEL(pp))
1253
1.45M
        next_type = FRIBIDI_CHANGE_NUMBER_TO_RTL (RL_TYPE(ppp_next));
1254
87.9k
      else
1255
87.9k
        next_type = FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(ppp_next), RL_LEVEL(pp)));
1256
1257
1.53M
      if (FRIBIDI_IS_NEUTRAL (this_type))
1258
380k
  RL_TYPE (pp) = (prev_type == next_type) ?
1259
363k
    /* N1. */ prev_type :
1260
380k
    /* N2. */ FRIBIDI_EMBEDDING_DIRECTION (pp);
1261
1.53M
    }
1262
1.83k
  }
1263
1264
1.83k
  compact_list (main_run_list);
1265
1266
1.83k
# if DEBUG
1267
1.83k
  if UNLIKELY
1268
1.83k
    (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.83k
# endif /* DEBUG */
1274
1275
  /* 6. Resolving implicit levels */
1276
1.83k
  DBG ("resolving implicit levels");
1277
1.83k
  {
1278
1.83k
    max_level = base_level;
1279
1280
1.83k
    for_run_list (pp, main_run_list)
1281
876k
    {
1282
876k
      FriBidiCharType this_type;
1283
876k
      int level;
1284
1285
876k
      this_type = RL_TYPE (pp);
1286
876k
      level = RL_LEVEL (pp);
1287
1288
      /* I1. Even */
1289
      /* I2. Odd */
1290
876k
      if (FRIBIDI_IS_NUMBER (this_type))
1291
3.64k
  RL_LEVEL (pp) = (level + 2) & ~1;
1292
872k
      else
1293
872k
  RL_LEVEL (pp) =
1294
872k
    level +
1295
872k
    (FRIBIDI_LEVEL_IS_RTL (level) ^ FRIBIDI_DIR_TO_LEVEL (this_type));
1296
1297
876k
      if (RL_LEVEL (pp) > max_level)
1298
21.1k
  max_level = RL_LEVEL (pp);
1299
876k
    }
1300
1.83k
  }
1301
1302
1.83k
  compact_list (main_run_list);
1303
1304
1.83k
# if DEBUG
1305
1.83k
  if UNLIKELY
1306
1.83k
    (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.83k
# 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.83k
  DBG ("reinserting explicit codes");
1317
1.83k
  if UNLIKELY
1318
1.83k
    (explicits_list->next != explicits_list)
1319
851
    {
1320
851
      register FriBidiRun *p;
1321
851
      register fribidi_boolean stat =
1322
851
  shadow_run_list (main_run_list, explicits_list, true);
1323
851
      explicits_list = NULL;
1324
851
      if UNLIKELY
1325
851
  (!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
851
      p = main_run_list->next;
1330
851
      if (p != main_run_list && p->level == FRIBIDI_SENTINEL)
1331
401
  p->level = base_level;
1332
735k
      for_run_list (p, main_run_list) if (p->level == FRIBIDI_SENTINEL)
1333
193k
  p->level = p->prev->level;
1334
851
    }
1335
1336
1.83k
# if DEBUG
1337
1.83k
  if UNLIKELY
1338
1.83k
    (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.83k
# endif /* DEBUG */
1345
1346
1.83k
  DBG ("reset the embedding levels, 1, 2, 3.");
1347
1.83k
  {
1348
1.83k
    register int j, state, pos;
1349
1.83k
    register FriBidiCharType char_type;
1350
1.83k
    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.83k
    list = new_run_list ();
1361
1.83k
    if UNLIKELY
1362
1.83k
      (!list) goto out;
1363
1.83k
    q = list;
1364
1.83k
    state = 1;
1365
1.83k
    pos = len - 1;
1366
19.8M
    for (j = len - 1; j >= -1; j--)
1367
19.8M
      {
1368
  /* close up the open link at the end */
1369
19.8M
  if (j >= 0)
1370
19.8M
    char_type = bidi_types[j];
1371
1.83k
  else
1372
1.83k
    char_type = FRIBIDI_TYPE_ON;
1373
19.8M
  if (!state && FRIBIDI_IS_SEPARATOR (char_type))
1374
126k
    {
1375
126k
      state = 1;
1376
126k
      pos = j;
1377
126k
    }
1378
19.7M
  else if (state &&
1379
2.48M
                 !(FRIBIDI_IS_EXPLICIT_OR_SEPARATOR_OR_BN_OR_WS(char_type)
1380
290k
                   || FRIBIDI_IS_ISOLATE(char_type)))
1381
128k
    {
1382
128k
      state = 0;
1383
128k
      p = new_run ();
1384
128k
      if UNLIKELY
1385
128k
        (!p)
1386
0
        {
1387
0
    free_run_list (list);
1388
0
    goto out;
1389
0
        }
1390
128k
      p->pos = j + 1;
1391
128k
      p->len = pos - j;
1392
128k
      p->type = base_dir;
1393
128k
      p->level = base_level;
1394
128k
      move_node_before (p, q);
1395
128k
      q = p;
1396
128k
    }
1397
19.8M
      }
1398
1.83k
    if UNLIKELY
1399
1.83k
      (!shadow_run_list (main_run_list, list, false)) goto out;
1400
1.83k
  }
1401
1402
1.83k
# if DEBUG
1403
1.83k
  if UNLIKELY
1404
1.83k
    (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.83k
# endif /* DEBUG */
1411
1412
1.83k
  {
1413
1.83k
    FriBidiStrIndex pos = 0;
1414
1.83k
    for_run_list (pp, main_run_list)
1415
1.45M
    {
1416
1.45M
      register FriBidiStrIndex l;
1417
1.45M
      register FriBidiLevel level = pp->level;
1418
21.2M
      for (l = pp->len; l; l--)
1419
19.8M
  embedding_levels[pos++] = level;
1420
1.45M
    }
1421
1.83k
  }
1422
1423
1.83k
  status = true;
1424
1425
1.83k
out:
1426
1.83k
  DBG ("leaving fribidi_get_par_embedding_levels");
1427
1428
1.83k
  if (main_run_list)
1429
1.83k
    free_run_list (main_run_list);
1430
1.83k
  if UNLIKELY
1431
1.83k
    (explicits_list) free_run_list (explicits_list);
1432
1433
1.83k
  return status ? max_level + 1 : 0;
1434
1.83k
}
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
 */