From 08d03071ab47f521e09c57cadba926556354ccb3 Mon Sep 17 00:00:00 2001 From: Mohamad Narimani Date: Sat, 30 Mar 2019 18:51:28 +0430 Subject: [PATCH] Fixed Shadda with other Tashkeel is not distinguishable Fixes : https://github.com/sorencoder/RTLTMPro/issues/13 --- Fonts/segoeui Numbers SDF.asset.meta | 2 +- Fonts/segoeui RTL Fixed SDF.mat.meta | 2 +- Fonts/segoeui RTL Glow SDF.mat.meta | 2 +- Fonts/segoeui RTL Outline SDF.mat.meta | 2 +- Fonts/segoeui RTL SDF.asset.meta | 2 +- Fonts/segoeui Tashkil SDF.asset.meta | 2 +- Fonts/segoeui.ttf.meta | 5 +- Ranges/TashkilRanges.txt | 2 +- Scripts/Runtime/RTLSupport.cs | 199 ++++++++++++++++++------- Scripts/Runtime/TashkeelCharacters.cs | 7 +- 10 files changed, 164 insertions(+), 61 deletions(-) diff --git a/Fonts/segoeui Numbers SDF.asset.meta b/Fonts/segoeui Numbers SDF.asset.meta index c7faafe..0e4abdb 100644 --- a/Fonts/segoeui Numbers SDF.asset.meta +++ b/Fonts/segoeui Numbers SDF.asset.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 4c5facc5e4f8a7f42b953ed125ff7d3d +guid: 1354aae31ce557349b4771ff95ba4229 NativeFormatImporter: externalObjects: {} mainObjectFileID: 11400000 diff --git a/Fonts/segoeui RTL Fixed SDF.mat.meta b/Fonts/segoeui RTL Fixed SDF.mat.meta index 8153687..ff33860 100644 --- a/Fonts/segoeui RTL Fixed SDF.mat.meta +++ b/Fonts/segoeui RTL Fixed SDF.mat.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 4d8cb3022c3efad4cb897b20c30d3093 +guid: 2ad9dc42ce37cf146a6bf8b81466c07d NativeFormatImporter: externalObjects: {} mainObjectFileID: 2100000 diff --git a/Fonts/segoeui RTL Glow SDF.mat.meta b/Fonts/segoeui RTL Glow SDF.mat.meta index 64e3cbd..7e5f0aa 100644 --- a/Fonts/segoeui RTL Glow SDF.mat.meta +++ b/Fonts/segoeui RTL Glow SDF.mat.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: c4d3ac12902d6f24a8c9ebf76f9ea768 +guid: 7181607f14929704e93fcd48974aa43f NativeFormatImporter: externalObjects: {} mainObjectFileID: 2100000 diff --git a/Fonts/segoeui RTL Outline SDF.mat.meta b/Fonts/segoeui RTL Outline SDF.mat.meta index 6a44852..b86467b 100644 --- a/Fonts/segoeui RTL Outline SDF.mat.meta +++ b/Fonts/segoeui RTL Outline SDF.mat.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: c512ea5c56d8f8746af62abb78fcd712 +guid: da6bbd594edeed544b4cf89d55f9b763 NativeFormatImporter: externalObjects: {} mainObjectFileID: 2100000 diff --git a/Fonts/segoeui RTL SDF.asset.meta b/Fonts/segoeui RTL SDF.asset.meta index 665dab0..8c71d87 100644 --- a/Fonts/segoeui RTL SDF.asset.meta +++ b/Fonts/segoeui RTL SDF.asset.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 3fbde2e562e333d488bc46986fc6f4f1 +guid: c55c953cec19afc46ac4d6029039c0b8 NativeFormatImporter: externalObjects: {} mainObjectFileID: 11400000 diff --git a/Fonts/segoeui Tashkil SDF.asset.meta b/Fonts/segoeui Tashkil SDF.asset.meta index 2925f52..1926143 100644 --- a/Fonts/segoeui Tashkil SDF.asset.meta +++ b/Fonts/segoeui Tashkil SDF.asset.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 2b55873cf640142479f769f70844b03a +guid: fdb9f6b25fc3d524cae65ac1a50078a4 NativeFormatImporter: externalObjects: {} mainObjectFileID: 11400000 diff --git a/Fonts/segoeui.ttf.meta b/Fonts/segoeui.ttf.meta index 8a83399..44a59f3 100644 --- a/Fonts/segoeui.ttf.meta +++ b/Fonts/segoeui.ttf.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 249445261b6c401438d2bf6d7c207747 +guid: a712010c123dc514e906d45103b3aef9 TrueTypeFontImporter: externalObjects: {} serializedVersion: 4 @@ -11,7 +11,8 @@ TrueTypeFontImporter: fontName: Segoe UI fontNames: - Segoe UI - fallbackFontReferences: [] + fallbackFontReferences: + - {fileID: 12800000, guid: 249445261b6c401438d2bf6d7c207747, type: 3} customCharacters: fontRenderingMode: 0 ascentCalculationMode: 1 diff --git a/Ranges/TashkilRanges.txt b/Ranges/TashkilRanges.txt index 560f86b..231e7cd 100644 --- a/Ranges/TashkilRanges.txt +++ b/Ranges/TashkilRanges.txt @@ -1 +1 @@ -00064b-00065f,000670 \ No newline at end of file +00064b-00065f,000670,00FC5E-00FC63 \ No newline at end of file diff --git a/Scripts/Runtime/RTLSupport.cs b/Scripts/Runtime/RTLSupport.cs index d83f354..2daa064 100644 --- a/Scripts/Runtime/RTLSupport.cs +++ b/Scripts/Runtime/RTLSupport.cs @@ -24,6 +24,24 @@ public class RTLSupport protected readonly Regex PairedTagFixer; protected readonly Regex LoneTagFixer; protected readonly StringBuilder FinalLetters; + + protected readonly string ShaddaDammatan = new string( + new[] { (char) TashkeelCharacters.Shadda, (char) TashkeelCharacters.Dammatan }); + + protected readonly string ShaddaKasratan = new string( + new[] { (char) TashkeelCharacters.Shadda, (char) TashkeelCharacters.Kasratan }); + + protected readonly string ShaddaSuperscriptAlef = new string( + new[] { (char) TashkeelCharacters.Shadda, (char) TashkeelCharacters.SuperscriptAlef }); + + protected readonly string ShaddaFatha = new string( + new[] { (char) TashkeelCharacters.Shadda, (char) TashkeelCharacters.Fatha }); + + protected readonly string ShaddaDamma = new string( + new[] { (char) TashkeelCharacters.Shadda, (char) TashkeelCharacters.Damma }); + + protected readonly string ShaddaKasra = new string( + new[] { (char) TashkeelCharacters.Shadda, (char) TashkeelCharacters.Kasra }); public RTLSupport() { @@ -81,19 +99,23 @@ public virtual bool IsRTLCharacter(char ch) if (ch >= (char) IsolatedLetters.Alef && ch <= (char) IsolatedLetters.Alef + 3) return true; - if (ch >= (char) IsolatedLetters.AlefHamza && ch <= (char) IsolatedLetters.AlefHamza + 3) + if (ch >= (char) IsolatedLetters.AlefHamza && + ch <= (char) IsolatedLetters.AlefHamza + 3) return true; if (ch >= (char) IsolatedLetters.WawHamza && ch <= (char) IsolatedLetters.WawHamza + 3) return true; - if (ch >= (char) IsolatedLetters.AlefMaksoor && ch <= (char) IsolatedLetters.AlefMaksoor + 3) + if (ch >= (char) IsolatedLetters.AlefMaksoor && + ch <= (char) IsolatedLetters.AlefMaksoor + 3) return true; - if (ch >= (char) IsolatedLetters.AlefMaksora && ch <= (char) IsolatedLetters.AlefMaksora + 3) + if (ch >= (char) IsolatedLetters.AlefMaksora && + ch <= (char) IsolatedLetters.AlefMaksora + 3) return true; - if (ch >= (char) IsolatedLetters.HamzaNabera && ch <= (char) IsolatedLetters.HamzaNabera + 3) + if (ch >= (char) IsolatedLetters.HamzaNabera && + ch <= (char) IsolatedLetters.HamzaNabera + 3) return true; if (ch >= (char) IsolatedLetters.Ba && ch <= (char) IsolatedLetters.Ba + 3) @@ -180,22 +202,28 @@ public virtual bool IsRTLCharacter(char ch) if (ch >= (char) IsolatedLetters.AlefMad && ch <= (char) IsolatedLetters.AlefMad + 3) return true; - if (ch >= (char) IsolatedLetters.TaMarboota && ch <= (char) IsolatedLetters.TaMarboota + 3) + if (ch >= (char) IsolatedLetters.TaMarboota && + ch <= (char) IsolatedLetters.TaMarboota + 3) return true; - if (ch >= (char) IsolatedLetters.PersianPe && ch <= (char) IsolatedLetters.PersianPe + 3) + if (ch >= (char) IsolatedLetters.PersianPe && + ch <= (char) IsolatedLetters.PersianPe + 3) return true; - if (ch >= (char) IsolatedLetters.PersianChe && ch <= (char) IsolatedLetters.PersianChe + 3) + if (ch >= (char) IsolatedLetters.PersianChe && + ch <= (char) IsolatedLetters.PersianChe + 3) return true; - if (ch >= (char) IsolatedLetters.PersianZe && ch <= (char) IsolatedLetters.PersianZe + 3) + if (ch >= (char) IsolatedLetters.PersianZe && + ch <= (char) IsolatedLetters.PersianZe + 3) return true; - if (ch >= (char) IsolatedLetters.PersianGaf && ch <= (char) IsolatedLetters.PersianGaf + 3) + if (ch >= (char) IsolatedLetters.PersianGaf && + ch <= (char) IsolatedLetters.PersianGaf + 3) return true; - if (ch >= (char) IsolatedLetters.PersianGaf2 && ch <= (char) IsolatedLetters.PersianGaf2 + 3) + if (ch >= (char) IsolatedLetters.PersianGaf2 && + ch <= (char) IsolatedLetters.PersianGaf2 + 3) return true; // Special Lam Alef @@ -415,10 +443,12 @@ protected virtual string RemoveTashkeel(string str) TashkeelLocations.Add(new TashkeelLocation(TashkeelCharacters.Sukun, i)); break; case TashkeelCharacters.MaddahAbove: - TashkeelLocations.Add(new TashkeelLocation(TashkeelCharacters.MaddahAbove, i)); + TashkeelLocations.Add( + new TashkeelLocation(TashkeelCharacters.MaddahAbove, i)); break; case TashkeelCharacters.SuperscriptAlef: - TashkeelLocations.Add(new TashkeelLocation(TashkeelCharacters.SuperscriptAlef, i)); + TashkeelLocations.Add( + new TashkeelLocation(TashkeelCharacters.SuperscriptAlef, i)); break; } } @@ -770,7 +800,8 @@ protected virtual void FixLigature(IList shapeFixedLetters) bool isAfterEnglishChar = char.IsLower(shapeFixedLetters[i + 1]) || char.IsUpper(shapeFixedLetters[i + 1]); bool isBeforeEnglishChar = - char.IsLower(shapeFixedLetters[i - 1]) || char.IsUpper(shapeFixedLetters[i - 1]); + char.IsLower(shapeFixedLetters[i - 1]) || + char.IsUpper(shapeFixedLetters[i - 1]); bool isAfterNumber = char.IsNumber(shapeFixedLetters[i + 1]); bool isBeforeNumber = char.IsNumber(shapeFixedLetters[i - 1]); bool isAfterSymbol = char.IsSymbol(shapeFixedLetters[i + 1]); @@ -795,7 +826,8 @@ protected virtual void FixLigature(IList shapeFixedLetters) continue; } - if (shapeFixedLetters[i] >= (char) 0xD800 && shapeFixedLetters[i] <= (char) 0xDBFF || + if (shapeFixedLetters[i] >= (char) 0xD800 && + shapeFixedLetters[i] <= (char) 0xDBFF || shapeFixedLetters[i] >= (char) 0xDC00 && shapeFixedLetters[i] <= (char) 0xDFFF) { ltrText.Add(shapeFixedLetters[i]); @@ -809,7 +841,8 @@ protected virtual void FixLigature(IList shapeFixedLetters) ltrText.Clear(); } - if (shapeFixedLetters[i] != 0xFFFF && shapeFixedLetters[i] != (int) GeneralLetters.ZeroWidthNoJoiner) + if (shapeFixedLetters[i] != 0xFFFF && + shapeFixedLetters[i] != (int) GeneralLetters.ZeroWidthNoJoiner) FinalLetters.Append(shapeFixedLetters[i]); } @@ -826,23 +859,56 @@ protected virtual void FixLigature(IList shapeFixedLetters) /// protected virtual char[] RestoreTashkeel(ICollection letters) { - char[] lettersWithTashkeel = new char[letters.Count + TashkeelLocations.Count]; + var lettersWithTashkeel = new StringBuilder(); int letterWithTashkeelTracker = 0; - foreach (var t in letters) + foreach (char t in letters) { - lettersWithTashkeel[letterWithTashkeelTracker] = t; + lettersWithTashkeel.Append(t); letterWithTashkeelTracker++; - foreach (var hLocation in TashkeelLocations) + + foreach (TashkeelLocation hLocation in TashkeelLocations) { if (hLocation.Position != letterWithTashkeelTracker) continue; - lettersWithTashkeel[letterWithTashkeelTracker] = hLocation.Tashkeel; + + lettersWithTashkeel.Append(hLocation.Tashkeel); letterWithTashkeelTracker++; } } - return lettersWithTashkeel; + /* + * Fix of https://github.com/sorencoder/RTLTMPro/issues/13 + * The workaround is to replace Shadda + Aother Tashkeel with combined form + */ + lettersWithTashkeel.Replace( + ShaddaFatha, + ((char) TashkeelCharacters.ShaddaWithFathaIsolatedForm).ToString()); + + lettersWithTashkeel.Replace( + ShaddaDamma, + ((char) TashkeelCharacters.ShaddaWithDammaIsolatedForm).ToString()); + + lettersWithTashkeel.Replace( + ShaddaKasra, + ((char) TashkeelCharacters.ShaddaWithKasraIsolatedForm).ToString()); + + lettersWithTashkeel.Replace( + ShaddaDammatan, + ((char) TashkeelCharacters.ShaddaWithDammatanIsolatedForm).ToString()); + + lettersWithTashkeel.Replace( + ShaddaKasratan, + ((char) TashkeelCharacters.ShaddaWithKasratanIsolatedForm).ToString()); + + lettersWithTashkeel.Replace( + ShaddaSuperscriptAlef, + ((char) TashkeelCharacters.ShaddaWithSuperscriptAlefIsolatedForm).ToString()); + + // TODO: Probably there is better way of converting string to char[] + var result = new char[lettersWithTashkeel.Length]; + lettersWithTashkeel.CopyTo(0, result, 0, lettersWithTashkeel.Length); + return result; } /// @@ -890,25 +956,40 @@ protected virtual bool IsLeadingLetter(IList letters, int index) letters[index - 1] == (int) GeneralLetters.Thal || letters[index - 1] == (int) GeneralLetters.Ra2 || letters[index - 1] == (int) GeneralLetters.Zeen || - letters[index - 1] == (int) GeneralLetters.PersianZe || + letters[index - 1] == + (int) GeneralLetters.PersianZe || letters[index - 1] == (int) GeneralLetters.Waw || - letters[index - 1] == (int) GeneralLetters.AlefMad || - letters[index - 1] == (int) GeneralLetters.AlefHamza || - letters[index - 1] == (int) GeneralLetters.Hamza || - letters[index - 1] == (int) GeneralLetters.AlefMaksoor || - letters[index - 1] == (int) GeneralLetters.ZeroWidthNoJoiner || - letters[index - 1] == (int) GeneralLetters.WawHamza || - letters[index - 1] == (int) IsolatedLetters.Alef || + letters[index - 1] == + (int) GeneralLetters.AlefMad || + letters[index - 1] == + (int) GeneralLetters.AlefHamza || + letters[index - 1] == + (int) GeneralLetters.Hamza || + letters[index - 1] == + (int) GeneralLetters.AlefMaksoor || + letters[index - 1] == + (int) GeneralLetters.ZeroWidthNoJoiner || + letters[index - 1] == + (int) GeneralLetters.WawHamza || + letters[index - 1] == + (int) IsolatedLetters.Alef || letters[index - 1] == (int) IsolatedLetters.Dal || - letters[index - 1] == (int) IsolatedLetters.Thal || + letters[index - 1] == + (int) IsolatedLetters.Thal || letters[index - 1] == (int) IsolatedLetters.Ra2 || - letters[index - 1] == (int) IsolatedLetters.Zeen || - letters[index - 1] == (int) IsolatedLetters.PersianZe || + letters[index - 1] == + (int) IsolatedLetters.Zeen || + letters[index - 1] == + (int) IsolatedLetters.PersianZe || letters[index - 1] == (int) IsolatedLetters.Waw || - letters[index - 1] == (int) IsolatedLetters.AlefMad || - letters[index - 1] == (int) IsolatedLetters.AlefHamza || - letters[index - 1] == (int) IsolatedLetters.Hamza || - letters[index - 1] == (int) IsolatedLetters.AlefMaksoor; + letters[index - 1] == + (int) IsolatedLetters.AlefMad || + letters[index - 1] == + (int) IsolatedLetters.AlefHamza || + letters[index - 1] == + (int) IsolatedLetters.Hamza || + letters[index - 1] == + (int) IsolatedLetters.AlefMaksoor; bool canThisLetterBeLeading = letters[index] != ' ' && letters[index] != (int) GeneralLetters.Dal && @@ -922,15 +1003,19 @@ protected virtual bool IsLeadingLetter(IList letters, int index) letters[index] != (int) GeneralLetters.AlefMad && letters[index] != (int) GeneralLetters.WawHamza && letters[index] != (int) GeneralLetters.Waw && - letters[index] != (int) GeneralLetters.ZeroWidthNoJoiner && + letters[index] != + (int) GeneralLetters.ZeroWidthNoJoiner && letters[index] != (int) GeneralLetters.Hamza; bool isNextLetterConnectable = index < letters.Count - 1 && IsRTLCharacter(letters[index + 1]) && letters[index + 1] != (int) GeneralLetters.Hamza && - letters[index + 1] != (int) GeneralLetters.ZeroWidthNoJoiner; + letters[index + 1] != + (int) GeneralLetters.ZeroWidthNoJoiner; - return isPreviousLetterNonConnectable && canThisLetterBeLeading && isNextLetterConnectable; + return isPreviousLetterNonConnectable && + canThisLetterBeLeading && + isNextLetterConnectable; } /// @@ -945,32 +1030,43 @@ protected virtual bool IsFinishingLetter(IList letters, int index) letters[index - 1] != (int) GeneralLetters.Thal && letters[index - 1] != (int) GeneralLetters.Ra2 && letters[index - 1] != (int) GeneralLetters.Zeen && - letters[index - 1] != (int) GeneralLetters.PersianZe && + letters[index - 1] != + (int) GeneralLetters.PersianZe && letters[index - 1] != (int) GeneralLetters.Waw && letters[index - 1] != (int) GeneralLetters.Alef && letters[index - 1] != (int) GeneralLetters.AlefMad && - letters[index - 1] != (int) GeneralLetters.AlefHamza && - letters[index - 1] != (int) GeneralLetters.AlefMaksoor && - letters[index - 1] != (int) GeneralLetters.WawHamza && + letters[index - 1] != + (int) GeneralLetters.AlefHamza && + letters[index - 1] != + (int) GeneralLetters.AlefMaksoor && + letters[index - 1] != + (int) GeneralLetters.WawHamza && letters[index - 1] != (int) GeneralLetters.Hamza && - letters[index - 1] != (int) GeneralLetters.ZeroWidthNoJoiner && + letters[index - 1] != + (int) GeneralLetters.ZeroWidthNoJoiner && letters[index - 1] != (int) IsolatedLetters.Dal && letters[index - 1] != (int) IsolatedLetters.Thal && letters[index - 1] != (int) IsolatedLetters.Ra2 && letters[index - 1] != (int) IsolatedLetters.Zeen && - letters[index - 1] != (int) IsolatedLetters.PersianZe && + letters[index - 1] != + (int) IsolatedLetters.PersianZe && letters[index - 1] != (int) IsolatedLetters.Waw && letters[index - 1] != (int) IsolatedLetters.Alef && - letters[index - 1] != (int) IsolatedLetters.AlefMad && - letters[index - 1] != (int) IsolatedLetters.AlefHamza && - letters[index - 1] != (int) IsolatedLetters.AlefMaksoor && - letters[index - 1] != (int) IsolatedLetters.WawHamza && + letters[index - 1] != + (int) IsolatedLetters.AlefMad && + letters[index - 1] != + (int) IsolatedLetters.AlefHamza && + letters[index - 1] != + (int) IsolatedLetters.AlefMaksoor && + letters[index - 1] != + (int) IsolatedLetters.WawHamza && letters[index - 1] != (int) IsolatedLetters.Hamza && IsRTLCharacter(letters[index - 1]); bool canThisLetterBeFinishing = letters[index] != ' ' && - letters[index] != (int) GeneralLetters.ZeroWidthNoJoiner && + letters[index] != + (int) GeneralLetters.ZeroWidthNoJoiner && letters[index] != (int) GeneralLetters.Hamza; return isPreviousLetterConnectable && canThisLetterBeFinishing; @@ -1010,7 +1106,8 @@ protected virtual bool IsMiddleLetter(IList letters, int index) letters[index - 1] != (int) GeneralLetters.AlefMaksoor && letters[index - 1] != (int) GeneralLetters.WawHamza && letters[index - 1] != (int) GeneralLetters.Hamza && - letters[index - 1] != (int) GeneralLetters.ZeroWidthNoJoiner && + letters[index - 1] != + (int) GeneralLetters.ZeroWidthNoJoiner && letters[index - 1] != (int) IsolatedLetters.Alef && letters[index - 1] != (int) IsolatedLetters.Dal && letters[index - 1] != (int) IsolatedLetters.Thal && diff --git a/Scripts/Runtime/TashkeelCharacters.cs b/Scripts/Runtime/TashkeelCharacters.cs index 9bc41c3..a43f023 100644 --- a/Scripts/Runtime/TashkeelCharacters.cs +++ b/Scripts/Runtime/TashkeelCharacters.cs @@ -1,5 +1,7 @@ namespace RTLTMPro { + // Note that if you add to these characters, you also need to define + // characters inside Range file and TextMesh Pro font asset unicode range. public enum TashkeelCharacters { Fathan = 0x064B, @@ -12,8 +14,11 @@ public enum TashkeelCharacters Sukun = 0x0652, MaddahAbove = 0x0653, SuperscriptAlef = 0x670, + ShaddaWithDammatanIsolatedForm = 0xFC5E, + ShaddaWithKasratanIsolatedForm = 0xFC5F, ShaddaWithFathaIsolatedForm = 0xFC60, ShaddaWithDammaIsolatedForm = 0xFC61, - ShaddaWithKasraIsolatedForm = 0xFC61 + ShaddaWithKasraIsolatedForm = 0xFC62, + ShaddaWithSuperscriptAlefIsolatedForm = 0xFC63 } } \ No newline at end of file