/// <summary> /// Is the letter at provided index a finishing letter? /// </summary> /// <returns><see langword="true" /> if the letter is a finishing letter</returns> private static bool IsFinishingLetter(FastStringBuilder letters, int index) { int currentIndexLetter = letters.Get(index); int previousIndexLetter = default; if (index != 0) { previousIndexLetter = letters.Get(index - 1); } bool isPreviousLetterConnectable = index != 0 && previousIndexLetter != ' ' && previousIndexLetter != (int)ArabicGeneralLetters.Dal && previousIndexLetter != (int)ArabicGeneralLetters.Thal && previousIndexLetter != (int)ArabicGeneralLetters.Ra2 && previousIndexLetter != (int)ArabicGeneralLetters.Zeen && previousIndexLetter != (int)ArabicGeneralLetters.PersianZe && previousIndexLetter != (int)ArabicGeneralLetters.Waw && previousIndexLetter != (int)ArabicGeneralLetters.Alef && previousIndexLetter != (int)ArabicGeneralLetters.AlefMad && previousIndexLetter != (int)ArabicGeneralLetters.AlefHamza && previousIndexLetter != (int)ArabicGeneralLetters.AlefMaksoor && previousIndexLetter != (int)ArabicGeneralLetters.WawHamza && previousIndexLetter != (int)ArabicGeneralLetters.Hamza && previousIndexLetter != (int)ArabicGeneralLetters.ZeroWidthNoJoiner && previousIndexLetter != (int)ArabicIsolatedLetters.Dal && previousIndexLetter != (int)ArabicIsolatedLetters.Thal && previousIndexLetter != (int)ArabicIsolatedLetters.Ra2 && previousIndexLetter != (int)ArabicIsolatedLetters.Zeen && previousIndexLetter != (int)ArabicIsolatedLetters.PersianZe && previousIndexLetter != (int)ArabicIsolatedLetters.Waw && previousIndexLetter != (int)ArabicIsolatedLetters.Alef && previousIndexLetter != (int)ArabicIsolatedLetters.AlefMad && previousIndexLetter != (int)ArabicIsolatedLetters.AlefHamza && previousIndexLetter != (int)ArabicIsolatedLetters.AlefMaksoor && previousIndexLetter != (int)ArabicIsolatedLetters.WawHamza && previousIndexLetter != (int)ArabicIsolatedLetters.Hamza && (previousIndexLetter < 0xFFFF && TextUtils.IsGlyphFixedArabicCharacter((char)previousIndexLetter)); bool canThisLetterBeFinishing = currentIndexLetter != ' ' && currentIndexLetter != (int)ArabicGeneralLetters.ZeroWidthNoJoiner && currentIndexLetter != (int)ArabicGeneralLetters.Hamza; return(isPreviousLetterConnectable && canThisLetterBeFinishing); }
/// <summary> /// Fixes the shape of letters based on their position. /// </summary> /// <param name="input"></param> /// <param name="output"></param> /// <param name="preserveNumbers"></param> /// <param name="farsi"></param> /// <returns></returns> public static void Fix(FastStringBuilder input, FastStringBuilder output, bool preserveNumbers, bool farsi, bool fixTextTags) { FixYah(input, farsi); output.SetValue(input); for (int i = 0; i < input.Length; i++) { bool skipNext = false; int iChar = input.Get(i); // For special Lam Letter connections. if (iChar == (int)ArabicGeneralLetters.Lam) { if (i < input.Length - 1) { skipNext = HandleSpecialLam(input, output, i); if (skipNext) { iChar = output.Get(i); } } } // We don't want to fix tatweel or zwnj character if (iChar == (int)ArabicGeneralLetters.ArabicTatweel || iChar == (int)ArabicGeneralLetters.ZeroWidthNoJoiner) { continue; } if (iChar < 0xFFFF && TextUtils.IsGlyphFixedArabicCharacter((char)iChar)) { char converted = GlyphTable.Convert((char)iChar); if (IsMiddleLetter(input, i)) { output.Set(i, (char)(converted + 3)); } else if (IsFinishingLetter(input, i)) { output.Set(i, (char)(converted + 1)); } else if (IsLeadingLetter(input, i)) { output.Set(i, (char)(converted + 2)); } } // If this letter as Lam and special Lam-Alef connection was made, We want to skip the Alef // (Lam-Alef occupies 1 space) if (skipNext) { i++; } } if (!preserveNumbers) { if (fixTextTags) { FixNumbersOutsideOfTags(output, farsi); } else { FixNumbers(output, farsi); } } }
/// <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); int previousIndexLetter = default; if (index != 0) { previousIndexLetter = letters.Get(index - 1); } int nextIndexLetter = default; if (index < letters.Length - 1) { nextIndexLetter = letters.Get(index + 1); } bool middleLetterCheck = index != 0 && currentIndexLetter != (int)ArabicGeneralLetters.Alef && currentIndexLetter != (int)ArabicGeneralLetters.Dal && currentIndexLetter != (int)ArabicGeneralLetters.Thal && currentIndexLetter != (int)ArabicGeneralLetters.Ra2 && currentIndexLetter != (int)ArabicGeneralLetters.Zeen && currentIndexLetter != (int)ArabicGeneralLetters.PersianZe && currentIndexLetter != (int)ArabicGeneralLetters.Waw && currentIndexLetter != (int)ArabicGeneralLetters.AlefMad && currentIndexLetter != (int)ArabicGeneralLetters.AlefHamza && currentIndexLetter != (int)ArabicGeneralLetters.AlefMaksoor && currentIndexLetter != (int)ArabicGeneralLetters.WawHamza && currentIndexLetter != (int)ArabicGeneralLetters.ZeroWidthNoJoiner && currentIndexLetter != (int)ArabicGeneralLetters.Hamza; bool previousLetterCheck = index != 0 && previousIndexLetter != (int)ArabicGeneralLetters.Alef && previousIndexLetter != (int)ArabicGeneralLetters.Dal && previousIndexLetter != (int)ArabicGeneralLetters.Thal && previousIndexLetter != (int)ArabicGeneralLetters.Ra2 && previousIndexLetter != (int)ArabicGeneralLetters.Zeen && previousIndexLetter != (int)ArabicGeneralLetters.PersianZe && previousIndexLetter != (int)ArabicGeneralLetters.Waw && previousIndexLetter != (int)ArabicGeneralLetters.AlefMad && previousIndexLetter != (int)ArabicGeneralLetters.AlefHamza && previousIndexLetter != (int)ArabicGeneralLetters.AlefMaksoor && previousIndexLetter != (int)ArabicGeneralLetters.WawHamza && previousIndexLetter != (int)ArabicGeneralLetters.Hamza && previousIndexLetter != (int)ArabicGeneralLetters.ZeroWidthNoJoiner && previousIndexLetter != (int)ArabicIsolatedLetters.Alef && previousIndexLetter != (int)ArabicIsolatedLetters.Dal && previousIndexLetter != (int)ArabicIsolatedLetters.Thal && previousIndexLetter != (int)ArabicIsolatedLetters.Ra2 && previousIndexLetter != (int)ArabicIsolatedLetters.Zeen && previousIndexLetter != (int)ArabicIsolatedLetters.PersianZe && previousIndexLetter != (int)ArabicIsolatedLetters.Waw && previousIndexLetter != (int)ArabicIsolatedLetters.AlefMad && previousIndexLetter != (int)ArabicIsolatedLetters.AlefHamza && previousIndexLetter != (int)ArabicIsolatedLetters.AlefMaksoor && previousIndexLetter != (int)ArabicIsolatedLetters.WawHamza && previousIndexLetter != (int)ArabicIsolatedLetters.Hamza && (previousIndexLetter < 0xFFFF && TextUtils.IsGlyphFixedArabicCharacter((char)previousIndexLetter)); bool nextLetterCheck = index < letters.Length - 1 && (nextIndexLetter < 0xFFFF && TextUtils.IsGlyphFixedArabicCharacter((char)nextIndexLetter)) && nextIndexLetter != (int)ArabicGeneralLetters.ZeroWidthNoJoiner && nextIndexLetter != (int)ArabicGeneralLetters.Hamza && nextIndexLetter != (int)ArabicIsolatedLetters.Hamza; return(nextLetterCheck && previousLetterCheck && middleLetterCheck); }
/// <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); int previousIndexLetter = default; if (index != 0) { previousIndexLetter = letters.Get(index - 1); } int nextIndexLetter = default; if (index < letters.Length - 1) { nextIndexLetter = letters.Get(index + 1); } bool isPreviousLetterNonConnectable = index == 0 || (previousIndexLetter < 0xFFFF && !TextUtils.IsGlyphFixedArabicCharacter((char)previousIndexLetter)) || previousIndexLetter == (int)ArabicGeneralLetters.Alef || previousIndexLetter == (int)ArabicGeneralLetters.Dal || previousIndexLetter == (int)ArabicGeneralLetters.Thal || previousIndexLetter == (int)ArabicGeneralLetters.Ra2 || previousIndexLetter == (int)ArabicGeneralLetters.Zeen || previousIndexLetter == (int)ArabicGeneralLetters.PersianZe || previousIndexLetter == (int)ArabicGeneralLetters.Waw || previousIndexLetter == (int)ArabicGeneralLetters.AlefMad || previousIndexLetter == (int)ArabicGeneralLetters.AlefHamza || previousIndexLetter == (int)ArabicGeneralLetters.Hamza || previousIndexLetter == (int)ArabicGeneralLetters.AlefMaksoor || previousIndexLetter == (int)ArabicGeneralLetters.ZeroWidthNoJoiner || previousIndexLetter == (int)ArabicGeneralLetters.WawHamza || previousIndexLetter == (int)ArabicIsolatedLetters.Alef || previousIndexLetter == (int)ArabicIsolatedLetters.Dal || previousIndexLetter == (int)ArabicIsolatedLetters.Thal || previousIndexLetter == (int)ArabicIsolatedLetters.Ra2 || previousIndexLetter == (int)ArabicIsolatedLetters.Zeen || previousIndexLetter == (int)ArabicIsolatedLetters.PersianZe || previousIndexLetter == (int)ArabicIsolatedLetters.Waw || previousIndexLetter == (int)ArabicIsolatedLetters.AlefMad || previousIndexLetter == (int)ArabicIsolatedLetters.AlefHamza || previousIndexLetter == (int)ArabicIsolatedLetters.Hamza || previousIndexLetter == (int)ArabicIsolatedLetters.AlefMaksoor; bool canThisLetterBeLeading = currentIndexLetter != ' ' && currentIndexLetter != (int)ArabicGeneralLetters.Dal && currentIndexLetter != (int)ArabicGeneralLetters.Thal && currentIndexLetter != (int)ArabicGeneralLetters.Ra2 && currentIndexLetter != (int)ArabicGeneralLetters.Zeen && currentIndexLetter != (int)ArabicGeneralLetters.PersianZe && currentIndexLetter != (int)ArabicGeneralLetters.Alef && currentIndexLetter != (int)ArabicGeneralLetters.AlefHamza && currentIndexLetter != (int)ArabicGeneralLetters.AlefMaksoor && currentIndexLetter != (int)ArabicGeneralLetters.AlefMad && currentIndexLetter != (int)ArabicGeneralLetters.WawHamza && currentIndexLetter != (int)ArabicGeneralLetters.Waw && currentIndexLetter != (int)ArabicGeneralLetters.ZeroWidthNoJoiner && currentIndexLetter != (int)ArabicGeneralLetters.Hamza; bool isNextLetterConnectable = index < letters.Length - 1 && (nextIndexLetter < 0xFFFF && TextUtils.IsGlyphFixedArabicCharacter((char)nextIndexLetter)) && nextIndexLetter != (int)ArabicGeneralLetters.Hamza && nextIndexLetter != (int)ArabicGeneralLetters.ZeroWidthNoJoiner; return(isPreviousLetterNonConnectable && canThisLetterBeLeading && isNextLetterConnectable); }