private void ProcessIsolatedRunSequence()

in src/Avalonia.Base/Media/TextFormatting/Unicode/BiDiAlgorithm.cs [856:1259]


        private void ProcessIsolatedRunSequence(BidiClass sos, BidiClass eos, int runLevel)
        {
            // Create mappings onto the underlying data
            var isolatedRunMapping = _isolatedRunMapping.AsSlice();
            _runResolvedClasses = new MappedArraySlice<BidiClass>(_workingClasses, isolatedRunMapping);
            _runOriginalClasses = new MappedArraySlice<BidiClass>(_originalClasses, isolatedRunMapping);
            _runLevels = new MappedArraySlice<sbyte>(_resolvedLevels, isolatedRunMapping);
            if (_hasBrackets)
            {
                _runBiDiPairedBracketTypes = new MappedArraySlice<BidiPairedBracketType>(_pairedBracketTypes, isolatedRunMapping);
                _runPairedBracketValues = new MappedArraySlice<int>(_pairedBracketValues, isolatedRunMapping);
            }

            _runLevel = runLevel;
            _runDirection = DirectionFromLevel(runLevel);
            _runLength = _runResolvedClasses.Length;

            // Rule W1
            // Also, set hasXX flags
            int i;
            var previousClass = sos;
            
            const uint isolateMask =
                (1U << (int)BidiClass.LeftToRightIsolate) |
                (1U << (int)BidiClass.RightToLeftIsolate) |
                (1U << (int)BidiClass.FirstStrongIsolate) |
                (1U << (int)BidiClass.PopDirectionalIsolate);

            const uint wRulesMask =
                (1U << (int)BidiClass.EuropeanNumber) |
                (1U << (int)BidiClass.ArabicLetter) |
                (1U << (int)BidiClass.EuropeanSeparator) |
                (1U << (int)BidiClass.CommonSeparator) |
                (1U << (int)BidiClass.ArabicNumber) |
                (1U << (int)BidiClass.EuropeanTerminator);

            uint wRules = 0;

            for (i = 0; i < _runLength; i++)
            {
                var resolvedClass = _runResolvedClasses[i];

                if (resolvedClass == BidiClass.NonspacingMark)
                {
                    _runResolvedClasses[i] = previousClass;
                }
                else
                {
                    var classBit = 1U << (int)resolvedClass;
                    if ((classBit & isolateMask) != 0U)
                    {
                        previousClass = BidiClass.OtherNeutral;
                    }
                    else
                    {
                        wRules |= classBit & wRulesMask;
                        previousClass = resolvedClass;
                    }
                }
            }

            // By tracking the types of characters known to be in the current run, we can
            // skip some of the rules that we know won't apply.
            var hasEN = (wRules & (1U << (int)BidiClass.EuropeanNumber)) != 0U;
            var hasAL = (wRules & (1U << (int)BidiClass.ArabicLetter)) != 0U;
            var hasES = (wRules & (1U << (int)BidiClass.EuropeanSeparator)) != 0U;
            var hasCS = (wRules & (1U << (int)BidiClass.CommonSeparator)) != 0U;
            var hasAN = (wRules & (1U << (int)BidiClass.ArabicNumber)) != 0U;
            var hasET = (wRules & (1U << (int)BidiClass.EuropeanTerminator)) != 0U;

            // Rule W2
            if (hasEN)
            {
                for (i = 0; i < _runLength; i++)
                {
                    if (_runResolvedClasses[i] != BidiClass.EuropeanNumber)
                    {
                        continue;
                    }

                    for (var j = i - 1; j >= 0; j--)
                    {
                        var resolvedClass = _runResolvedClasses[j];

                        switch (resolvedClass)
                        {
                            case BidiClass.LeftToRight:
                            case BidiClass.RightToLeft:
                            case BidiClass.ArabicLetter:
                            {
                                if (resolvedClass == BidiClass.ArabicLetter)
                                {
                                    _runResolvedClasses[i] = BidiClass.ArabicNumber;
                                    hasAN = true;
                                }

                                j = -1;
                                    
                                break;
                            }
                        }
                    }
                }
            }

            // Rule W3
            if (hasAL)
            {
                for (i = 0; i < _runLength; i++)
                {
                    if (_runResolvedClasses[i] == BidiClass.ArabicLetter)
                    {
                        _runResolvedClasses[i] = BidiClass.RightToLeft;
                    }
                }
            }

            // Rule W4
            if ((hasES || hasCS) && (hasEN || hasAN))
            {
                for (i = 1; i < _runLength - 1; ++i)
                {
                    ref var resolvedClass = ref _runResolvedClasses[i];
                    
                    if (resolvedClass == BidiClass.EuropeanSeparator)
                    {
                        var previousSeparatorClass = _runResolvedClasses[i - 1];
                        var nextSeparatorClass = _runResolvedClasses[i + 1];

                        if (previousSeparatorClass == BidiClass.EuropeanNumber && nextSeparatorClass == BidiClass.EuropeanNumber)
                        {
                            // ES between EN and EN
                            resolvedClass = BidiClass.EuropeanNumber;
                        }
                    }
                    else if (resolvedClass == BidiClass.CommonSeparator)
                    {
                        var previousSeparatorClass = _runResolvedClasses[i - 1];
                        var nextSeparatorClass = _runResolvedClasses[i + 1];

                        if ((previousSeparatorClass == BidiClass.ArabicNumber && nextSeparatorClass == BidiClass.ArabicNumber) ||
                             (previousSeparatorClass == BidiClass.EuropeanNumber && nextSeparatorClass == BidiClass.EuropeanNumber))
                        {
                            // CS between (AN and AN) or (EN and EN)
                            resolvedClass = previousSeparatorClass;
                        }
                    }
                }
            }

            // Rule W5
            if (hasET && hasEN)
            {
                for (i = 0; i < _runLength; ++i)
                {
                    if (_runResolvedClasses[i] != BidiClass.EuropeanTerminator)
                    {
                        continue;
                    }
                    
                    // Locate end of sequence
                    var sequenceStart = i;
                    var sequenceEnd = i;
                    
                    while (sequenceEnd < _runLength && _runResolvedClasses[sequenceEnd] == BidiClass.EuropeanTerminator)
                    {
                        sequenceEnd++;
                    }

                    // Preceded by, or followed by EN?
                    if ((sequenceStart == 0 ? sos : _runResolvedClasses[sequenceStart - 1]) == BidiClass.EuropeanNumber
                        || (sequenceEnd == _runLength ? eos : _runResolvedClasses[sequenceEnd]) == BidiClass.EuropeanNumber)
                    {
                        // Change the entire range
                        for (var j = sequenceStart; i < sequenceEnd; ++i)
                        {
                            _runResolvedClasses[i] = BidiClass.EuropeanNumber;
                        }
                    }

                    // continue at end of sequence
                    i = sequenceEnd;
                }
            }

            // Rule W6
            if (hasES || hasET || hasCS)
            {
                for (i = 0; i < _runLength; ++i)
                {
                    ref var resolvedClass = ref _runResolvedClasses[i];

                    switch (resolvedClass)
                    {
                        case BidiClass.EuropeanSeparator:
                        case BidiClass.EuropeanTerminator:
                        case BidiClass.CommonSeparator:
                        {
                            resolvedClass = BidiClass.OtherNeutral;
                            
                            break;
                        }
                    }
                }
            }

            // Rule W7.
            if (hasEN)
            {
                var previousStrongClass = sos;
                
                for (i = 0; i < _runLength; ++i)
                {
                    ref var resolvedClass = ref _runResolvedClasses[i];

                    switch (resolvedClass)
                    {
                        case BidiClass.EuropeanNumber:
                        {
                            // If prev strong type was an L change this to L too
                            if (previousStrongClass == BidiClass.LeftToRight)
                            {
                                _runResolvedClasses[i] = BidiClass.LeftToRight;
                            }
                            
                            break;
                        }
                       
                        case BidiClass.LeftToRight:
                        case BidiClass.RightToLeft:
                        {
                            // Remember previous strong type (NB: AL should already be changed to R)
                            previousStrongClass = resolvedClass;
                            break;
                        }
                    }
                }
            }

            // Rule N0 - process bracket pairs
            if (_hasBrackets)
            {
                int count;
                var pairedBrackets = LocatePairedBrackets();
                
                for (i = 0, count = pairedBrackets.Count; i < count; i++)
                {
                    var pairedBracket = pairedBrackets[i];
                    
                    var strongDirection = InspectPairedBracket(pairedBracket);

                    // Case "d" - no strong types in the brackets, ignore
                    if (strongDirection == BidiClass.OtherNeutral)
                    {
                        continue;
                    }

                    // Case "b" - strong type found that matches the embedding direction
                    if ((strongDirection == BidiClass.LeftToRight || strongDirection == BidiClass.RightToLeft) && strongDirection == _runDirection)
                    {
                        SetPairedBracketDirection(pairedBracket, strongDirection);
                        continue;
                    }

                    // Case "c" - found opposite strong type found, look before to establish context
                    strongDirection = InspectBeforePairedBracket(pairedBracket, sos);
                    
                    if (strongDirection == _runDirection || strongDirection == BidiClass.OtherNeutral)
                    {
                        strongDirection = _runDirection;
                    }

                    SetPairedBracketDirection(pairedBracket, strongDirection);
                }
            }

            // Rules N1 and N2 - resolve neutral types
            for (i = 0; i < _runLength; ++i)
            {
                var resolvedClass = _runResolvedClasses[i];
                
                if (IsNeutralClass(resolvedClass))
                {
                    // Locate end of sequence
                    var seqStart = i;
                    var seqEnd = i;
                    
                    while (seqEnd < _runLength && IsNeutralClass(_runResolvedClasses[seqEnd]))
                    {
                        seqEnd++;
                    }

                    // Work out the preceding class
                    BidiClass classBefore;
                    
                    if (seqStart == 0)
                    {
                        classBefore = sos;
                    }
                    else
                    {
                        classBefore = _runResolvedClasses[seqStart - 1];
                        
                        switch (classBefore)
                        {
                            case BidiClass.ArabicNumber:
                            case BidiClass.EuropeanNumber:
                            {
                                classBefore = BidiClass.RightToLeft;
                                
                                break;
                            }
                        }
                    }

                    // Work out the following class
                    BidiClass classAfter;
                    
                    if (seqEnd == _runLength)
                    {
                        classAfter = eos;
                    }
                    else
                    {
                        classAfter = _runResolvedClasses[seqEnd];

                        switch (classAfter)
                        {
                            case BidiClass.ArabicNumber:
                            case BidiClass.EuropeanNumber:
                            {
                                classAfter = BidiClass.RightToLeft;
                                
                                break;
                            }
                        }
                    }

                    // Work out the final resolved type
                    BidiClass finalResolveClass;
                    
                    if (classBefore == classAfter)
                    {
                        // Rule N1
                        finalResolveClass = classBefore;
                    }
                    else
                    {
                        // Rule N2
                        finalResolveClass = _runDirection;
                    }

                    // Apply changes
                    for (var j = seqStart; j < seqEnd; j++)
                    {
                        _runResolvedClasses[j] = finalResolveClass;
                    }

                    // continue after this run
                    i = seqEnd;
                }
            }

            // Rules I1 and I2 - resolve implicit types
            if ((_runLevel & 0x01) == 0)
            {
                // Rule I1 - even
                for (i = 0; i < _runLength; i++)
                {
                    var resolvedClass = _runResolvedClasses[i];
                    ref var currentRunLevel = ref _runLevels[i];

                    switch (resolvedClass)
                    {
                        case BidiClass.RightToLeft:
                        {
                            currentRunLevel++;
                            break;
                        }
                        case BidiClass.ArabicNumber:
                        case BidiClass.EuropeanNumber:
                        {
                            currentRunLevel += 2;
                            
                            break;
                        }
                    }
                }
            }
            else
            {
                // Rule I2 - odd
                for (i = 0; i < _runLength; i++)
                {
                    var resolvedClass = _runResolvedClasses[i];
                    ref var currentRunLevel = ref _runLevels[i];
                    
                    if (resolvedClass != BidiClass.RightToLeft)
                    {
                        currentRunLevel++;
                    }
                }
            }
        }