Coverage Report

Created: 2023-09-25 06:03

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