Coverage Report

Created: 2025-12-14 06:22

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