private byte resolveExplicitLevels() {
        int i = 0;
        byte dirProp;
        byte level = GetParaLevelAt(0);
        byte dirct;
        isolateCount = 0;

        /* determine if the text is mixed-directional or single-directional */
        dirct = directionFromFlags();

        /* we may not need to resolve any explicit levels */
        if (dirct != MIXED) {
            /* not mixed directionality: levels don't matter - trailingWSStart will be 0 */
            return dirct;
        }
        if (reorderingMode > REORDER_LAST_LOGICAL_TO_VISUAL) {
            /* inverse BiDi: mixed, but all characters are at the same embedding level */
            /* set all levels to the paragraph level */
            int paraIndex, start, limit;
            for (paraIndex = 0; paraIndex < paraCount; paraIndex++) {
                if (paraIndex == 0)
                    start = 0;
                else
                    start = paras_limit[paraIndex - 1];
                limit = paras_limit[paraIndex];
                level = paras_level[paraIndex];
                for (i = start; i < limit; i++)
                    levels[i] =level;
            }
            return dirct;               /* no bracket matching for inverse BiDi */
        }
        if ((flags & (MASK_EXPLICIT | MASK_ISO)) == 0) {
            /* no embeddings, set all levels to the paragraph level */
            /* we still have to perform bracket matching */
            int paraIndex, start, limit;
            BracketData bracketData = new BracketData();
            bracketInit(bracketData);
            for (paraIndex = 0; paraIndex < paraCount; paraIndex++) {
                if (paraIndex == 0)
                    start = 0;
                else
                    start = paras_limit[paraIndex-1];
                limit = paras_limit[paraIndex];
                level = paras_level[paraIndex];
                for (i = start; i < limit; i++) {
                    levels[i] = level;
                    dirProp = dirProps[i];
                    if (dirProp == BN)
                        continue;
                    if (dirProp == B) {
                        if ((i + 1) < length) {
                            if (text[i] == CR && text[i + 1] == LF)
                                continue;   /* skip CR when followed by LF */
                            bracketProcessB(bracketData, level);
                        }
                        continue;
                    }
                    bracketProcessChar(bracketData, i);
                }
            }
            return dirct;
        }
        /* continue to perform (Xn) */

        /* (X1) level is set for all codes, embeddingLevel keeps track of the push/pop operations */
        /* both variables may carry the LEVEL_OVERRIDE flag to indicate the override status */
        byte embeddingLevel = level, newLevel;
        byte previousLevel = level; /* previous level for regular (not CC) characters */
        int lastCcPos = 0;          /* index of last effective LRx,RLx, PDx */

        /* The following stack remembers the embedding level and the ISOLATE flag of level runs.
           stackLast points to its current entry. */
        short[] stack = new short[MAX_EXPLICIT_LEVEL + 2];  /* we never push anything >= MAX_EXPLICIT_LEVEL
                                                               but we need one more entry as base */
        int stackLast = 0;
        int overflowIsolateCount = 0;
        int overflowEmbeddingCount = 0;
        int validIsolateCount = 0;
        BracketData bracketData = new BracketData();
        bracketInit(bracketData);
        stack[0] = level;       /* initialize base entry to para level, no override, no isolate */

        /* recalculate the flags */
        flags = 0;

        for (i = 0; i < length; i++) {
            dirProp = dirProps[i];
            switch (dirProp) {
            case LRE:
            case RLE:
            case LRO:
            case RLO:
                /* (X2, X3, X4, X5) */
                flags |= DirPropFlag(BN);
                levels[i] = previousLevel;
                if (dirProp == LRE || dirProp == LRO)
                    /* least greater even level */
                    newLevel = (byte)((embeddingLevel+2) & ~(LEVEL_OVERRIDE | 1));
                else
                    /* least greater odd level */
                    newLevel = (byte)((NoOverride(embeddingLevel) + 1) | 1);
                if (newLevel <= MAX_EXPLICIT_LEVEL && overflowIsolateCount == 0 &&
                                                      overflowEmbeddingCount == 0) {
                    lastCcPos = i;
                    embeddingLevel = newLevel;
                    if (dirProp == LRO || dirProp == RLO)
                        embeddingLevel |= LEVEL_OVERRIDE;
                    stackLast++;
                    stack[stackLast] = embeddingLevel;
                    /* we don't need to set LEVEL_OVERRIDE off for LRE and RLE
                       since this has already been done for newLevel which is
                       the source for embeddingLevel.
                     */
                } else {
                    if (overflowIsolateCount == 0)
                        overflowEmbeddingCount++;
                }
                break;
            case PDF:
                /* (X7) */
                flags |= DirPropFlag(BN);
                levels[i] = previousLevel;
                /* handle all the overflow cases first */
                if (overflowIsolateCount > 0) {
                    break;
                }
                if (overflowEmbeddingCount > 0) {
                    overflowEmbeddingCount--;
                    break;
                }
                if (stackLast > 0 && stack[stackLast] < ISOLATE) {   /* not an isolate entry */
                    lastCcPos = i;
                    stackLast--;
                    embeddingLevel = (byte)stack[stackLast];
                }
                break;
            case LRI:
            case RLI:
                flags |= DirPropFlag(ON) | DirPropFlagLR(embeddingLevel);
                levels[i] = NoOverride(embeddingLevel);
                if (NoOverride(embeddingLevel) != NoOverride(previousLevel)) {
                    bracketProcessBoundary(bracketData, lastCcPos,
                                           previousLevel, embeddingLevel);
                    flags |= DirPropFlagMultiRuns;
                }
                previousLevel = embeddingLevel;
                /* (X5a, X5b) */
                if (dirProp == LRI)
                    /* least greater even level */
                    newLevel=(byte)((embeddingLevel+2)&~(LEVEL_OVERRIDE|1));
                else
                    /* least greater odd level */
                    newLevel=(byte)((NoOverride(embeddingLevel)+1)|1);
                if (newLevel <= MAX_EXPLICIT_LEVEL && overflowIsolateCount == 0
                                                   && overflowEmbeddingCount == 0) {
                    flags |= DirPropFlag(dirProp);
                    lastCcPos = i;
                    validIsolateCount++;
                    if (validIsolateCount > isolateCount)
                        isolateCount = validIsolateCount;
                    embeddingLevel = newLevel;
                    /* we can increment stackLast without checking because newLevel
                       will exceed UBIDI_MAX_EXPLICIT_LEVEL before stackLast overflows */
                    stackLast++;
                    stack[stackLast] = (short)(embeddingLevel + ISOLATE);
                    bracketProcessLRI_RLI(bracketData, embeddingLevel);
                } else {
                    /* make it WS so that it is handled by adjustWSLevels() */
                    dirProps[i] = WS;
                    overflowIsolateCount++;
                }
                break;
            case PDI:
                if (NoOverride(embeddingLevel) != NoOverride(previousLevel)) {
                    bracketProcessBoundary(bracketData, lastCcPos,
                                           previousLevel, embeddingLevel);
                    flags |= DirPropFlagMultiRuns;
                }
                /* (X6a) */
                if (overflowIsolateCount > 0) {
                    overflowIsolateCount--;
                    /* make it WS so that it is handled by adjustWSLevels() */
                    dirProps[i] = WS;
                }
                else if (validIsolateCount > 0) {
                    flags |= DirPropFlag(PDI);
                    lastCcPos = i;
                    overflowEmbeddingCount = 0;
                    while (stack[stackLast] < ISOLATE)  /* pop embedding entries */
                        stackLast--;                    /* until the last isolate entry */
                    stackLast--;                        /* pop also the last isolate entry */
                    validIsolateCount--;
                    bracketProcessPDI(bracketData);
                } else
                    /* make it WS so that it is handled by adjustWSLevels() */
                    dirProps[i] = WS;
                embeddingLevel = (byte)(stack[stackLast] & ~ISOLATE);
                flags |= DirPropFlag(ON) | DirPropFlagLR(embeddingLevel);
                previousLevel = embeddingLevel;
                levels[i] = NoOverride(embeddingLevel);
                break;
            case B:
                flags |= DirPropFlag(B);
                levels[i] = GetParaLevelAt(i);
                if ((i + 1) < length) {
                    if (text[i] == CR && text[i + 1] == LF)
                        break;          /* skip CR when followed by LF */
                    overflowEmbeddingCount = overflowIsolateCount = 0;
                    validIsolateCount = 0;
                    stackLast = 0;
                    previousLevel = embeddingLevel = GetParaLevelAt(i + 1);
                    stack[0] = embeddingLevel;   /* initialize base entry to para level, no override, no isolate */
                    bracketProcessB(bracketData, embeddingLevel);
                }
                break;
            case BN:
                /* BN, LRE, RLE, and PDF are supposed to be removed (X9) */
                /* they will get their levels set correctly in adjustWSLevels() */
                levels[i] = previousLevel;
                flags |= DirPropFlag(BN);
                break;
            default:
                /* all other types are normal characters and get the "real" level */
                if (NoOverride(embeddingLevel) != NoOverride(previousLevel)) {
                    bracketProcessBoundary(bracketData, lastCcPos,
                                           previousLevel, embeddingLevel);
                    flags |= DirPropFlagMultiRuns;
                    if ((embeddingLevel & LEVEL_OVERRIDE) != 0)
                        flags |= DirPropFlagO(embeddingLevel);
                    else
                        flags |= DirPropFlagE(embeddingLevel);
                }
                previousLevel = embeddingLevel;
                levels[i] = embeddingLevel;
                bracketProcessChar(bracketData, i);
                /* the dirProp may have been changed in bracketProcessChar() */
                flags |= DirPropFlag(dirProps[i]);
                break;
            }
        }
        if ((flags & MASK_EMBEDDING) != 0) {
            flags |= DirPropFlagLR(paraLevel);
        }
        if (orderParagraphsLTR && (flags & DirPropFlag(B)) != 0) {
            flags |= DirPropFlag(L);
        }
        /* again, determine if the text is mixed-directional or single-directional */
        dirct = directionFromFlags();

        return dirct;
    }
private byte resolveExplicitLevels ( ) { int i = 0 ; byte dirProp ; byte level = GetParaLevelAt ( 0 ) ; byte dirct ; isolateCount = 0 ; dirct = directionFromFlags ( ) ; if ( dirct != MIXED ) { return dirct ; } if ( reorderingMode > REORDER_LAST_LOGICAL_TO_VISUAL ) { int paraIndex , start , limit ; for ( paraIndex = 0 ; paraIndex < paraCount ; paraIndex ++ ) { if ( paraIndex == 0 ) start = 0 ; else start = paras_limit [ paraIndex - 1 ] ; limit = paras_limit [ paraIndex ] ; level = paras_level [ paraIndex ] ; for ( i = start ; i < limit ; i ++ ) levels [ i ] = level ; } return dirct ; } if ( ( flags & ( MASK_EXPLICIT | MASK_ISO ) ) == 0 ) { int paraIndex , start , limit ; BracketData bracketData = new BracketData ( ) ; bracketInit ( bracketData ) ; for ( paraIndex = 0 ; paraIndex < paraCount ; paraIndex ++ ) { if ( paraIndex == 0 ) start = 0 ; else start = paras_limit [ paraIndex - 1 ] ; limit = paras_limit [ paraIndex ] ; level = paras_level [ paraIndex ] ; for ( i = start ; i < limit ; i ++ ) { levels [ i ] = level ; dirProp = dirProps [ i ] ; if ( dirProp == BN ) continue ; if ( dirProp == B ) { if ( ( i + 1 ) < length ) { if ( text [ i ] == CR && text [ i + 1 ] == LF ) continue ; bracketProcessB ( bracketData , level ) ; } continue ; } bracketProcessChar ( bracketData , i ) ; } } return dirct ; } byte embeddingLevel = level , newLevel ; byte previousLevel = level ; int lastCcPos = 0 ; short [ ] stack = new short [ MAX_EXPLICIT_LEVEL + 2 ] ; int stackLast = 0 ; int overflowIsolateCount = 0 ; int overflowEmbeddingCount = 0 ; int validIsolateCount = 0 ; BracketData bracketData = new BracketData ( ) ; bracketInit ( bracketData ) ; stack [ 0 ] = level ; flags = 0 ; for ( i = 0 ; i < length ; i ++ ) { dirProp = dirProps [ i ] ; switch ( dirProp ) { case LRE : case RLE : case LRO : case RLO : flags |= DirPropFlag ( BN ) ; levels [ i ] = previousLevel ; if ( dirProp == LRE || dirProp == LRO ) newLevel = ( byte ) ( ( embeddingLevel + 2 ) & ~ ( LEVEL_OVERRIDE | 1 ) ) ; else newLevel = ( byte ) ( ( NoOverride ( embeddingLevel ) + 1 ) | 1 ) ; if ( newLevel <= MAX_EXPLICIT_LEVEL && overflowIsolateCount == 0 && overflowEmbeddingCount == 0 ) { lastCcPos = i ; embeddingLevel = newLevel ; if ( dirProp == LRO || dirProp == RLO ) embeddingLevel |= LEVEL_OVERRIDE ; stackLast ++ ; stack [ stackLast ] = embeddingLevel ; } else { if ( overflowIsolateCount == 0 ) overflowEmbeddingCount ++ ; } break ; case PDF : flags |= DirPropFlag ( BN ) ; levels [ i ] = previousLevel ; if ( overflowIsolateCount > 0 ) { break ; } if ( overflowEmbeddingCount > 0 ) { overflowEmbeddingCount -- ; break ; } if ( stackLast > 0 && stack [ stackLast ] < ISOLATE ) { lastCcPos = i ; stackLast -- ; embeddingLevel = ( byte ) stack [ stackLast ] ; } break ; case LRI : case RLI : flags |= DirPropFlag ( ON ) | DirPropFlagLR ( embeddingLevel ) ; levels [ i ] = NoOverride ( embeddingLevel ) ; if ( NoOverride ( embeddingLevel ) != NoOverride ( previousLevel ) ) { bracketProcessBoundary ( bracketData , lastCcPos , previousLevel , embeddingLevel ) ; flags |= DirPropFlagMultiRuns ; } previousLevel = embeddingLevel ; if ( dirProp == LRI ) newLevel = ( byte ) ( ( embeddingLevel + 2 ) & ~ ( LEVEL_OVERRIDE | 1 ) ) ; else newLevel = ( byte ) ( ( NoOverride ( embeddingLevel ) + 1 ) | 1 ) ; if ( newLevel <= MAX_EXPLICIT_LEVEL && overflowIsolateCount == 0 && overflowEmbeddingCount == 0 ) { flags |= DirPropFlag ( dirProp ) ; lastCcPos = i ; validIsolateCount ++ ; if ( validIsolateCount > isolateCount ) isolateCount = validIsolateCount ; embeddingLevel = newLevel ; stackLast ++ ; stack [ stackLast ] = ( short ) ( embeddingLevel + ISOLATE ) ; bracketProcessLRI_RLI ( bracketData , embeddingLevel ) ; } else { dirProps [ i ] = WS ; overflowIsolateCount ++ ; } break ; case PDI : if ( NoOverride ( embeddingLevel ) != NoOverride ( previousLevel ) ) { bracketProcessBoundary ( bracketData , lastCcPos , previousLevel , embeddingLevel ) ; flags |= DirPropFlagMultiRuns ; } if ( overflowIsolateCount > 0 ) { overflowIsolateCount -- ; dirProps [ i ] = WS ; } else if ( validIsolateCount > 0 ) { flags |= DirPropFlag ( PDI ) ; lastCcPos = i ; overflowEmbeddingCount = 0 ; while ( stack [ stackLast ] < ISOLATE ) stackLast -- ; stackLast -- ; validIsolateCount -- ; bracketProcessPDI ( bracketData ) ; } else dirProps [ i ] = WS ; embeddingLevel = ( byte ) ( stack [ stackLast ] & ~ ISOLATE ) ; flags |= DirPropFlag ( ON ) | DirPropFlagLR ( embeddingLevel ) ; previousLevel = embeddingLevel ; levels [ i ] = NoOverride ( embeddingLevel ) ; break ; case B : flags |= DirPropFlag ( B ) ; levels [ i ] = GetParaLevelAt ( i ) ; if ( ( i + 1 ) < length ) { if ( text [ i ] == CR && text [ i + 1 ] == LF ) break ; overflowEmbeddingCount = overflowIsolateCount = 0 ; validIsolateCount = 0 ; stackLast = 0 ; previousLevel = embeddingLevel = GetParaLevelAt ( i + 1 ) ; stack [ 0 ] = embeddingLevel ; bracketProcessB ( bracketData , embeddingLevel ) ; } break ; case BN : levels [ i ] = previousLevel ; flags |= DirPropFlag ( BN ) ; break ; default : if ( NoOverride ( embeddingLevel ) != NoOverride ( previousLevel ) ) { bracketProcessBoundary ( bracketData , lastCcPos , previousLevel , embeddingLevel ) ; flags |= DirPropFlagMultiRuns ; if ( ( embeddingLevel & LEVEL_OVERRIDE ) != 0 ) flags |= DirPropFlagO ( embeddingLevel ) ; else flags |= DirPropFlagE ( embeddingLevel ) ; } previousLevel = embeddingLevel ; levels [ i ] = embeddingLevel ; bracketProcessChar ( bracketData , i ) ; flags |= DirPropFlag ( dirProps [ i ] ) ; break ; } } if ( ( flags & MASK_EMBEDDING ) != 0 ) { flags |= DirPropFlagLR ( paraLevel ) ; } if ( orderParagraphsLTR && ( flags & DirPropFlag ( B ) ) != 0 ) { flags |= DirPropFlag ( L ) ; } dirct = directionFromFlags ( ) ; return dirct ; }
/*
Resolve the explicit levels as specified by explicit embedding codes.
Recalculate the flags to have them reflect the real properties
after taking the explicit embeddings into account.

The BiDi algorithm is designed to result in the same behavior whether embedding
levels are externally specified (from "styled text", supposedly the preferred
method) or set by explicit embedding codes (LRx, RLx, PDF, FSI, PDI) in the plain text.
That is why (X9) instructs to remove all not-isolate explicit codes (and BN).
However, in a real implementation, the removal of these codes and their index
positions in the plain text is undesirable since it would result in
reallocated, reindexed text.
Instead, this implementation leaves the codes in there and just ignores them
in the subsequent processing.
In order to get the same reordering behavior, positions with a BN or a not-isolate
explicit embedding code just get the same level assigned as the last "real"
character.

Some implementations, not this one, then overwrite some of these
directionality properties at "real" same-level-run boundaries by
L or R codes so that the resolution of weak types can be performed on the
entire paragraph at once instead of having to parse it once more and
perform that resolution on same-level-runs.
This limits the scope of the implicit rules in effectively
the same way as the run limits.

Instead, this implementation does not modify these codes, except for
paired brackets whose properties (ON) may be replaced by L or R.
On one hand, the paragraph has to be scanned for same-level-runs, but
on the other hand, this saves another loop to reset these codes,
or saves making and modifying a copy of dirProps[].


Note that (Pn) and (Xn) changed significantly from version 4 of the BiDi algorithm.


Handling the stack of explicit levels (Xn):

With the BiDi stack of explicit levels, as pushed with each
LRE, RLE, LRO, RLO, LRI, RLI and FSI and popped with each PDF and PDI,
the explicit level must never exceed MAX_EXPLICIT_LEVEL.

In order to have a correct push-pop semantics even in the case of overflows,
overflow counters and a valid isolate counter are used as described in UAX#9
section 3.3.2 "Explicit Levels and Directions".

This implementation assumes that MAX_EXPLICIT_LEVEL is odd.

Returns the direction