Coverage Report

Created: 2026-07-16 07:04

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