/// <summary> /// Is the letter at provided index a leading letter? /// </summary> /// <returns><see langword="true" /> if the letter is a leading letter</returns> private static bool IsLeadingLetter(FastStringBuilder letters, int index) { var currentIndexLetter = letters.Get(index); char previousIndexLetter = default; if (index != 0) previousIndexLetter = letters.Get(index - 1); char nextIndexLetter = default; if (index < letters.Length - 1) nextIndexLetter = letters.Get(index + 1); bool isPreviousLetterNonConnectable = index == 0 || !TextUtils.IsRTLCharacter(previousIndexLetter) || previousIndexLetter == (int)GeneralLetters.Alef || previousIndexLetter == (int)GeneralLetters.Dal || previousIndexLetter == (int)GeneralLetters.Thal || previousIndexLetter == (int)GeneralLetters.Ra2 || previousIndexLetter == (int)GeneralLetters.Zeen || previousIndexLetter == (int)GeneralLetters.PersianZe || previousIndexLetter == (int)GeneralLetters.Waw || previousIndexLetter == (int)GeneralLetters.AlefMad || previousIndexLetter == (int)GeneralLetters.AlefHamza || previousIndexLetter == (int)GeneralLetters.Hamza || previousIndexLetter == (int)GeneralLetters.AlefMaksoor || previousIndexLetter == (int)GeneralLetters.ZeroWidthNoJoiner || previousIndexLetter == (int)GeneralLetters.WawHamza || previousIndexLetter == (int)IsolatedLetters.Alef || previousIndexLetter == (int)IsolatedLetters.Dal || previousIndexLetter == (int)IsolatedLetters.Thal || previousIndexLetter == (int)IsolatedLetters.Ra2 || previousIndexLetter == (int)IsolatedLetters.Zeen || previousIndexLetter == (int)IsolatedLetters.PersianZe || previousIndexLetter == (int)IsolatedLetters.Waw || previousIndexLetter == (int)IsolatedLetters.AlefMad || previousIndexLetter == (int)IsolatedLetters.AlefHamza || previousIndexLetter == (int)IsolatedLetters.Hamza || previousIndexLetter == (int)IsolatedLetters.AlefMaksoor; bool canThisLetterBeLeading = currentIndexLetter != ' ' && currentIndexLetter != (int)GeneralLetters.Dal && currentIndexLetter != (int)GeneralLetters.Thal && currentIndexLetter != (int)GeneralLetters.Ra2 && currentIndexLetter != (int)GeneralLetters.Zeen && currentIndexLetter != (int)GeneralLetters.PersianZe && currentIndexLetter != (int)GeneralLetters.Alef && currentIndexLetter != (int)GeneralLetters.AlefHamza && currentIndexLetter != (int)GeneralLetters.AlefMaksoor && currentIndexLetter != (int)GeneralLetters.AlefMad && currentIndexLetter != (int)GeneralLetters.WawHamza && currentIndexLetter != (int)GeneralLetters.Waw && currentIndexLetter != (int)GeneralLetters.ZeroWidthNoJoiner && currentIndexLetter != (int)GeneralLetters.Hamza; bool isNextLetterConnectable = index < letters.Length - 1 && TextUtils.IsRTLCharacter(nextIndexLetter) && nextIndexLetter != (int)GeneralLetters.Hamza && nextIndexLetter != (int)GeneralLetters.ZeroWidthNoJoiner; return isPreviousLetterNonConnectable && canThisLetterBeLeading && isNextLetterConnectable; }
/// <summary> /// Is the letter at provided index a middle letter? /// </summary> /// <returns><see langword="true" /> if the letter is a middle letter</returns> private static bool IsMiddleLetter(FastStringBuilder letters, int index) { var currentIndexLetter = letters.Get(index); char previousIndexLetter = default; if (index != 0) previousIndexLetter = letters.Get(index - 1); char nextIndexLetter = default; if (index < letters.Length - 1) nextIndexLetter = letters.Get(index + 1); bool middleLetterCheck = index != 0 && currentIndexLetter != (int)GeneralLetters.Alef && currentIndexLetter != (int)GeneralLetters.Dal && currentIndexLetter != (int)GeneralLetters.Thal && currentIndexLetter != (int)GeneralLetters.Ra2 && currentIndexLetter != (int)GeneralLetters.Zeen && currentIndexLetter != (int)GeneralLetters.PersianZe && currentIndexLetter != (int)GeneralLetters.Waw && currentIndexLetter != (int)GeneralLetters.AlefMad && currentIndexLetter != (int)GeneralLetters.AlefHamza && currentIndexLetter != (int)GeneralLetters.AlefMaksoor && currentIndexLetter != (int)GeneralLetters.WawHamza && currentIndexLetter != (int)GeneralLetters.ZeroWidthNoJoiner && currentIndexLetter != (int)GeneralLetters.Hamza; bool previousLetterCheck = index != 0 && previousIndexLetter != (int)GeneralLetters.Alef && previousIndexLetter != (int)GeneralLetters.Dal && previousIndexLetter != (int)GeneralLetters.Thal && previousIndexLetter != (int)GeneralLetters.Ra2 && previousIndexLetter != (int)GeneralLetters.Zeen && previousIndexLetter != (int)GeneralLetters.PersianZe && previousIndexLetter != (int)GeneralLetters.Waw && previousIndexLetter != (int)GeneralLetters.AlefMad && previousIndexLetter != (int)GeneralLetters.AlefHamza && previousIndexLetter != (int)GeneralLetters.AlefMaksoor && previousIndexLetter != (int)GeneralLetters.WawHamza && previousIndexLetter != (int)GeneralLetters.Hamza && previousIndexLetter != (int)GeneralLetters.ZeroWidthNoJoiner && previousIndexLetter != (int)IsolatedLetters.Alef && previousIndexLetter != (int)IsolatedLetters.Dal && previousIndexLetter != (int)IsolatedLetters.Thal && previousIndexLetter != (int)IsolatedLetters.Ra2 && previousIndexLetter != (int)IsolatedLetters.Zeen && previousIndexLetter != (int)IsolatedLetters.PersianZe && previousIndexLetter != (int)IsolatedLetters.Waw && previousIndexLetter != (int)IsolatedLetters.AlefMad && previousIndexLetter != (int)IsolatedLetters.AlefHamza && previousIndexLetter != (int)IsolatedLetters.AlefMaksoor && previousIndexLetter != (int)IsolatedLetters.WawHamza && previousIndexLetter != (int)IsolatedLetters.Hamza && TextUtils.IsRTLCharacter(previousIndexLetter); bool nextLetterCheck = index < letters.Length - 1 && TextUtils.IsRTLCharacter(nextIndexLetter) && nextIndexLetter != (int)GeneralLetters.ZeroWidthNoJoiner && nextIndexLetter != (int)GeneralLetters.Hamza && nextIndexLetter != (int)IsolatedLetters.Hamza; return nextLetterCheck && previousLetterCheck && middleLetterCheck; }
public static void FindTag( FastStringBuilder str, int start, out Tag tag) { for (int i = start; i < str.Length;) { if (str.Get(i) != '<') { i++; continue; } bool calculateHashCode = true; tag.HashCode = 0; for (int j = i + 1; j < str.Length; j++) { int jChar = str.Get(j); if (calculateHashCode) { if (Char32Utils.IsLetter(jChar)) { unchecked { if (tag.HashCode == 0) { tag.HashCode = jChar.GetHashCode(); } else { tag.HashCode = (tag.HashCode * 397) ^ jChar.GetHashCode(); } } } else if (tag.HashCode != 0) { // We have computed the hash code. Now we reached a non letter character. We need to stop calculateHashCode = false; } } // Rich text tag cannot contain < or start with space if ((j == i + 1 && jChar == ' ') || jChar == '<') { break; } if (jChar == '>') { // Check if the tag is closing, opening or self contained tag.Start = i; tag.End = j; if (str.Get(j - 1) == '/') { // This is self contained. tag.Type = TagType.SelfContained; } else if (str.Get(i + 1) == '/') { // This is closing tag.Type = TagType.Closing; } else { tag.Type = TagType.Opening; } return; } } i++; } tag.Start = 0; tag.End = 0; tag.Type = TagType.None; tag.HashCode = 0; }