Coverage Report

Created: 2026-05-30 06:13

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
12.5G
#define RL_TYPE(list) ((list)->type)
50
17.0M
#define RL_LEN(list) ((list)->len)
51
592M
#define RL_LEVEL(list) ((list)->level)
52
53
/* "Within this scope, bidirectional types EN and AN are treated as R" */
54
995M
#define RL_TYPE_AN_EN_AS_RTL(list) ( \
55
995M
 (((list)->type == FRIBIDI_TYPE_AN) || ((list)->type == FRIBIDI_TYPE_EN) | ((list)->type == FRIBIDI_TYPE_RTL)) ? FRIBIDI_TYPE_RTL : (list)->type)
56
24.0M
#define RL_BRACKET_TYPE(list) ((list)->bracket_type)
57
80.9M
#define RL_ISOLATE_LEVEL(list) ((list)->isolate_level)
58
59
35.6k
#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.82M
{
75
5.82M
  FriBidiRun *first;
76
77
5.82M
  fribidi_assert (second);
78
5.82M
  fribidi_assert (second->next);
79
5.82M
  first = second->prev;
80
5.82M
  fribidi_assert (first);
81
82
5.82M
  first->next = second->next;
83
5.82M
  first->next->prev = first;
84
5.82M
  RL_LEN (first) += RL_LEN (second);
85
5.82M
  if (second->next_isolate)
86
5.81M
    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
16.7k
  else if (second->next->prev_isolate == second)
91
0
    second->next->prev_isolate = second->prev_isolate;  
92
5.82M
  if (second->prev_isolate)
93
5.82M
    second->prev_isolate->next_isolate = second->next_isolate;
94
5.82M
  first->next_isolate = second->next_isolate;
95
96
5.82M
  fribidi_free (second);
97
5.82M
  return first;
98
5.82M
}
99
static void
100
compact_list (
101
  FriBidiRun *list
102
)
103
5.55k
{
104
5.55k
  fribidi_assert (list);
105
106
5.55k
  if (list->next)
107
5.55k
    for_run_list (list, list)
108
8.91M
      if (RL_TYPE (list->prev) == RL_TYPE (list)
109
6.04M
    && RL_LEVEL (list->prev) == RL_LEVEL (list)
110
5.84M
          && RL_ISOLATE_LEVEL (list->prev) == RL_ISOLATE_LEVEL (list)
111
5.81M
          && RL_BRACKET_TYPE(list) == FRIBIDI_NO_BRACKET /* Don't join brackets! */
112
2.63M
          && RL_BRACKET_TYPE(list->prev) == FRIBIDI_NO_BRACKET
113
8.91M
          )
114
2.62M
      list = merge_with_prev (list);
115
5.55k
}
116
117
static void
118
compact_neutrals (
119
  FriBidiRun *list
120
)
121
3.70k
{
122
3.70k
  fribidi_assert (list);
123
124
3.70k
  if (list->next)
125
3.70k
    {
126
3.70k
      for_run_list (list, list)
127
9.36M
      {
128
9.36M
  if (RL_LEVEL (list->prev) == RL_LEVEL (list)
129
9.21M
            && RL_ISOLATE_LEVEL (list->prev) == RL_ISOLATE_LEVEL (list)
130
9.18M
      &&
131
9.18M
      ((RL_TYPE (list->prev) == RL_TYPE (list)
132
3.11M
        || (FRIBIDI_IS_NEUTRAL (RL_TYPE (list->prev))
133
1.04M
      && FRIBIDI_IS_NEUTRAL (RL_TYPE (list)))))
134
6.40M
            && RL_BRACKET_TYPE(list) == FRIBIDI_NO_BRACKET /* Don't join brackets! */
135
3.20M
            && RL_BRACKET_TYPE(list->prev) == FRIBIDI_NO_BRACKET
136
9.36M
            )
137
3.18M
    list = merge_with_prev (list);
138
9.36M
      }
139
3.70k
    }
140
3.70k
}
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.8M
{
152
21.8M
  FriBidiRun *ppp = forward ? list->next_isolate : list->prev_isolate;
153
21.8M
  if (!ppp)
154
443k
    return &sentinel;
155
156
21.4M
  while (ppp)
157
21.4M
    {
158
21.4M
      FriBidiCharType ppp_type = RL_TYPE (ppp);
159
160
21.4M
      if (ppp_type == FRIBIDI_TYPE_SENTINEL)
161
6.59k
        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
21.4M
      if (ppp->isolate_level > list->isolate_level   /* <- How can this be true? */
168
21.4M
          || (forward && ppp_type == FRIBIDI_TYPE_PDI)
169
21.3M
          || (skip_neutral && !FRIBIDI_IS_STRONG(ppp_type)))
170
66.2k
        {
171
66.2k
          ppp = forward ? ppp->next_isolate : ppp->prev_isolate;
172
66.2k
          if (!ppp)
173
6.59k
            ppp = &sentinel;
174
175
66.2k
          continue;
176
66.2k
        }
177
21.3M
      break;
178
21.4M
    }
179
180
21.3M
  return ppp;
181
21.8M
}
182
183
#ifdef DEBUG
184
/*======================================================================
185
 *  For debugging, define some functions for printing the types and the
186
 *  levels.
187
 *----------------------------------------------------------------------*/
188
189
static char char_from_level_array[] = {
190
  '$',        /* -1 == FRIBIDI_SENTINEL, indicating
191
         * start or end of string. */
192
  /* 0-61 == 0-9,a-z,A-Z are the the only valid levels before resolving
193
   * implicits.  after that the level @ may be appear too. */
194
  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
195
  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
196
  'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
197
  'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D',
198
  'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
199
  'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
200
  'Y', 'Z',
201
202
  /* TBD - insert another 125-64 levels */
203
204
  '@',        /* 62 == only must appear after resolving
205
         * implicits. */
206
207
  '!',        /* 63 == FRIBIDI_LEVEL_INVALID, internal error,
208
         * this level shouldn't be seen.  */
209
210
  '*', '*', '*', '*', '*' /* >= 64 == overflows, this levels and higher
211
         * levels show a real bug!. */
212
};
213
214
#define fribidi_char_from_level(level) char_from_level_array[(level) + 1]
215
216
static void
217
print_types_re (
218
  const FriBidiRun *pp
219
)
220
0
{
221
0
  fribidi_assert (pp);
222
223
0
  MSG ("  Run types  : ");
224
0
  for_run_list (pp, pp)
225
0
  {
226
0
    MSG6 ("%d:%d(%s)[%d,%d] ",
227
0
    pp->pos, pp->len, fribidi_get_bidi_type_name (pp->type), pp->level, pp->isolate_level);
228
0
  }
229
0
  MSG ("\n");
230
0
}
231
232
static void
233
print_resolved_levels (
234
  const FriBidiRun *pp
235
)
236
0
{
237
0
  fribidi_assert (pp);
238
239
0
  MSG ("  Res. levels: ");
240
0
  for_run_list (pp, pp)
241
0
  {
242
0
    register FriBidiStrIndex i;
243
0
    for (i = RL_LEN (pp); i; i--)
244
0
      MSG2 ("%c", fribidi_char_from_level (RL_LEVEL (pp)));
245
0
  }
246
0
  MSG ("\n");
247
0
}
248
249
static void
250
print_resolved_types (
251
  const FriBidiRun *pp
252
)
253
0
{
254
0
  fribidi_assert (pp);
255
256
0
  MSG ("  Res. types : ");
257
0
  for_run_list (pp, pp)
258
0
  {
259
0
    FriBidiStrIndex i;
260
0
    for (i = RL_LEN (pp); i; i--)
261
0
      MSG2 ("%s ", fribidi_get_bidi_type_name (pp->type));
262
0
  }
263
0
  MSG ("\n");
264
0
}
265
266
static void
267
print_bidi_string (
268
  /* input */
269
  const FriBidiCharType *bidi_types,
270
  const FriBidiStrIndex len
271
)
272
0
{
273
0
  register FriBidiStrIndex i;
274
275
0
  fribidi_assert (bidi_types);
276
277
0
  MSG ("  Org. types : ");
278
0
  for (i = 0; i < len; i++)
279
0
    MSG2 ("%s ", fribidi_get_bidi_type_name (bidi_types[i]));
280
0
  MSG ("\n");
281
0
}
282
283
static void print_pairing_nodes(FriBidiPairingNode *nodes)
284
0
{
285
0
  MSG ("Pairs: ");
286
0
  while (nodes)
287
0
    {
288
0
      MSG3 ("(%d, %d) ", nodes->open->pos, nodes->close->pos);
289
0
      nodes = nodes->next;
290
0
    }
291
0
  MSG ("\n");
292
0
}
293
#endif /* DEBUG */
294
295
296
/*=========================================================================
297
 * define macros for push and pop the status in to / out of the stack
298
 *-------------------------------------------------------------------------*/
299
300
/* There are a few little points in pushing into and popping from the status
301
   stack:
302
   1. when the embedding level is not valid (more than
303
   FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL=125), you must reject it, and not to push
304
   into the stack, but when you see a PDF, you must find the matching code,
305
   and if it was pushed in the stack, pop it, it means you must pop if and
306
   only if you have pushed the matching code, the over_pushed var counts the
307
   number of rejected codes so far.
308
309
   2. there's a more confusing point too, when the embedding level is exactly
310
   FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL-1=124, an LRO, LRE, or LRI is rejected
311
   because the new level would be FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL+1=126, that
312
   is invalid; but an RLO, RLE, or RLI is accepted because the new level is
313
   FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL=125, that is valid, so the rejected codes
314
   may be not continuous in the logical order, in fact there are at most two
315
   continuous intervals of codes, with an RLO, RLE, or RLI between them.  To
316
   support this case, the first_interval var counts the number of rejected
317
   codes in the first interval, when it is 0, means that there is only one
318
   interval.
319
320
*/
321
322
/* a. If this new level would be valid, then this embedding code is valid.
323
   Remember (push) the current embedding level and override status.
324
   Reset current level to this new level, and reset the override status to
325
   new_override.
326
   b. If the new level would not be valid, then this code is invalid. Don't
327
   change the current level or override status.
328
*/
329
#define PUSH_STATUS \
330
744k
    FRIBIDI_BEGIN_STMT \
331
744k
      if LIKELY(over_pushed == 0 \
332
744k
                && isolate_overflow == 0 \
333
744k
                && new_level <= FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL)   \
334
744k
        { \
335
67.4k
          if UNLIKELY(level == FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL - 1) \
336
67.4k
            first_interval = over_pushed; \
337
67.4k
          status_stack[stack_size].level = level; \
338
67.4k
          status_stack[stack_size].isolate_level = isolate_level; \
339
67.4k
          status_stack[stack_size].isolate = isolate; \
340
67.4k
          status_stack[stack_size].override = override; \
341
67.4k
          stack_size++; \
342
67.4k
          level = new_level; \
343
67.4k
          override = new_override; \
344
676k
        } else if LIKELY(isolate_overflow == 0) \
345
676k
    over_pushed++; \
346
744k
    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
385k
    FRIBIDI_BEGIN_STMT \
353
385k
      if (stack_size) \
354
385k
      { \
355
167k
        if UNLIKELY(over_pushed > first_interval) \
356
167k
          over_pushed--; \
357
167k
        else \
358
167k
          { \
359
39.5k
            if LIKELY(over_pushed == first_interval) \
360
39.5k
              first_interval = 0; \
361
39.5k
            stack_size--; \
362
39.5k
            level = status_stack[stack_size].level; \
363
39.5k
            override = status_stack[stack_size].override; \
364
39.5k
            isolate = status_stack[stack_size].isolate; \
365
39.5k
            isolate_level = status_stack[stack_size].isolate_level; \
366
39.5k
          } \
367
167k
      } \
368
385k
    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.68M
    ( \
375
4.68M
      RL_LEVEL(pp->prev) == RL_LEVEL(pp) ? \
376
4.68M
        RL_TYPE(pp->prev) : \
377
4.68M
        FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(pp->prev), RL_LEVEL(pp))) \
378
4.68M
    )
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
15.1k
    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.47M
{
430
1.47M
  FriBidiPairingNode *node = fribidi_malloc(sizeof(FriBidiPairingNode));
431
1.47M
  node->open = open;
432
1.47M
  node->close = close;
433
1.47M
  node->next = nodes;
434
1.47M
  nodes = node;
435
1.47M
  return nodes;
436
1.47M
}
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.47M
{
444
1.47M
  FriBidiPairingNode *pfast, *pslow;
445
1.47M
  if (!source || !source->next)
446
0
    {
447
0
      *front = source;
448
0
      *back = NULL;
449
0
    }
450
1.47M
  else
451
1.47M
    {
452
1.47M
      pslow = source;
453
1.47M
      pfast = source->next;
454
12.5M
      while (pfast)
455
11.0M
        {
456
11.0M
          pfast= pfast->next;
457
11.0M
          if (pfast)
458
10.1M
            {
459
10.1M
              pfast = pfast->next;
460
10.1M
              pslow = pslow->next;
461
10.1M
            }
462
11.0M
        }
463
1.47M
      *front = source;
464
1.47M
      *back = pslow->next;
465
1.47M
      pslow->next = NULL;
466
1.47M
    }
467
1.47M
}
468
469
static FriBidiPairingNode *
470
pairing_nodes_sorted_merge(FriBidiPairingNode *nodes1,
471
                           FriBidiPairingNode *nodes2)
472
13.2M
{
473
13.2M
  FriBidiPairingNode *res = NULL;
474
13.2M
  if (!nodes1)
475
132k
    return nodes2;
476
13.1M
  if (!nodes2)
477
1.33M
    return nodes1;
478
479
11.7M
  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.7M
  else
485
10.7M
    {
486
10.7M
      res = nodes2;
487
10.7M
      res->next = pairing_nodes_sorted_merge(nodes1, nodes2->next);
488
10.7M
    }
489
11.7M
  return res;
490
13.1M
}
491
492
static void sort_pairing_nodes(FriBidiPairingNode **nodes)
493
2.94M
{
494
2.94M
  FriBidiPairingNode *front, *back;
495
496
  /* 0 or 1 node case */
497
2.94M
  if (!*nodes || !(*nodes)->next)
498
1.47M
    return;
499
500
1.47M
  pairing_nodes_front_back_split(*nodes, &front, &back);
501
1.47M
  sort_pairing_nodes(&front);
502
1.47M
  sort_pairing_nodes(&back);
503
1.47M
  *nodes = pairing_nodes_sorted_merge(front, back);
504
1.47M
}
505
506
static void free_pairing_nodes(FriBidiPairingNode *nodes)
507
1.85k
{
508
1.47M
  while (nodes)
509
1.47M
    {
510
1.47M
      FriBidiPairingNode *p = nodes;
511
1.47M
      nodes = nodes->next;
512
1.47M
      fribidi_free(p);
513
1.47M
    }
514
1.85k
}
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.85k
{
528
1.85k
  FriBidiLevel base_level, max_level = 0;
529
1.85k
  FriBidiParType base_dir;
530
1.85k
  FriBidiRun *main_run_list = NULL, *explicits_list = NULL, *pp;
531
1.85k
  fribidi_boolean status = false;
532
1.85k
  int max_iso_level = 0;
533
534
1.85k
  if UNLIKELY
535
1.85k
    (!len)
536
1
    {
537
1
      status = true;
538
1
      goto out;
539
1
    }
540
541
1.85k
  DBG ("in fribidi_get_par_embedding_levels");
542
543
1.85k
  fribidi_assert (bidi_types);
544
1.85k
  fribidi_assert (pbase_dir);
545
1.85k
  fribidi_assert (embedding_levels);
546
547
  /* Determinate character types */
548
1.85k
  {
549
    /* Get run-length encoded character types */
550
1.85k
    main_run_list = run_list_encode_bidi_types (bidi_types, bracket_types, len);
551
1.85k
    if UNLIKELY
552
1.85k
      (!main_run_list) goto out;
553
1.85k
  }
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.85k
  base_level = FRIBIDI_DIR_TO_LEVEL (*pbase_dir);
559
1.85k
  if (!FRIBIDI_IS_STRONG (*pbase_dir))
560
    /* P2. P3. Search for first strong character and use its direction as
561
       base direction */
562
1.85k
    {
563
1.85k
      int valid_isolate_count = 0;
564
1.85k
      for_run_list (pp, main_run_list)
565
1.72M
        {
566
1.72M
          if (RL_TYPE(pp) == FRIBIDI_TYPE_PDI)
567
24.9k
            {
568
              /* Ignore if there is no matching isolate */
569
24.9k
              if (valid_isolate_count>0)
570
8.29k
                valid_isolate_count--;
571
24.9k
            }
572
1.69M
          else if (FRIBIDI_IS_ISOLATE(RL_TYPE(pp)))
573
1.11M
            valid_isolate_count++;
574
585k
          else if (valid_isolate_count==0 && FRIBIDI_IS_LETTER (RL_TYPE (pp)))
575
731
            {
576
731
              base_level = FRIBIDI_DIR_TO_LEVEL (RL_TYPE (pp));
577
731
              *pbase_dir = FRIBIDI_LEVEL_TO_DIR (base_level);
578
731
              break;
579
731
            }
580
1.72M
        }
581
1.85k
    }
582
1.85k
  base_dir = FRIBIDI_LEVEL_TO_DIR (base_level);
583
1.85k
  DBG2 ("  base level : %c", fribidi_char_from_level (base_level));
584
1.85k
  DBG2 ("  base dir   : %s", fribidi_get_bidi_type_name (base_dir));
585
586
1.85k
# if DEBUG
587
1.85k
  if UNLIKELY
588
1.85k
    (fribidi_debug_status ())
589
0
    {
590
0
      print_types_re (main_run_list);
591
0
    }
592
1.85k
# endif /* DEBUG */
593
594
  /* Explicit Levels and Directions */
595
1.85k
  DBG ("explicit levels and directions");
596
1.85k
  {
597
1.85k
    FriBidiLevel level, new_level = 0;
598
1.85k
    int isolate_level = 0;
599
1.85k
    FriBidiCharType override, new_override;
600
1.85k
    FriBidiStrIndex i;
601
1.85k
    int stack_size, over_pushed, first_interval;
602
1.85k
    int valid_isolate_count = 0;
603
1.85k
    int isolate_overflow = 0;
604
1.85k
    int isolate = 0; /* The isolate status flag */
605
1.85k
    struct
606
1.85k
    {
607
1.85k
      FriBidiCharType override; /* only LTR, RTL and ON are valid */
608
1.85k
      FriBidiLevel level;
609
1.85k
      int isolate;
610
1.85k
      int isolate_level;
611
1.85k
    } status_stack[FRIBIDI_BIDI_MAX_RESOLVED_LEVELS];
612
1.85k
    FriBidiRun temp_link;
613
1.85k
    FriBidiRun *run_per_isolate_level[FRIBIDI_BIDI_MAX_RESOLVED_LEVELS];
614
1.85k
    int prev_isolate_level = 0; /* When running over the isolate levels, remember the previous level */
615
616
1.85k
    memset(run_per_isolate_level, 0, sizeof(run_per_isolate_level[0])
617
1.85k
           * 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.85k
    explicits_list = new_run_list ();
624
1.85k
    if UNLIKELY
625
1.85k
      (!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.85k
    level = base_level;
635
1.85k
    override = FRIBIDI_TYPE_ON;
636
    /* stack */
637
1.85k
    stack_size = 0;
638
1.85k
    over_pushed = 0;
639
1.85k
    first_interval = 0;
640
1.85k
    valid_isolate_count = 0;
641
1.85k
    isolate_overflow = 0;
642
643
1.85k
    for_run_list (pp, main_run_list)
644
5.75M
    {
645
5.75M
      FriBidiCharType this_type = RL_TYPE (pp);
646
5.75M
      RL_ISOLATE_LEVEL (pp) = isolate_level;
647
648
5.75M
      if (FRIBIDI_IS_EXPLICIT_OR_BN (this_type))
649
192k
  {
650
192k
    if (FRIBIDI_IS_STRONG (this_type))
651
34.3k
      {     /* 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
34.3k
        new_override = FRIBIDI_EXPLICIT_TO_OVERRIDE_DIR (this_type);
663
715k
        for (i = RL_LEN (pp); i; i--)
664
681k
    {
665
681k
      new_level =
666
681k
        ((level + FRIBIDI_DIR_TO_LEVEL (this_type) + 2) & ~1) -
667
681k
        FRIBIDI_DIR_TO_LEVEL (this_type);
668
681k
                  isolate = 0;
669
681k
      PUSH_STATUS;
670
681k
    }
671
34.3k
      }
672
157k
    else if (this_type == FRIBIDI_TYPE_PDF)
673
116k
      {
674
        /* 3. Terminating Embeddings and overrides */
675
        /*   X7. With each PDF, determine the matching embedding or
676
           override code. */
677
161k
              for (i = RL_LEN (pp); i; i--)
678
147k
                {
679
147k
                  if (stack_size && status_stack[stack_size-1].isolate != 0)
680
102k
                    break;
681
147k
                  POP_STATUS;
682
45.4k
                }
683
116k
      }
684
685
    /* X9. Remove all RLE, LRE, RLO, LRO, PDF, and BN codes. */
686
    /* Remove element and add it to explicits_list */
687
192k
    RL_LEVEL (pp) = FRIBIDI_SENTINEL;
688
192k
    temp_link.next = pp->next;
689
192k
    move_node_before (pp, explicits_list);
690
192k
    pp = &temp_link;
691
192k
  }
692
5.55M
      else if (this_type == FRIBIDI_TYPE_PDI)
693
        /* X6a. pop the direction of the stack */
694
599k
        {
695
1.19M
          for (i = RL_LEN (pp); i; i--)
696
599k
            {
697
599k
              if (isolate_overflow > 0)
698
12.2k
                {
699
12.2k
                  isolate_overflow--;
700
12.2k
                  RL_LEVEL (pp) = level;
701
12.2k
                }
702
703
587k
              else if (valid_isolate_count > 0)
704
9.97k
                {
705
                  /* Pop away all LRE,RLE,LRO, RLO levels
706
                     from the stack, as these are implicitly
707
                     terminated by the PDI */
708
152k
                  while (stack_size && !status_stack[stack_size-1].isolate)
709
142k
                    POP_STATUS;
710
9.97k
                  over_pushed = 0; /* The PDI resets the overpushed! */
711
9.97k
                  POP_STATUS;
712
9.97k
                  if (isolate_level>0)
713
8.46k
                    isolate_level--;
714
9.97k
                  valid_isolate_count--;
715
9.97k
                  RL_LEVEL (pp) = level;
716
9.97k
                  RL_ISOLATE_LEVEL (pp) = isolate_level;
717
9.97k
                }
718
577k
              else
719
577k
                {
720
                  /* Ignore isolated PDI's by turning them into ON's */
721
577k
                  RL_TYPE (pp) = FRIBIDI_TYPE_ON;
722
577k
                  RL_LEVEL (pp) = level;
723
577k
                }
724
599k
            }
725
599k
        }
726
4.96M
      else if (FRIBIDI_IS_ISOLATE(this_type))
727
1.22M
        {
728
          /* TBD support RL_LEN > 1 */
729
1.22M
          new_override = FRIBIDI_TYPE_ON;
730
1.22M
          isolate = 1;
731
1.22M
          if (this_type == FRIBIDI_TYPE_LRI)
732
876k
            new_level = level + 2 - (level%2);
733
349k
          else if (this_type == FRIBIDI_TYPE_RLI)
734
5.38k
            new_level = level + 1 + (level%2);
735
344k
          else if (this_type == FRIBIDI_TYPE_FSI)
736
344k
            {
737
              /* Search for a local strong character until we
738
                 meet the corresponding PDI or the end of the
739
                 paragraph */
740
344k
              FriBidiRun *fsi_pp;
741
344k
              int isolate_count = 0;
742
344k
              int fsi_base_level = 0;
743
344k
              for_run_list (fsi_pp, pp)
744
12.3G
                {
745
12.3G
                  if (RL_TYPE(fsi_pp) == FRIBIDI_TYPE_PDI)
746
71.0M
                    {
747
71.0M
                      isolate_count--;
748
71.0M
                      if (valid_isolate_count < 0)
749
0
                        break;
750
71.0M
                    }
751
12.3G
                  else if (FRIBIDI_IS_ISOLATE(RL_TYPE(fsi_pp)))
752
3.30G
                    isolate_count++;
753
9.01G
                  else if (isolate_count==0 && FRIBIDI_IS_LETTER (RL_TYPE (fsi_pp)))
754
16.9k
                    {
755
16.9k
                      fsi_base_level = FRIBIDI_DIR_TO_LEVEL (RL_TYPE (fsi_pp));
756
16.9k
                      break;
757
16.9k
                    }
758
12.3G
                }
759
760
              /* Same behavior like RLI and LRI above */
761
344k
              if (FRIBIDI_LEVEL_IS_RTL (fsi_base_level))
762
1.01k
                new_level = level + 1 + (level%2);
763
343k
              else
764
343k
                new_level = level + 2 - (level%2);
765
344k
            }
766
767
1.22M
    RL_LEVEL (pp) = level;
768
1.22M
          RL_ISOLATE_LEVEL (pp) = isolate_level;
769
1.22M
          if (isolate_level < FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL-1)
770
75.2k
              isolate_level++;
771
772
1.22M
    if (!FRIBIDI_IS_NEUTRAL (override))
773
44.5k
      RL_TYPE (pp) = override;
774
775
1.22M
          if (new_level <= FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL)
776
62.9k
            {
777
62.9k
              valid_isolate_count++;
778
62.9k
              PUSH_STATUS;
779
62.9k
              level = new_level;
780
62.9k
            }
781
1.16M
          else
782
1.16M
            isolate_overflow += 1;
783
1.22M
        }
784
3.73M
      else if (this_type == FRIBIDI_TYPE_BS)
785
280
  {
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
280
    break;
790
280
  }
791
3.73M
      else
792
3.73M
  {
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.73M
    RL_LEVEL (pp) = level;
800
3.73M
    if (!FRIBIDI_IS_NEUTRAL (override))
801
281k
      RL_TYPE (pp) = override;
802
3.73M
  }
803
5.75M
    }
804
805
    /* Build the isolate_level connections */
806
1.85k
    prev_isolate_level = 0;
807
1.85k
    for_run_list (pp, main_run_list)
808
6.61M
    {
809
6.61M
      int isolate_level = RL_ISOLATE_LEVEL (pp);
810
6.61M
      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.61M
      if (isolate_level<prev_isolate_level)
815
58.6k
        for (i=isolate_level+1; i<=prev_isolate_level; i++)
816
48.3k
          run_per_isolate_level[i]=0;
817
6.61M
      prev_isolate_level = isolate_level;
818
      
819
6.61M
      if (run_per_isolate_level[isolate_level])
820
6.54M
        {
821
6.54M
          run_per_isolate_level[isolate_level]->next_isolate = pp;
822
6.54M
          pp->prev_isolate = run_per_isolate_level[isolate_level];
823
6.54M
        }
824
6.61M
      run_per_isolate_level[isolate_level] = pp;
825
6.61M
    }
826
827
    /* Implementing X8. It has no effect on a single paragraph! */
828
1.85k
    level = base_level;
829
1.85k
    override = FRIBIDI_TYPE_ON;
830
1.85k
    stack_size = 0;
831
1.85k
    over_pushed = 0;
832
1.85k
  }
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.85k
# if DEBUG
846
1.85k
  if UNLIKELY
847
1.85k
    (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.85k
# endif /* DEBUG */
855
856
  /* 4. Resolving weak types. Also calculate the maximum isolate level */
857
1.85k
  max_iso_level = 0;
858
1.85k
  DBG ("4a. resolving weak types");
859
1.85k
  {
860
1.85k
    int last_strong_stack[FRIBIDI_BIDI_MAX_RESOLVED_LEVELS];
861
1.85k
    FriBidiCharType prev_type_orig;
862
1.85k
    fribidi_boolean w4;
863
864
1.85k
    last_strong_stack[0] = base_dir;
865
866
1.85k
    for_run_list (pp, main_run_list)
867
4.70M
    {
868
4.70M
      register FriBidiCharType prev_type, this_type, next_type;
869
4.70M
      FriBidiRun *ppp_prev, *ppp_next;
870
4.70M
      int iso_level;
871
872
4.70M
      ppp_prev = get_adjacent_run(pp, false, false);
873
4.70M
      ppp_next = get_adjacent_run(pp, true, false);
874
875
4.70M
      this_type = RL_TYPE (pp);
876
4.70M
      iso_level = RL_ISOLATE_LEVEL(pp);
877
878
4.70M
      if (iso_level > max_iso_level)
879
30.3k
        max_iso_level = iso_level;
880
881
4.70M
      if (RL_LEVEL(ppp_prev) == RL_LEVEL(pp))
882
4.62M
        prev_type = RL_TYPE(ppp_prev);
883
83.6k
      else
884
83.6k
        prev_type = FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(ppp_prev), RL_LEVEL(pp)));
885
886
4.70M
      if (RL_LEVEL(ppp_next) == RL_LEVEL(pp))
887
4.61M
        next_type = RL_TYPE(ppp_next);
888
85.6k
      else
889
85.6k
        next_type = FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(ppp_next), RL_LEVEL(pp)));
890
891
4.70M
      if (FRIBIDI_IS_STRONG (prev_type))
892
984k
  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.70M
      if (this_type == FRIBIDI_TYPE_NSM)
903
11.2k
  {
904
          /* New rule in Unicode 6.3 */
905
11.2k
          if (FRIBIDI_IS_ISOLATE (RL_TYPE (pp->prev)))
906
1.49k
              RL_TYPE(pp) = FRIBIDI_TYPE_ON;
907
908
11.2k
    if (RL_LEVEL (ppp_prev) == RL_LEVEL (pp))
909
10.3k
            {
910
10.3k
              if (ppp_prev == pp->prev)
911
9.96k
                pp = merge_with_prev (pp);
912
10.3k
            }
913
876
    else
914
876
      RL_TYPE (pp) = prev_type;
915
916
11.2k
    if (prev_type == next_type && RL_LEVEL (pp) == RL_LEVEL (pp->next))
917
6.55k
      {
918
6.55k
              if (ppp_next == pp->next)
919
5.88k
                pp = merge_with_prev (pp->next);
920
6.55k
      }
921
11.2k
    continue;   /* As we know the next condition cannot be true. */
922
11.2k
  }
923
924
      /* W2: European numbers. */
925
4.69M
      if (this_type == FRIBIDI_TYPE_EN && last_strong_stack[iso_level] == FRIBIDI_TYPE_AL)
926
1.84k
  {
927
1.84k
    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.84k
    if (next_type == FRIBIDI_TYPE_NSM)
932
530
      RL_TYPE (ppp_next) = FRIBIDI_TYPE_AN;
933
1.84k
  }
934
4.69M
    }
935
936
1.85k
# if DEBUG
937
1.85k
  if UNLIKELY
938
1.85k
    (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.85k
# 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.85k
    last_strong_stack[0] = base_dir;
949
950
1.85k
    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.85k
    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.85k
    prev_type_orig = FRIBIDI_TYPE_ON;
960
961
    /* Each isolate level has its own memory of the last strong character */
962
1.85k
    for_run_list (pp, main_run_list)
963
4.69M
    {
964
4.69M
      register FriBidiCharType prev_type, this_type, next_type;
965
4.69M
      int iso_level;
966
4.69M
      FriBidiRun *ppp_prev, *ppp_next;
967
968
4.69M
      this_type = RL_TYPE (pp);
969
4.69M
      iso_level = RL_ISOLATE_LEVEL(pp);
970
971
4.69M
      ppp_prev = get_adjacent_run(pp, false, false);
972
4.69M
      ppp_next = get_adjacent_run(pp, true, false);
973
974
4.69M
      if (RL_LEVEL(ppp_prev) == RL_LEVEL(pp))
975
4.61M
        prev_type = RL_TYPE(ppp_prev);
976
83.6k
      else
977
83.6k
        prev_type = FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(ppp_prev), RL_LEVEL(pp)));
978
979
4.69M
      if (RL_LEVEL(ppp_next) == RL_LEVEL(pp))
980
4.60M
        next_type = RL_TYPE(ppp_next);
981
86.1k
      else
982
86.1k
        next_type = FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(ppp_next), RL_LEVEL(pp)));
983
984
4.69M
      if (FRIBIDI_IS_STRONG (prev_type))
985
987k
  last_strong_stack[iso_level] = prev_type;
986
987
      /* W2 ??? */
988
989
      /* W3: Change ALs to R. */
990
4.69M
      if (this_type == FRIBIDI_TYPE_AL)
991
4.00k
  {
992
4.00k
    RL_TYPE (pp) = FRIBIDI_TYPE_RTL;
993
4.00k
    w4 = true;
994
4.00k
    prev_type_orig = FRIBIDI_TYPE_ON;
995
4.00k
    continue;
996
4.00k
  }
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.69M
      if (w4
1002
4.69M
    && RL_LEN (pp) == 1 && FRIBIDI_IS_ES_OR_CS (this_type)
1003
7.95k
    && FRIBIDI_IS_NUMBER (prev_type_orig)
1004
2.00k
    && prev_type_orig == next_type
1005
1.37k
    && (prev_type_orig == FRIBIDI_TYPE_EN
1006
659
        || this_type == FRIBIDI_TYPE_CS))
1007
953
  {
1008
953
    RL_TYPE (pp) = prev_type;
1009
953
    this_type = RL_TYPE (pp);
1010
953
  }
1011
4.69M
      w4 = true;
1012
1013
      /* W5. A sequence of European terminators adjacent to European
1014
         numbers changes to All European numbers. */
1015
4.69M
      if (this_type == FRIBIDI_TYPE_ET
1016
5.54k
    && (prev_type_orig == FRIBIDI_TYPE_EN
1017
4.35k
        || next_type == FRIBIDI_TYPE_EN))
1018
1.51k
  {
1019
1.51k
    RL_TYPE (pp) = FRIBIDI_TYPE_EN;
1020
1.51k
    w4 = false;
1021
1.51k
    this_type = RL_TYPE (pp);
1022
1.51k
  }
1023
1024
      /* W6. Otherwise change separators and terminators to other neutral. */
1025
4.69M
      if (FRIBIDI_IS_NUMBER_SEPARATOR_OR_TERMINATOR (this_type))
1026
11.0k
  RL_TYPE (pp) = FRIBIDI_TYPE_ON;
1027
1028
      /* W7. Change european numbers to L. */
1029
4.69M
      if (this_type == FRIBIDI_TYPE_EN && last_strong_stack[iso_level] == FRIBIDI_TYPE_LTR)
1030
9.10k
  {
1031
9.10k
    RL_TYPE (pp) = FRIBIDI_TYPE_LTR;
1032
9.10k
    prev_type_orig = (RL_LEVEL (pp) == RL_LEVEL (pp->next) ?
1033
8.98k
          FRIBIDI_TYPE_EN : FRIBIDI_TYPE_ON);
1034
9.10k
  }
1035
4.68M
      else
1036
4.68M
  prev_type_orig = PREV_TYPE_OR_SOR (pp->next);
1037
4.69M
    }
1038
1.85k
  }
1039
1040
1.85k
  compact_neutrals (main_run_list);
1041
1042
1.85k
# if DEBUG
1043
1.85k
  if UNLIKELY
1044
1.85k
    (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.85k
# endif /* DEBUG */
1050
1051
  /* 5. Resolving Neutral Types */
1052
1053
1.85k
  DBG ("5. resolving neutral types - N0");
1054
1.85k
  {
1055
    /*  BD16 - Build list of all pairs*/
1056
1.85k
    int num_iso_levels = max_iso_level + 1;
1057
1.85k
    FriBidiPairingNode *pairing_nodes = NULL;
1058
1.85k
    FriBidiRun *local_bracket_stack[FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL][LOCAL_BRACKET_SIZE];
1059
1.85k
    FriBidiRun **bracket_stack[FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL];
1060
1.85k
    int bracket_stack_size[FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL];
1061
1.85k
    int last_level = RL_LEVEL(main_run_list);
1062
1.85k
    int last_iso_level = 0;
1063
1064
1.85k
    memset(bracket_stack, 0, sizeof(bracket_stack[0])*num_iso_levels);
1065
1.85k
    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.85k
    {
1071
1.85k
      int iso_level;
1072
31.5k
      for (iso_level=0; iso_level < LOCAL_BRACKET_SIZE; iso_level++)
1073
29.6k
        bracket_stack[iso_level] = local_bracket_stack[iso_level];
1074
1075
24.9k
      for (iso_level=LOCAL_BRACKET_SIZE; iso_level < num_iso_levels; iso_level++)
1076
23.0k
        bracket_stack[iso_level] = fribidi_malloc (sizeof (bracket_stack[0])
1077
23.0k
                                                       * FRIBIDI_BIDI_MAX_NESTED_BRACKET_PAIRS);
1078
1.85k
    }
1079
1080
    /* Build the bd16 pair stack. */
1081
1.85k
    for_run_list (pp, main_run_list)
1082
4.52M
      {
1083
4.52M
        int level = RL_LEVEL(pp);
1084
4.52M
        int iso_level = RL_ISOLATE_LEVEL(pp);
1085
4.52M
        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.52M
        if (level != last_level && last_iso_level == iso_level)
1091
8.62k
          bracket_stack_size[last_iso_level] = 0;
1092
1093
4.52M
        if (brack_prop!= FRIBIDI_NO_BRACKET
1094
3.11M
            && RL_TYPE(pp)==FRIBIDI_TYPE_ON)
1095
2.99M
          {
1096
2.99M
            if (FRIBIDI_IS_BRACKET_OPEN(brack_prop))
1097
1.49M
              {
1098
1.49M
                if (bracket_stack_size[iso_level]==FRIBIDI_BIDI_MAX_NESTED_BRACKET_PAIRS)
1099
21
                  break;
1100
1101
                /* push onto the pair stack */
1102
1.49M
                bracket_stack[iso_level][bracket_stack_size[iso_level]++] = pp;
1103
1.49M
              }
1104
1.50M
            else
1105
1.50M
              {
1106
1.50M
                int stack_idx = bracket_stack_size[iso_level] - 1;
1107
1.50M
                while (stack_idx >= 0)
1108
1.47M
                  {
1109
1.47M
                    FriBidiBracketType se_brack_prop = RL_BRACKET_TYPE(bracket_stack[iso_level][stack_idx]);
1110
1.47M
                    if (FRIBIDI_BRACKET_ID(se_brack_prop) == FRIBIDI_BRACKET_ID(brack_prop))
1111
1.47M
                      {
1112
1.47M
                        bracket_stack_size[iso_level] = stack_idx;
1113
1114
1.47M
                        pairing_nodes = pairing_nodes_push(pairing_nodes,
1115
1.47M
                                                           bracket_stack[iso_level][stack_idx],
1116
1.47M
                                                           pp);
1117
1.47M
                        break;
1118
1.47M
                    }
1119
6.70k
                    stack_idx--;
1120
6.70k
                  }
1121
1.50M
              }
1122
2.99M
          }
1123
4.52M
        last_level = level;
1124
4.52M
        last_iso_level = iso_level;
1125
4.52M
      }
1126
1127
    /* The list must now be sorted for the next algo to work! */
1128
1.85k
    sort_pairing_nodes(&pairing_nodes);
1129
1130
1.85k
# if DEBUG
1131
1.85k
    if UNLIKELY
1132
1.85k
    (fribidi_debug_status ())
1133
0
      {
1134
0
        print_pairing_nodes (pairing_nodes);
1135
0
      }
1136
1.85k
# endif /* DEBUG */
1137
1138
    /* Start the N0 */
1139
1.85k
    {
1140
1.85k
      FriBidiPairingNode *ppairs = pairing_nodes;
1141
1.47M
      while (ppairs)
1142
1.47M
        {
1143
1.47M
          int embedding_level = ppairs->open->level; 
1144
1145
          /* Find matching strong. */
1146
1.47M
          fribidi_boolean found = false;
1147
1.47M
          FriBidiRun *ppn;
1148
477M
          for (ppn = ppairs->open; ppn!= ppairs->close; ppn = ppn->next)
1149
476M
            {
1150
476M
              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
476M
              int this_level = RL_LEVEL (ppn) +
1155
476M
                (FRIBIDI_LEVEL_IS_RTL (RL_LEVEL(ppn)) ^ FRIBIDI_DIR_TO_LEVEL (this_type));
1156
1157
              /* N0b */
1158
476M
              if (FRIBIDI_IS_STRONG (this_type) && this_level == embedding_level)
1159
123k
                {
1160
123k
                  RL_TYPE(ppairs->open) = RL_TYPE(ppairs->close) = this_level%2 ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR;
1161
123k
                  found = true;
1162
123k
                  break;
1163
123k
                }
1164
476M
            }
1165
1166
          /* N0c */
1167
          /* Search for any strong type preceding and within the bracket pair */
1168
1.47M
          if (!found)
1169
1.34M
            {
1170
              /* Search for a preceding strong */
1171
1.34M
              int prec_strong_level = embedding_level; /* TBDov! Extract from Isolate level in effect */
1172
1.34M
              int iso_level = RL_ISOLATE_LEVEL(ppairs->open);
1173
411M
              for (ppn = ppairs->open->prev; ppn->type != FRIBIDI_TYPE_SENTINEL; ppn=ppn->prev)
1174
411M
                {
1175
411M
                  FriBidiCharType this_type = RL_TYPE_AN_EN_AS_RTL(ppn);
1176
411M
                  if (FRIBIDI_IS_STRONG (this_type) && RL_ISOLATE_LEVEL(ppn) == iso_level)
1177
1.33M
                    {
1178
1.33M
                      prec_strong_level = RL_LEVEL (ppn) +
1179
1.33M
                        (FRIBIDI_LEVEL_IS_RTL (RL_LEVEL(ppn)) ^ FRIBIDI_DIR_TO_LEVEL (this_type));
1180
1181
1.33M
                      break;
1182
1.33M
                    }
1183
411M
                }
1184
1185
108M
              for (ppn = ppairs->open; ppn!= ppairs->close; ppn = ppn->next)
1186
107M
                {
1187
107M
                  FriBidiCharType this_type = RL_TYPE_AN_EN_AS_RTL(ppn);
1188
107M
                  if (FRIBIDI_IS_STRONG (this_type) && RL_ISOLATE_LEVEL(ppn) == iso_level)
1189
6.16k
                    {
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
6.16k
                      RL_TYPE(ppairs->open) = RL_TYPE(ppairs->close) = prec_strong_level % 2 ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR;
1195
6.16k
                      found = true;
1196
6.16k
                      break;
1197
6.16k
                    }
1198
107M
                }
1199
1.34M
            }
1200
1201
1.47M
          ppairs = ppairs->next;
1202
1.47M
        }
1203
1204
1.85k
      free_pairing_nodes(pairing_nodes);
1205
1206
1.85k
      if (num_iso_levels >= LOCAL_BRACKET_SIZE)
1207
405
        {
1208
405
          int i;
1209
          /* Only need to free the non static members */
1210
23.4k
          for (i=LOCAL_BRACKET_SIZE; i<num_iso_levels; i++)
1211
23.0k
            fribidi_free(bracket_stack[i]);
1212
405
        }
1213
1214
      /* Remove the bracket property and re-compact */
1215
1.85k
      {
1216
1.85k
        const FriBidiBracketType NoBracket = FRIBIDI_NO_BRACKET;
1217
1.85k
        for_run_list (pp, main_run_list)
1218
4.67M
          pp->bracket_type = NoBracket;
1219
1.85k
        compact_neutrals (main_run_list);
1220
1.85k
      }
1221
1.85k
    }
1222
1223
1.85k
# if DEBUG
1224
1.85k
  if UNLIKELY
1225
1.85k
    (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.85k
# endif /* DEBUG */
1231
1.85k
  }
1232
1233
1.85k
  DBG ("resolving neutral types - N1+N2");
1234
1.85k
  {
1235
1.85k
    for_run_list (pp, main_run_list)
1236
1.50M
    {
1237
1.50M
      FriBidiCharType prev_type, this_type, next_type;
1238
1.50M
      FriBidiRun *ppp_prev, *ppp_next;
1239
1240
1.50M
      ppp_prev = get_adjacent_run(pp, false, false);
1241
1.50M
      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.50M
      this_type = FRIBIDI_CHANGE_NUMBER_TO_RTL (RL_TYPE (pp));
1246
1247
1.50M
      if (RL_LEVEL(ppp_prev) == RL_LEVEL(pp))
1248
1.42M
        prev_type = FRIBIDI_CHANGE_NUMBER_TO_RTL (RL_TYPE(ppp_prev));
1249
83.6k
      else
1250
83.6k
        prev_type = FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(ppp_prev), RL_LEVEL(pp)));
1251
1252
1.50M
      if (RL_LEVEL(ppp_next) == RL_LEVEL(pp))
1253
1.42M
        next_type = FRIBIDI_CHANGE_NUMBER_TO_RTL (RL_TYPE(ppp_next));
1254
85.8k
      else
1255
85.8k
        next_type = FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(ppp_next), RL_LEVEL(pp)));
1256
1257
1.50M
      if (FRIBIDI_IS_NEUTRAL (this_type))
1258
404k
  RL_TYPE (pp) = (prev_type == next_type) ?
1259
388k
    /* N1. */ prev_type :
1260
404k
    /* N2. */ FRIBIDI_EMBEDDING_DIRECTION (pp);
1261
1.50M
    }
1262
1.85k
  }
1263
1264
1.85k
  compact_list (main_run_list);
1265
1266
1.85k
# if DEBUG
1267
1.85k
  if UNLIKELY
1268
1.85k
    (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.85k
# endif /* DEBUG */
1274
1275
  /* 6. Resolving implicit levels */
1276
1.85k
  DBG ("resolving implicit levels");
1277
1.85k
  {
1278
1.85k
    max_level = base_level;
1279
1280
1.85k
    for_run_list (pp, main_run_list)
1281
790k
    {
1282
790k
      FriBidiCharType this_type;
1283
790k
      int level;
1284
1285
790k
      this_type = RL_TYPE (pp);
1286
790k
      level = RL_LEVEL (pp);
1287
1288
      /* I1. Even */
1289
      /* I2. Odd */
1290
790k
      if (FRIBIDI_IS_NUMBER (this_type))
1291
2.84k
  RL_LEVEL (pp) = (level + 2) & ~1;
1292
787k
      else
1293
787k
  RL_LEVEL (pp) =
1294
787k
    level +
1295
787k
    (FRIBIDI_LEVEL_IS_RTL (level) ^ FRIBIDI_DIR_TO_LEVEL (this_type));
1296
1297
790k
      if (RL_LEVEL (pp) > max_level)
1298
21.5k
  max_level = RL_LEVEL (pp);
1299
790k
    }
1300
1.85k
  }
1301
1302
1.85k
  compact_list (main_run_list);
1303
1304
1.85k
# if DEBUG
1305
1.85k
  if UNLIKELY
1306
1.85k
    (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.85k
# 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.85k
  DBG ("reinserting explicit codes");
1317
1.85k
  if UNLIKELY
1318
1.85k
    (explicits_list->next != explicits_list)
1319
809
    {
1320
809
      register FriBidiRun *p;
1321
809
      register fribidi_boolean stat =
1322
809
  shadow_run_list (main_run_list, explicits_list, true);
1323
809
      explicits_list = NULL;
1324
809
      if UNLIKELY
1325
809
  (!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
809
      p = main_run_list->next;
1330
809
      if (p != main_run_list && p->level == FRIBIDI_SENTINEL)
1331
352
  p->level = base_level;
1332
700k
      for_run_list (p, main_run_list) if (p->level == FRIBIDI_SENTINEL)
1333
191k
  p->level = p->prev->level;
1334
809
    }
1335
1336
1.85k
# if DEBUG
1337
1.85k
  if UNLIKELY
1338
1.85k
    (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.85k
# endif /* DEBUG */
1345
1346
1.85k
  DBG ("reset the embedding levels, 1, 2, 3.");
1347
1.85k
  {
1348
1.85k
    register int j, state, pos;
1349
1.85k
    register FriBidiCharType char_type;
1350
1.85k
    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.85k
    list = new_run_list ();
1361
1.85k
    if UNLIKELY
1362
1.85k
      (!list) goto out;
1363
1.85k
    q = list;
1364
1.85k
    state = 1;
1365
1.85k
    pos = len - 1;
1366
20.8M
    for (j = len - 1; j >= -1; j--)
1367
20.8M
      {
1368
  /* close up the open link at the end */
1369
20.8M
  if (j >= 0)
1370
20.8M
    char_type = bidi_types[j];
1371
1.85k
  else
1372
1.85k
    char_type = FRIBIDI_TYPE_ON;
1373
20.8M
  if (!state && FRIBIDI_IS_SEPARATOR (char_type))
1374
109k
    {
1375
109k
      state = 1;
1376
109k
      pos = j;
1377
109k
    }
1378
20.6M
  else if (state &&
1379
3.10M
                 !(FRIBIDI_IS_EXPLICIT_OR_SEPARATOR_OR_BN_OR_WS(char_type)
1380
261k
                   || FRIBIDI_IS_ISOLATE(char_type)))
1381
111k
    {
1382
111k
      state = 0;
1383
111k
      p = new_run ();
1384
111k
      if UNLIKELY
1385
111k
        (!p)
1386
0
        {
1387
0
    free_run_list (list);
1388
0
    goto out;
1389
0
        }
1390
111k
      p->pos = j + 1;
1391
111k
      p->len = pos - j;
1392
111k
      p->type = base_dir;
1393
111k
      p->level = base_level;
1394
111k
      move_node_before (p, q);
1395
111k
      q = p;
1396
111k
    }
1397
20.8M
      }
1398
1.85k
    if UNLIKELY
1399
1.85k
      (!shadow_run_list (main_run_list, list, false)) goto out;
1400
1.85k
  }
1401
1402
1.85k
# if DEBUG
1403
1.85k
  if UNLIKELY
1404
1.85k
    (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.85k
# endif /* DEBUG */
1411
1412
1.85k
  {
1413
1.85k
    FriBidiStrIndex pos = 0;
1414
1.85k
    for_run_list (pp, main_run_list)
1415
1.32M
    {
1416
1.32M
      register FriBidiStrIndex l;
1417
1.32M
      register FriBidiLevel level = pp->level;
1418
22.1M
      for (l = pp->len; l; l--)
1419
20.8M
  embedding_levels[pos++] = level;
1420
1.32M
    }
1421
1.85k
  }
1422
1423
1.85k
  status = true;
1424
1425
1.85k
out:
1426
1.85k
  DBG ("leaving fribidi_get_par_embedding_levels");
1427
1428
1.85k
  if (main_run_list)
1429
1.85k
    free_run_list (main_run_list);
1430
1.85k
  if UNLIKELY
1431
1.85k
    (explicits_list) free_run_list (explicits_list);
1432
1433
1.85k
  return status ? max_level + 1 : 0;
1434
1.85k
}
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
 */