示例#1
0
文件: NBidi.cs 项目: esx2ve/NativeRTL
        // 3.3.1.P1 - Split the text into separate paragraphs.
        // A paragraph separator is kept with the previous paragraph.
        // Within each paragraph, apply all the other rules of this algorithm.
        public static Paragraph[] SplitStringToParagraphs(string logicalString)
        {
            ArrayList     ret = new ArrayList();
            int           i;
            StringBuilder sb = new StringBuilder();

            for (i = 0; i < logicalString.Length; ++i)
            {
                char c = logicalString[i];
                BidiCharacterType cType = UnicodeCharacterDataResolver.GetBidiCharacterType(c);
                if (cType == BidiCharacterType.B)
                {
                    Paragraph p = new Paragraph(sb.ToString());
                    p.ParagraphSeparator = c;
                    ret.Add(p);
                    sb.Length = 0;
                }
                else
                {
                    sb.Append(c);
                }
            }
            if (sb.Length > 0) // string ended without a paragraph separator
            {
                ret.Add(new Paragraph(sb.ToString()));
            }
            return((Paragraph[])ret.ToArray(typeof(Paragraph)));
        }
示例#2
0
文件: NBidi.cs 项目: esx2ve/NativeRTL
            private StringBuilder InternalDecompose(ArrayList char_lengths)
            {
                StringBuilder target = new StringBuilder();
                StringBuilder buffer = new StringBuilder();

                _hasArabic = false;
                _hasNSMs   = false;

                for (int i = 0; i < _text.Length; ++i)
                {
                    BidiCharacterType ct = UnicodeCharacterDataResolver.GetBidiCharacterType(_text[i]);
                    _hasArabic |= ((ct == BidiCharacterType.AL) || (ct == BidiCharacterType.AN));
                    _hasNSMs   |= (ct == BidiCharacterType.NSM);

                    buffer.Length = 0;
                    GetRecursiveDecomposition(false, _text[i], buffer);
                    char_lengths.Add(1 - buffer.Length);
                    // add all of the characters in the decomposition.
                    // (may be just the original character, if there was
                    // no decomposition mapping)

                    char ch;
                    for (int j = 0; j < buffer.Length; ++j)
                    {
                        ch = buffer[j];
                        UnicodeCanonicalClass chClass = UnicodeCharacterDataResolver.GetUnicodeCanonicalClass(ch);
                        int k = target.Length; // insertion point
                        if (chClass != UnicodeCanonicalClass.NR)
                        {
                            // bubble-sort combining marks as necessary
                            char ch2;
                            for (; k > 0; --k)
                            {
                                ch2 = target[k - 1];
                                if (UnicodeCharacterDataResolver.GetUnicodeCanonicalClass(ch2) <= chClass)
                                {
                                    break;
                                }
                            }
                        }
                        target.Insert(k, ch);
                    }
                }
                return(target);
            }
示例#3
0
文件: NBidi.cs 项目: esx2ve/NativeRTL
            // 3.3.1 The Paragraph Level
            // P2 - In each paragraph, find the first character of type L, AL, or R.
            // P3 - If a character is found in P2 and it is of type AL or R, then
            // set the paragraph embedding level to one; otherwise, set it to zero.
            public void RecalculateParagraphEmbeddingLevel()
            {
                embedding_level = 1;

                foreach (char c in _text)
                {
                    BidiCharacterType cType = UnicodeCharacterDataResolver.GetBidiCharacterType(c);
                    if (cType == BidiCharacterType.R || cType == BidiCharacterType.AL)
                    {
                        embedding_level = 1;
                        break;
                    }
                    else if (cType == BidiCharacterType.L)
                    {
                        break;
                    }
                }
            }
示例#4
0
文件: NBidi.cs 项目: esx2ve/NativeRTL
            // 3.3.2 Explicit Levels and Directions
            public void RecalculateCharactersEmbeddingLevels()
            {
                // This method is implemented in such a way it handles the string in logical order,
                // rather than visual order, so it is easier to handle complex layouts. That is why
                // it is placed BEFORE ReorderString rather than AFTER it, as its number suggests.
                if (_hasArabic)
                {
                    _text = PerformArabicShaping(_text);
                }

                _text_data = new CharData[_text.Length];

                #region rules X1 - X9
                // X1
                byte embeddingLevel           = EmbeddingLevel;
                DirectionalOverrideStatus dos = DirectionalOverrideStatus.Neutral;
                Stack dosStack = new Stack();
                Stack elStack  = new Stack();
                int   idx      = 0;
                for (int i = 0; i < _text.Length; ++i)
                {
                    bool x9Char = false;
                    char c      = _text[i];
                    _text_data[i]._ct   = UnicodeCharacterDataResolver.GetBidiCharacterType(c);
                    _text_data[i]._char = c;
                    _text_data[i]._idx  = idx;
                    idx += _char_lengths[i];

                    #region rules X2 - X5
                    // X2. With each RLE, compute the least greater odd embedding level.
                    // X4. With each RLO, compute the least greater odd embedding level.
                    if (c == BidiChars.RLE || c == BidiChars.RLO)
                    {
                        x9Char = true;
                        if (embeddingLevel < 60)
                        {
                            elStack.Push(embeddingLevel);
                            dosStack.Push(dos);

                            ++embeddingLevel;
                            embeddingLevel |= 1;

                            if (c == BidiChars.RLE)
                            {
                                dos = DirectionalOverrideStatus.Neutral;
                            }
                            else
                            {
                                dos = DirectionalOverrideStatus.RTL;
                            }
                        }
                    }
                    // X3. With each LRE, compute the least greater even embedding level.
                    // X5. With each LRO, compute the least greater even embedding level.
                    else if (c == BidiChars.LRE || c == BidiChars.LRO)
                    {
                        x9Char = true;
                        if (embeddingLevel < 59)
                        {
                            elStack.Push(embeddingLevel);
                            dosStack.Push(dos);

                            embeddingLevel |= 1;
                            ++embeddingLevel;

                            if (c == BidiChars.LRE)
                            {
                                dos = DirectionalOverrideStatus.Neutral;
                            }
                            else
                            {
                                dos = DirectionalOverrideStatus.LTR;
                            }
                        }
                    }
                    #endregion

                    #region rule X6
                    // X6. For all types besides RLE, LRE, RLO, LRO, and PDF: (...)
                    else if (c != BidiChars.PDF)
                    {
                        // a. Set the level of the current character to the current embedding level.
                        _text_data[i]._el = embeddingLevel;

                        //b. Whenever the directional override status is not neutral,
                        //reset the current character type to the directional override status.
                        if (dos == DirectionalOverrideStatus.LTR)
                        {
                            _text_data[i]._ct = BidiCharacterType.L;
                        }
                        else if (dos == DirectionalOverrideStatus.RTL)
                        {
                            _text_data[i]._ct = BidiCharacterType.R;
                        }
                    }
                    #endregion

                    #region rule X7
                    //Terminating Embeddings and Overrides
                    // X7. With each PDF, determine the matching embedding or override code.
                    // If there was a valid matching code, restore (pop) the last remembered (pushed)
                    // embedding level and directional override.
                    else if (c == BidiChars.PDF)
                    {
                        x9Char = true;
                        if (elStack.Count > 0)
                        {
                            embeddingLevel = (byte)(elStack.Pop());
                            dos            = (DirectionalOverrideStatus)(dosStack.Pop());
                        }
                    }
                    #endregion

                    // X8. All explicit directional embeddings and overrides are completely
                    // terminated at the end of each paragraph. Paragraph separators are not
                    // included in the embedding.

                    if (x9Char || _text_data[i]._ct == BidiCharacterType.BN)
                    {
                        _text_data[i]._el = embeddingLevel;
                    }
                }
                #endregion

                // X10. The remaining rules are applied to each run of characters at the same level.
                int prevLevel = EmbeddingLevel;
                int start     = 0;
                while (start < _text.Length)
                {
                    #region rule X10 - run level setup
                    byte level            = _text_data[start]._el;
                    BidiCharacterType sor = TypeForLevel(Math.Max(prevLevel, level));

                    int limit = start + 1;
                    while (limit < _text.Length && _text_data[limit]._el == level)
                    {
                        ++limit;
                    }

                    byte nextLevel        = limit < _text.Length ? _text_data[limit]._el : EmbeddingLevel;
                    BidiCharacterType eor = TypeForLevel(Math.Max(nextLevel, level));
                    #endregion

                    ResolveWeakTypes(start, limit, sor, eor);
                    ResolveNeutralTypes(start, limit, sor, eor, level);
                    ResolveImplicitTypes(start, limit, level);

                    prevLevel = level;
                    start     = limit;
                }

                // Wrap lines
                ReorderString(0, _text.Length);

                FixMirroredCharacters();

                ArrayList indexes = new ArrayList();
                ArrayList lengths = new ArrayList();

                StringBuilder sb = new StringBuilder();
                foreach (CharData cd in _text_data)
                {
                    sb.Append(cd._char);
                    indexes.Add(cd._idx);
                    lengths.Add(1);
                }

                _bidi_text    = sb.ToString();
                _bidi_indexes = (int[])indexes.ToArray(typeof(int));
            }